软件处理按键消抖(裸机)
1.中断中的初步消抖,软件定时器计时,非阻塞消抖,为每个按键都设置一个独立软件定时器,正常触发后定时器设置10ms非阻塞延时,如果10ms内再次触发同一按键的中断认为无效按键中断,再将该按键的消抖定时器重置为10ms。
2.用户态的数据处理,硬件中断中设置全局变量来传递软中断信号(快进快出,用户态判断),收到特定按键的中断信号后,更新逻辑键值,清除软中断信号;
3.逻辑消抖,收到中断信号后用当前的逻辑键值和上次保存的逻辑键值信息相比较,如果没有变化,则不将逻辑键值向外传输。
4.不同中断源的中断优先级需要有差异,用于做软件定时器时基的systick优先级最高,按键的优先级按重要程度排序,CM3架构有快中断机制,连续两个中断发生时,会跳过中间的恢复堆栈步骤,直接进入第二个中断函数,减小非阻塞中断消抖带来的爆栈风险。
5.传输按键信息时需要阻塞等待信道中上一次信息传输完成。
非阻塞软件定时器的实现:
uint32_t global_time_saver; //软定时器的时基
systick_IRQ() //systick系统时钟定时器
{
++global_time_saver; //软定时器的时基
}
EXIT_IRQ() //按键中断
{
static uint32_t key_timer_saver[2]; //特定按键的软定时器
......
if( global_time_saver - key_timer_saver[0] <10) //按键0的非阻塞软定时器
{
key_timer_saver[0] = global_time_saver;
}else func_0(); //中断内要么内联函数,要么do-while宏,防止中断嵌套爆栈
if( global_time_saver - key_timer_saver[1] <10) //按键1的非阻塞软定时器
{
key_timer_saver[1] = global_time_saver;
}else func_1(); //发送对应按键的软中断信号
......
return;
}
传输阻塞:
volatile uint32_t transfer_completed=1; //传输完成标志,一般在外设的中断函数里更新
main()
{
static transfer_timer; //传输超时软看门狗
......
while(1)
{
if(soft_irq)
{
deal_data();
transfer_timer = global_time_saver ;
while( transfer_completed != 1 || global_time_saver - transfer_timer < 1000);//阻塞等待传输完成
if(global_time_saver - transfer_timer >= 1000) deal_transfer_fault(); //传输超时软看门狗
transfer_completed = 0; //每次传输前将传输完成标志软件清0
transfer_func();
soft_irq =0; //清除软中断
}
}
}
TRANSFER_IRQ() //通信外设的中断
{
if(irq == TRANSMITED) //中断标志位为传输完成中断
{
transfer_completed = 1; //软件置位传输完成标志
......
}
......
}