關(guān)于按鍵消抖或者開關(guān)量信號(hào)監(jiān)測(cè),可以參考本公眾號(hào)的另外一篇原創(chuàng)文章:按鍵消抖常用的軟硬件方法。在該文章中介紹了兩種軟件延時(shí)的方式。但也都各有缺點(diǎn)。
一:舊方案
方案一:純軟件延時(shí)
sbit KEY = P1^3; ///按鍵讀取函數(shù) uint8_t GetKey(void) { if(KEY == 1) { DelayMs(20); //延時(shí)消抖 if(KEY == 1) { return 1; } else { return 0; } } else { return 0; } }致命缺點(diǎn):在延時(shí)的時(shí)候一直占用cpu的資源,如果在延時(shí)的時(shí)候,有其他外部中斷或者搶占事件,系統(tǒng)完全沒有響應(yīng)的
方案二:中斷消抖
此處不在貼出代碼:感興趣的同學(xué)可到文章中查看:按鍵消抖常用的軟硬件方法
致命缺點(diǎn):多占用中斷資源。操作復(fù)雜。在資源就是成本的產(chǎn)品中(多占用一個(gè)中斷可能會(huì)導(dǎo)致需要選擇價(jià)格更高的MCU),這種方案的缺點(diǎn)更加明顯。
推薦方案
本文推薦一種更高效、合適,已在產(chǎn)品中使用過的軟件設(shè)計(jì)方案。直接上代碼。
#include1、函數(shù)詳解:// 定義開關(guān)信號(hào)結(jié)構(gòu)體 typedef struct { bool lastState; // 上次開關(guān)信號(hào)狀態(tài) bool currentState; // 當(dāng)前開關(guān)信號(hào)狀態(tài) bool validState; // 有效的開關(guān)信號(hào)狀態(tài) int debounceDelayCounter; // 開關(guān)信號(hào)消抖計(jì)數(shù)器 } DebouncedSwitch; // 初始化開關(guān)信號(hào)結(jié)構(gòu)體 void initializeSwitch(DebouncedSwitch* switchObj) { switchObj->lastState = false; switchObj->currentState = false; switchObj->validState = false; switchObj->debounceDelayCounter = 0; } // 模擬讀取開關(guān)信號(hào)狀態(tài)的函數(shù) bool readSwitchState() { // 在這里替換為實(shí)際的開關(guān)信號(hào)讀取代碼 // 返回開關(guān)信號(hào)的當(dāng)前狀態(tài)(true表示開,false表示關(guān)) return false; } // 處理開關(guān)信號(hào)消抖的函數(shù) void debounceSwitch(DebouncedSwitch* switchObj, int debounceTime) { // 讀取當(dāng)前開關(guān)信號(hào)狀態(tài) switchObj->currentState = readSwitchState(); // 如果當(dāng)前狀態(tài)與上次狀態(tài)不同,重置計(jì)數(shù)器并更新上次狀態(tài) if (switchObj->currentState != switchObj->lastState) { switchObj->debounceDelayCounter = 0; } else { // 如果狀態(tài)相同,增加計(jì)數(shù)器值 switchObj->debounceDelayCounter++; } // 如果計(jì)數(shù)器達(dá)到指定的消抖時(shí)間,表示開關(guān)信號(hào)狀態(tài)穩(wěn)定 if (switchObj->debounceDelayCounter >= (debounceTime / 10)) { // 如果當(dāng)前狀態(tài)與 validState 不同,表示發(fā)生了有效的狀態(tài)變化 if (switchObj->currentState != switchObj->validState) { switchObj->validState = switchObj->currentState; } } // 更新上次狀態(tài) switchObj->lastState = switchObj->currentState; } int main() { // 創(chuàng)建一個(gè)開關(guān)信號(hào)的DebouncedSwitch結(jié)構(gòu)體 DebouncedSwitch switchObj; initializeSwitch(&switchObj); while (1) { debounceSwitch(&switchObj, 100); // 設(shè)置消抖時(shí)間為100毫秒 if (switchObj.validState) { if (switchObj.validState) { // 執(zhí)行開關(guān)信號(hào)為開的操作 printf("開關(guān)信號(hào)為開 "); } else { // 執(zhí)行開關(guān)信號(hào)為關(guān)的操作 printf("開關(guān)信號(hào)為關(guān) "); } } // 在這里可以添加其他需要執(zhí)行的代碼 // 模擬延時(shí)或等待開關(guān)信號(hào)狀態(tài)變化 // 這里使用usleep函數(shù)來模擬10毫秒的延時(shí) // 實(shí)際上,你需要根據(jù)你的硬件和操作系統(tǒng)來等待開關(guān)信號(hào)狀態(tài)變化 usleep(10000); // 10毫秒 } return 0; }
debounceSwitch函數(shù)該函數(shù)用于處理開關(guān)信號(hào)的消抖,以確保穩(wěn)定的開關(guān)狀態(tài)。 它接受一個(gè)指向 DebouncedSwitch 結(jié)構(gòu)體的指針,該結(jié)構(gòu)體包含了上次狀態(tài)、當(dāng)前狀態(tài)、有效狀態(tài)等信息,以及消抖時(shí)間的設(shè)置。
該函數(shù)的被調(diào)用周期為10ms(可以與產(chǎn)品程序中其他任務(wù)并行執(zhí)行)。
2、函數(shù)的工作流程如下:
1)讀取當(dāng)前開關(guān)信號(hào)狀態(tài)。
2)如果當(dāng)前狀態(tài)與上次狀態(tài)不同,重置計(jì)數(shù)器并更新上次狀態(tài)。
3)如果當(dāng)前狀態(tài)與上次狀態(tài)相同,增加計(jì)數(shù)器值。
4)如果計(jì)數(shù)器達(dá)到指定的消抖時(shí)間,表示開關(guān)信號(hào)狀態(tài)穩(wěn)定。
5)如果當(dāng)前狀態(tài)與 validState 不同,表示發(fā)生了有效的狀態(tài)變化,更新有效狀態(tài)。
6)更新上次狀態(tài)以便下一次比較
3、優(yōu)點(diǎn)介紹:
1)擴(kuò)展性:
debounceSwitch該函數(shù)使用結(jié)構(gòu)體指針的形式,提供了開關(guān)量檢測(cè)的框架,需要多個(gè)開關(guān)量/按鍵檢測(cè)時(shí),實(shí)例化對(duì)應(yīng)的按鍵變量即可。例如:main函數(shù)的示例中實(shí)例化了switchObj,多有多個(gè)按鍵可以多定義不同的switchObj即可。如下:代碼所展示:
DebouncedSwitch switchObj_key1;
DebouncedSwitch switchObj_key2;
//其他代碼
debounceSwitch(&switchObj_key1, 100);
debounceSwitch(&switchObj_key2,50);
2、高度可定制:
debounceSwitch函數(shù)中的消抖時(shí)間是作為參數(shù)傳遞的,這使得消抖時(shí)間可以根據(jù)不同的開關(guān)信號(hào)或應(yīng)用場(chǎng)景進(jìn)行定制。這種可定制性允許您在不同情況下使用不同的消抖時(shí)間,以滿足特定需求。
3、適用于實(shí)時(shí)系統(tǒng):
相對(duì)于純軟件延時(shí)消抖,debounceSwitch函數(shù)是更可靠的,因?yàn)樗灰蕾囉谲浖难訒r(shí),而是基于實(shí)際的狀態(tài)變化來判斷開關(guān)信號(hào)的穩(wěn)定性。這使得它適用于實(shí)時(shí)系統(tǒng)和對(duì)時(shí)間精度要求較高的應(yīng)用。
總結(jié)
當(dāng)然,作為一個(gè)產(chǎn)品中使用的函數(shù)還有很多可優(yōu)化的空間,比如:函數(shù)內(nèi)判斷指針不為空。進(jìn)行參數(shù)的有效性檢查等等。
審核編輯:湯梓紅
-
開關(guān)量
+關(guān)注
關(guān)注
2文章
169瀏覽量
15071 -
源碼
+關(guān)注
關(guān)注
8文章
641瀏覽量
29216 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4331瀏覽量
62629 -
按鍵消抖
+關(guān)注
關(guān)注
2文章
27瀏覽量
10452
原文標(biāo)題:共享一個(gè)產(chǎn)品中使用的按鍵消抖/開關(guān)量監(jiān)測(cè)函數(shù)(附源碼,可移植)
文章出處:【微信號(hào):玩轉(zhuǎn)單片機(jī)與嵌入式,微信公眾號(hào):玩轉(zhuǎn)單片機(jī)與嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論