基于STM32按键的防抖和松开处理:状态机

用延时和while();去处理按键很浪费资源,这里我们用定时器来做一个按键的处理-状态机;
【基于STM32按键的防抖和松开处理:状态机】typedef enum {KEY_RELEASED,KEY_PRESSED,KEY_PROCESSED}KEY_STATUS;//释放按下处理过的typedef struct {uint8_tbyCounter;//按键是否有效KEY_STATUS eKeyStatus;//按键状态}KEY_ATTRIB;KEY_ATTRIB Key_up,Key0,Key1,Key2;
首先我们定义了一个枚举,里面有三个元素,这个三个元素代表按键的三种状态 。,按键松开状态,,按键按下状态
,按键已被处理状态
然后我们在定义一个结构体,里面有两个类型一个按键检测标志(后面我们将通过这个标志来防抖及松开判断),一个为该按键当前状态 。
定义四个按键,Key0,Key1,Key2
我们用的硬件为原子的阿波罗开发板,芯片是,上面有四个按键
这里我们将四个按键连接的引脚配置为输入,然后在开一个定时器4,周期为10ms 。在将串口2打开 。
这是我们的定时器回调函数
void HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim){if (htim->Instance == htim4.Instance){Key_up.byCounter <<= 1;Key0.byCounter<<= 1;Key1.byCounter<<= 1;Key2.byCounter<<= 1;if ( HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==1)//KEYUP{Key_up.byCounter++;if (Key_up.byCounter==0xff)//检测按键是否有效{if (Key_up.eKeyStatus != KEY_PROCESSED)//判断是否为处理过的按键Key_up.eKeyStatus = KEY_PRESSED;//标记为一个未处理的按键}}else{if ((Key_up.byCounter == 0x00)&&(Key_up.eKeyStatus == KEY_PROCESSED))Key_up.eKeyStatus = KEY_RELEASED;//标记为一个被释放的按键}if ( HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3)==0)//KEY0{Key0.byCounter++;if (Key0.byCounter==0xff)//检测按键是否有效{if (Key0.eKeyStatus != KEY_PROCESSED)//判断是否为处理过的按键Key0.eKeyStatus = KEY_PRESSED;//标记为一个未处理的按键}}else{if ((Key0.byCounter == 0x00)&&(Key0.eKeyStatus == KEY_PROCESSED))Key0.eKeyStatus = KEY_RELEASED;//标记为一个被释放的按键}if ( HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2)==0)//KEY1{Key1.byCounter++;if (Key1.byCounter==0xff)//检测按键是否有效{if (Key1.eKeyStatus != KEY_PROCESSED)//判断是否为处理过的按键Key1.eKeyStatus = KEY_PRESSED;//标记为一个未处理的按键}}else{if ((Key1.byCounter == 0x00)&&(Key1.eKeyStatus == KEY_PROCESSED))Key1.eKeyStatus = KEY_RELEASED;//标记为一个被释放的按键}if ( HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13)==0)//KEY2{Key2.byCounter++;if (Key2.byCounter==0xff)//检测按键是否有效{if (Key2.eKeyStatus != KEY_PROCESSED)//判断是否为处理过的按键Key2.eKeyStatus = KEY_PRESSED;//标记为一个未处理的按键}}else{if ((Key2.byCounter == 0x00)&&(Key2.eKeyStatus == KEY_PROCESSED))Key2.eKeyStatus = KEY_RELEASED;//标记为一个被释放的按键}}}
在tim4的回调函数里我们将四个按键的向左1移动一位 。
然后当有按键按下,比如键按下,
开始自增 。
第一次进回调函数,
.左移一位,.值为0(初始默认为0)
然后.自增,
.为0x01,
第二次进入回调函数
.左移一位,.值为0x02
然后.自增,
.为0x03,
以此类推,第八次进入回调函数时.自增后为0xff,这时我们就判定他为有效按键,这样其实就是我们的防抖为80ms,在这里我们目前先将按键模式规定为按下后必须松开,再次按下才行,这样当我们判定为有效按键时,我们接着判断是不是一个处理过的按键,不是OK,标记为新的按键
if (. != )//判断按键是否被处理过
. = ;//标志为一个未处理的按键
然后当松开按键,因为每次进回调函数,都会左移,所以松开按键80ms后
会为0,也就是松开的防抖80ms 。我们再去判断一下按键被处理了没,处理了就将按键标记为释放(其实这个也可以不用判断处理了没,当为0我们就可以直接标记为释放,因为80ms,对于芯片算很长一段时间了) 。