按键检测
CubeMX的操作
普通按键检测的I/O口设置
- 将按键对应的I/O口设置为输入模式。
- 如果按键使用上拉电阻则设置I/O口为上拉电阻,如果按键使用的是下拉电阻则设置I/O口味下拉电阻。
外部中断按键检测的I/O口设置
- 将按键对应的I/O口设置为EXTI模式,并打开外部中断。
- 如果按键使用上拉电阻则设置I/O口为上拉电阻,如果按键使用的是下拉电阻则设置I/O口味下拉电阻。
注意,该配置的I/O口也可以使用普通的按键检测。
Keil5的操作
普通按键检测
- 检测按键是否按下。
- 执行按键按下后应该执行的操作。
- 开始新一轮的按键检测。
软件去抖的按键检测
- 检测按键是否按下。
- 延时一小段时间(10~30ms),去除抖动,再次检测按键是否按下。
- 执行按键按下后应该执行的操作。
- 检测是否松开了按键,如果是,则开始新一轮的按键检测,如果不是,则等待松手,松手后再进行新一轮的按键检测。
如果是编写一个按键检测函数,可以在第3步检测到后将标志变量变为有效,而不是真的去执行应该执行的操作。
按键检测函数例程:
/**
* @brief 检测按键是否按下
* @param Key_Port是按键对应的IO口端口;Key_Pin是按键对应的IO口编号;Level是按键按下对应的电平状态
* @retval 如果按下返回1,如果没有按下返回0
*/
uint16_t Key_Detection(GPIO_TypeDef * Key_Port, uint16_t Key_Pin, GPIO_PinState Level)
{
uint16_t Key_State = 0;
if(Level == HAL_GPIO_ReadPin(Key_Port,Key_Pin))
{
HAL_Delay(15);
if(Level == HAL_GPIO_ReadPin(Key_Port,Key_Pin))
{
Key_State = 1;
}
while(Level == HAL_GPIO_ReadPin(Key_Port,Key_Pin));
}
return Key_State;
}
外部中断的按键检测
- 在左侧的工程界面中找到用户应用文件夹下的"stm32f1XX_it.c"文件打开,这个文件就是专门存放处理中断的函数的。
- 在该文件中搜索EXTI,即可找到处理对应中断的中断服务函数,每个中断服务函数都调用了同一个函数,该函数会完成中断检测、中断标志位的清除、并调用回调函数。
- 找到回调函数"HAL_GPIO_EXTI_Callback",去除前面的"weak"标记,并把整个函数复制到自己的.c文件或是"stm32f1XX_it.c"文件中进行使用。
应当注意,所有的外部中断使用同一个回调函数,通过传入参数(IO口编号)的不同来分辨是哪个外部中断被触发。另外,外部中断无法去抖,一般单片机的外部中断输入段都会进行硬件去抖,但如果它还无法消抖,那就自己对按键进行硬件消抖。
按键检测并亮灯的例程:
/**
* @brief 这是外部中断的回调函数,功能为按键控制LED灯,并保存灯的亮灭状态。
* 使用之前需要将三个按键分别设置别名“Key1”、“Key2”和“Key3”,LED设置为“Led2”和"Led3"。
* 按键1控制LED2,按键2控制LED3,按键3熄灭两盏LED。
* 两个外部变量是用来记录LED灯状态的,应该放在主函数所在文件中作为全局变量。
*/
>extern uint16_t led2_state, led3_state;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == Key1_Pin)
{
if(1 == led2_state)
{
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
led2_state=0;
}
else if(0 == led2_state)
{
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET);
led2_state=1;
}
}
if(GPIO_Pin == Key2_Pin)
{
if(1 == led3_state)
{
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
led3_state=0;
}
else if(0 == led3_state)
{
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET);
led3_state=1;
}
}
if(GPIO_Pin == Key3_Pin)
{
led2_state = 0;
led3_state = 0;
HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET);
}
}