1、硬件设计
按键机械触点断开、闭合时,由于按键触点的弹性作用,按键开关不会马上稳定接通或一下就断开,使用按键时就会产生下图中的带纹波信号,需要软件消抖处理滤波
由于用软件消抖处理滤波不方便输入检测,所以提出了如下带有硬件消抖的电路。
从按键的原理图可知,当按键没有被按下时,GPIO引脚通过一个下拉电阻R64使引脚处于低电平状态,当按键被按下时,按键所在的电路导通,VCC通过一个限流电阻R33连接到GPIO引脚,使GPIO引脚的输入状态为高电平,只要我们检测引脚的输入电平为高电平,即可判断按键是否被按下。
同LED工程,为了使工程的移植性更高,是工程更有条理,我们把按键相关的代码独立分开存储,在工程模板上新建“bsp_key.c”及“bsp_key.h”,这些文件可由自己的喜好命名,这些文件不属于STM32标准库的内容,是根据自己的需要编写的。
bsp_keyscan.c中代码如下
#include "bsp_keyscan.h"
/**
* @brief 配置按键检测用到的I/O口
* @param 无
* @retval 无
*/
void key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_key_InitStructure;
RCC_AHB1PeriphClockCmd(key1_GPIO_CLK, ENABLE); //enable AHB1 periphral clock
RCC_AHB1PeriphClockCmd(key2_GPIO_CLK, ENABLE); //enable AHB1 periphral clock
GPIO_key_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_key_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_key_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_key_InitStructure.GPIO_Speed = GPIO_Fast_Speed; //keyscan gpio port register configure
GPIO_key_InitStructure.GPIO_Pin = key1_pin;
GPIO_Init(key1_GPIO_PORT,&GPIO_key_InitStructure); //Initializes the gpio according to the specified parameters in the GPIO_key_InitStructure
RCC_AHB1PeriphClockCmd(key2_GPIO_CLK, ENABLE); //enable AHB1 periphral clock
GPIO_key_InitStructure.GPIO_Pin = key2_pin;
GPIO_Init(key2_GPIO_PORT,&GPIO_key_InitStructure); //Initializes the gpio according to the specified parameters in the GPIO_key_InitStructure
}
/**按键按下标志宏
*按按键按下为高电平,设置KEY_ON = 1 , KEY_OFF = 0
*若按键按下为低电平,设置KEY_ON = 0 , KEY_OFF = 1 即可
*/
/**
* @brief 检测是否有按键按下
* @param GPIOx:具体的端口,x可以是(A...K)
* @param GPIO_PIN:具体的端口位,可以是GPIO_PIN_x(x可以是0...15)
* @retval 按键的状态
* @arg KEY_ON :按键按下
* @arg KEY_OFF :按键没按下
*/
uint8_t Key_Scan(GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin )
{
if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON) //Detect whether the key is pressed
{
while(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON); //Loosen the detection
return KEY_ON;
}
else
{
return KEY_OFF;
}
}
第一个函数是按键GPIO初始化函数,初始化的流程与LED GPIO 初始化函数 类似,主要区别是引脚的模式。函数执行流程如下:
(1) 使用 GPIO_InitTypeDef 定义 GPIO 初始化结构体变量,以便下面用于存储 GPIO 配置。
(2) 调用库函数 RCC_AHB1PeriphClockCmd 来使能按键的 GPIO 端口时钟。
(3) 向 GPIO初始化结构体赋值,把引脚初始化成浮空输入模式,其中的 GPIO_Pin 使用宏“KEYx_PIN”来赋值,使函数的实现方便移植。由于引脚的默认电平受按键电路影响,所以设置成“浮空/上拉/下拉”模式均没有区别。
(4) 使用以上初始化结构体的配置,调用 GPIO_Init 函数向寄存器写入参数,完成 GPIO的初始化,这里的 GPIO 端口使用“KEYx_GPIO_PORT”宏来赋值,也是为了程序移植方便。
(5) 使用同样的初始化结构体,只修改控制的引脚和端口,初始化其它按键检测时使用的GPIO引脚 第二个函数是按键扫描函数,在这里我们定义了一个 Key_Scan 函数用于扫描按键状态。GPIO引脚的输入电平可通过读取 IDR 寄存器对应的数据位来感知,而 STM32 标准库提供了库函数GPIO_ReadInputDataBit 来获取位状态,该函数输入 GPIO端口及引脚号,函数返回该引脚的电平状态,高电平返回 1,低电平返回 0。Key_Scan 函数中以 GPIO_ReadInputDataBit 的返回值与自定义的宏“KEY_ON”对比,若检测到按键按下,则使用 while 循环持续检测按键状态,直到按键释放,按键释放后 Key_Scan函数返回一个“KEY_ON”值;若没有检测到按键按下,则函数直接返回“KEY_OFF”。若按键的硬件没有做消抖处理,需要在这个 Key_Scan函数中做软件滤波,防止波纹抖动引起误触发。
bsp_keyscan.h的代码如下
#ifndef _BSP_KEYSCAN_H
#define _BSP_KEYSCAN_H
#include "stm32f4xx.h"
/*************************引脚定义***********************/
#define key1_pin GPIO_Pin_0
#define key1_GPIO_PORT GPIOA
#define key1_GPIO_CLK RCC_AHB1Periph_GPIOA
#define key2_pin GPIO_Pin_13
#define key2_GPIO_PORT GPIOC
#define key2_GPIO_CLK RCC_AHB1Periph_GPIOC
#define KEY_ON 1
#define KEY_OFF 0
void key_GPIO_Config(void);
uint8_t Key_Scan(GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin );
#endif
以上代码根据按键的硬件连接,把检测按键输入的 GPIO端口、GPIO引脚号以及GPIO端口时钟封装起来.
主函数代码如下
#include "stm32f4xx.h"
#include "bsp_led.h"
#include "bsp_keyscan.h"
int main (void)
{
LED_Config();
key_GPIO_Config();
while(1)
{
if(Key_Scan(key1_GPIO_PORT,key1_pin) == KEY_ON )
{
LED_R_Toggle;
}
if(Key_Scan(key2_GPIO_PORT,key2_pin) == KEY_ON )
{
LED_B_Toggle;
}
}
}
编译运行后,按下KEY1则红灯状态改变,按下KEY2蓝灯状态改变一次
上一篇:STM32 的位带操作
下一篇:stm32f4固件库函数点亮LED灯
推荐阅读最新更新时间:2024-03-16 16:24
设计资源 培训 开发板 精华推荐
- 再续点评Vishay视频 抢楼拿奖进行到底
- 有奖直播|安森美高能效产品在 EV-Charger 市场的应用
- 五一活动上线!动动手,一起来场旧物\"劳动\"大改造吧
- 下载Mentor白皮书,迎接电路板与晶片日益复杂的设计挑战,还有好礼相送哟!
- 留下你的点评,是德科技信号分析仪,精美礼品等你拿!
- 点评下载资料,参加幸运抽奖,让我们迈开技术交流分享的步伐!!
- ADI 网络化电机控制解决方案
- ADI有奖下载活动之25:ADI汽车传感器和传感器接口解决方案
- 考眼力:高速数字设计的秘籍 藏在哪里? 走近Keysight PATHWAVE,提升工作效率
- 注册有礼 | 施耐德电器邀请您参加EP23上海国际电力电工展线上云逛展