关于stm32短按,长按,双击的处理(基于蓝桥杯嵌入式 stm g431)
基于网上学习,自我总结理解如下:
按键简介
按键工作原理
按键(轻触开关)常用于用户输入、模式切换、功能选择等场景。其由弹簧片和触点组成,按下时可以实现电路的闭合。按下时接通电路,松开时断开。
其常常搭配上拉或下拉电阻使用,搭配上拉电阻时,其接在近地侧,抬起时信号线高电平,按下拉低信号线;搭配下拉电阻时,其接在近电源侧,抬起时信号线低电平,按下拉高信号线。
开发板按键电路:
由此可知在此块开发板的按键为上拉电阻,即没有按时为高电平(1),按下则为低电平(0)。
GPIO输入的CubeMX配置和HAL库使用
经过前述分析,可知按键相关引脚连接和配置要求如下:
按键 |
对应引脚 |
配置 |
配置后效果 |
KEY1 |
PB0 |
上拉输入 |
默认高定平,按下低电平 |
KEY2 |
PB1 |
上拉输入 |
默认高定平,按下低电平 |
KEY3 |
PB2 |
上拉输入 |
默认高定平,按下低电平 |
KEY4 |
PA0 |
下拉输入 |
默认低定平,按下高电平 |
在CubeMX配置文件的GPIO配置中确认相关配置:
HAL库的引脚状态读取API:
/**
* @brief Reads the specified input port pin.
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
* @param GPIO_Pin: specifies the port bit to read.
* This parameter can be GPIO_PIN_x where x can be (0..15).
* @retval The input port pin value.
*/
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
随后关于按键read函数(其中分析有点复杂,本博主就不解释):
uint8_t key_value,key_down,key_up,key_old;
void KEY_Read(void)
{
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==0) key_value=1;
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==0) key_value=2;
else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==0) key_value=3;
else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==0) key_value=4;
else key_value=0; //默认为0
key_down=key_value&(key_value^key_old);
key_up=~key_value&(key_value^key_old);
key_old=key_value;
}
main.c:
void KEY_Proc(void)
{
if(uwTick-Key_Tick<20) //官方建议20ms
return;
Key_Tick=uwTick;
KEY_Read();
关于短按(这个不解释,都看得懂):
//按键的短按处理
if(key_up==1) {}
else if(key_up==2) {}
else if(key_up==3) {}
else if(key_up==4) {}
关于长按:
本博主自我理解示意图(字可能不太好看…..):
即当按键按下时,高电平变为低电平,此时将定义长按的tick等于uwtick(即清零开始计算),再然后如果按键值还是按下的值并且超过800ms(普遍认为长按为800ms),则进行长按的实现函数
注意:若短按为按下触发的话(不是抬起触发),则长按和短按都会执行,所以注意!!!!
代码:
else if(key_down== 1||key_down== 2||key_down==3||key_down==4)
{
long_Tick=uwTick;
}
if(key_value==1&&(uwTick-long_Tick>800))
{
time++;
}
else if(key_value==2&&(uwTick-long_Tick>800))
{
time--;
}
else if(key_down==3&&(uwTick-long_Tick>800))
{
}
else if(key_down==4&&(uwTick-long_Tick>800))
{
}
关于双击:
本博主自我理解示意图(字可能不太好看…..):
即当按键第一次按下时,按键1的计数值=1,然后在此条件下,若按键1又按下了,且没有超过300ms(普遍认为300ms以内为双击所花费时间),则进行双击任务函数,若大于300ms则进行单按操作。
注意:这样会与前面的单按给混在一起,所以需要自我进行小修改;而且,双击这里的单按触发会比短按稍微慢一些些,可以看的出来。
代码:
if(key_down==1&&key_num_1==0)
{
key_num_1=1;
double_Tick=uwTick;
}
else if(key_num_1==1)
{
if(key_down==1&& uwTick - double_Tick<300)
{
key_num_1=0;
time=10;
}
else if(uwTick-double_Tick>300)
{key_num_1=0;}
}
总结:
短按长按双击都可以很方便的使用内部定时器来这样执行,同时其他模块亦是如此,都万变不离其宗。
(本人学生,若有问题,大家可以相互交流学习,共同发展)
作者:学嵌入式的小白_1