按键消抖之 同步 异步 阻塞 非阻塞(基于STM32)
同步、异步:通讯方式
阻塞、非阻塞:等待状态
老张爱喝茶,废话不说/煮开水。
出场人物:老张,水壶两把(普通氷壶,简称水壶,•会响M水壶,简称响氷壶)
1、老张把水壶放到火上,立等水开,(同步阻塞 )
老张觉得自己有点傻
2、老张把水誠到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)
老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀----的噪音^
3、老张把响水壶放到火上,立等水开。(异步阻塞)
老张觉得这样傻等意义不大
4、老张把响水壶放到火上,去客厅看电视,7_)<壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)
老张觉得自己聪明了。
按键消抖
需要消抖的原因
触点按键(电平按键/AD按键)一般是由机械弹性开关,当机械按键触点断开、闭合时,由于机械触点的弹性作用,所以按键开关在闭合时不会马上就稳定的接触,在断开时也不会马上一下子就彻底断开,而是在闭合及断开的瞬间均伴随有一连串的抖动,键抖动会引起一次按键被误读多次。按键稳定闭合时间长短一般是由按键操作人员来决定,一般会在100ms时间以上,如果刻意的快速按下按键的话,有可能达到40~50ms时间左右。而抖动的时间是由按键的机械特性决定,一般会在10ms时间以内。为了确保CPU对按键的一次闭合仅作一次处理,所以必须去除抖动。按键去抖的核心理念是,当检测到按键状态变化时,不是立即去响应按键工作,而是先等待按键闭合或按键断开彻底稳定后再对按键进行处理。
消抖方式
软件消抖有两种:
延时消抖:运行效率不高、CPU空转、不能放到中断服务函数;
对比消抖(非阻塞IO):运行效率高、不会造成CPU空转、可放在中断服务函数中;
其中,值得格外注意的是PA0、PE4、PE3引脚外接的是上拉电阻,按键未按下时引脚为高电平。PE2引脚外接下拉电阻,按键未按下式引脚为低电平。按键按下各引脚电平反向。这在下面代码中也有所体现。
代码实现
/*按键消抖*/
/**************************
*函 数 名:unsigned char KEY_Scanf(void)
*函数功能:按键扫描函数(对比消抖)
*参 数:无
*返 回 值:按键值
记录3---5次
***************************/
unsigned char KEY_Scanf(void)
{
unsigned char return_value =0; //返回值承载变量
static unsigned char KEY_1,KEY_2,KEY_3,Count=0,Free_Flag=0;
/*传值操作*/
KEY_3 = KEY_2;
KEY_2 = KEY_1;
/*记录次数*/
Count++;
/*判断按键按下----->检测IO口--->电平*/
if((Free_Flag==0)&&((GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2))||(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))||(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4))||(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3))))
{
if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)){
KEY_1 = Key_left; //左键按下
}
else if(!GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)){
KEY_1 = Key_up; //上键按下
}
else if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)){
KEY_1 = Key_right; //右键按下
}
else if(!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)){
KEY_1 = Key_down; //下键按下
}
if(Count >3){ //记录三次
Count = 0;
if((KEY_1==KEY_2)&&(KEY_3=KEY_1)){
return_value = KEY_1; //改变返回值变量
Free_Flag =1; //产生自锁
}
}
}
/*检测抬起*/
else if((!GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2))&&GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)&&GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)&&GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3))
{
Count=0;
Free_Flag=0;
}
return return_value;
}