程序框架的构建
一、需求分析
二、程序框架
三、按键消抖
详细解析都在注释里了:
/*
* 函数名:KeyShakeProcess_Callback
* 功能:处理按键消抖的回调函数,会在Systick的1ms中断服务函数中调用
* 输入参数:无
* 输出参数:无
* 返回值:无
*/
void KeyShakeProcess_Callback(void)
{
KeyEvent nKeyEvent = {0};//初始化表示按键信息的结构体。
static uint32_t press_time = 0;//按下时刻的tick时间
static uint32_t release_time = 0;//松开时刻的tick时间
uint32_t tick = HAL_GetTick();
if(tick == KeyTrigerTime)
{ //因为整个函数是放在SysTick_Handler(void)中的,每1ms进入一次这个中断,tick值加1
//当tick值增长到KeyTrigerTime时,也即通过了消抖判断,真正地按下/松开了,才继续后续的判断
//换句话说,就是当有按键按下时,KeyTrigerTime为此时的HAL_GetTick()值加上用于消抖延迟的50ms。
//而由于tick=HAL_GetTick();那么tick值随着滴答中断不断地增长,并且每次滴答中断里都会判断tick值是否等于KeyTrigerTime,
//如果没有按键按下的话,KeyTrigerTime = 0初始值。不满足判断条件,什么都不做。
//如果有按键按下,按下的瞬间,触发EXTI0中断,KeyTrigerTime = 此时HAL_GetTick()值+50,此时的tick值也等于HAL_GetTick(),即 KeyTrigerTime比tick大50,仍然判断tick是否与KeyTrigerTime相等,显然不相等。
//而滴答中断每1ms都会使tick加1,tick在不断增长,而KeyTrigerTime的值在按下的瞬间就已经确定,是定值了。
//不过,这也就达到了消抖的目的,即在按键按下或松开的那一瞬间不去读按键IO口的电平,而是在延迟50个tick之后,50个tick之后,tick增加到与 KeyTrigerTime相等,满足判断条件,这之后再读取按键IO口的电平,从而达到了消抖的目的。
if(KEY_STATE() == 0) // press
{
press_time = tick; //如果按键按下,记录按下时的tick值
}
else // release
{
release_time = tick; //如果按键松开,记录松开时的tick值
}
// if(release_time != 0 && release_time < press_time)
// {
// release_time = press_time = 0; //如果松开时刻的tick值不为0 且 松开时刻的tick值小于按下时刻的tick值,说明
// }
if(press_time != 0 && release_time != 0)
{
nKeyEvent.num = 1;
nKeyEvent.time = release_time - press_time; //给存储按键信息的结构体的成员赋值
release_time = press_time = 0; //并清空松开和按下时刻的tick值
Driver_Buffer_WriteBytes(&KeyBuffer, (uint8_t*)&nKeyEvent.num, sizeof(KeyEvent));//将按键的序号写到环形缓冲区
}
}
}
训练营导航:www.100ask.net