軟件處理按鍵消抖(裸機(jī))
1.中斷中的初步消抖,軟件定時器計(jì)時,非阻塞消抖,為每個按鍵都設(shè)置一個獨(dú)立軟件定時器,正常觸發(fā)后定時器設(shè)置10ms非阻塞延時,如果10ms內(nèi)再次觸發(fā)同一按鍵的中斷認(rèn)為無效按鍵中斷,再將該按鍵的消抖定時器重置為10ms。
2.用戶態(tài)的數(shù)據(jù)處理,硬件中斷中設(shè)置全局變量來傳遞軟中斷信號(快進(jìn)快出,用戶態(tài)判斷),收到特定按鍵的中斷信號后,更新邏輯鍵值,清除軟中斷信號;
3.邏輯消抖,收到中斷信號后用當(dāng)前的邏輯鍵值和上次保存的邏輯鍵值信息相比較,如果沒有變化,則不將邏輯鍵值向外傳輸。
4.不同中斷源的中斷優(yōu)先級需要有差異,用于做軟件定時器時基的systick優(yōu)先級最高,按鍵的優(yōu)先級按重要程度排序,CM3架構(gòu)有快中斷機(jī)制,連續(xù)兩個中斷發(fā)生時,會跳過中間的恢復(fù)堆棧步驟,直接進(jìn)入第二個中斷函數(shù),減小非阻塞中斷消抖帶來的爆棧風(fēng)險。
5.傳輸按鍵信息時需要阻塞等待信道中上一次信息傳輸完成。
非阻塞軟件定時器的實(shí)現(xiàn):
uint32_t global_time_saver;????//軟定時器的時基
systick_IRQ()????//systick系統(tǒng)時鐘定時器
{
????++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();????//中斷內(nèi)要么內(nèi)聯(lián)函數(shù),要么do-while宏,防止中斷嵌套爆棧
???? if( global_time_saver - key_timer_saver[1]? <10)????//按鍵1的非阻塞軟定時器
???? {
???????? key_timer_saver[1] = global_time_saver;
???? }else?func_1();????//發(fā)送對應(yīng)按鍵的軟中斷信號
???? ......
???? return;
}
傳輸阻塞:
volatile uint32_t transfer_completed=1;????//傳輸完成標(biāo)志,一般在外設(shè)的中斷函數(shù)里更新
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;????//每次傳輸前將傳輸完成標(biāo)志軟件清0????????
????????????transfer_func();
????????????soft_irq?=0;????????//清除軟中斷
????????}
????}
}
TRANSFER_IRQ()????//通信外設(shè)的中斷
{
????if(irq == TRANSMITED)????//中斷標(biāo)志位為傳輸完成中斷
???? {
???????? transfer_completed = 1;????//軟件置位傳輸完成標(biāo)志
???????? ......
???? }
???? ......
}