標題: [失敗]狀態(tài)機+事件驅(qū)動 按鍵掃描 [打印本頁]
作者: 王朗的誘惑 時間: 2018-10-9 10:48
標題: [失敗]狀態(tài)機+事件驅(qū)動 按鍵掃描
首先說明:這是一個失敗的按鍵掃描程序。它的前身是機智云的STM32按鍵掃描代碼。
不管是用什么芯片,按鍵掃描的延時去抖總是令人心痛,費CPU費電費時間,于是各種各樣好玩有趣的按鍵掃描代碼誕生了。就比如我曾經(jīng)下載的這個機智云的代碼,使用狀態(tài)機+事件驅(qū)動,看起來非常漂亮。
使用狀態(tài)機和一個定時器,就可以去除消抖延時,提高按鍵掃描效率,還可以在里面添加各種各樣的功能判斷,好處說不完吶。
而事件驅(qū)動,把按鍵和按鍵對應的功能隔離開,使用函數(shù)指針連接,這樣分隔開了按鍵掃描和事件處理。回想起多級菜單,每一級菜單按鍵功能都不一樣,處理起來簡直就是噩夢。如果用事件機制來做的話,就可以通過函數(shù)指針動態(tài)改變按鍵功能,終于把重復混亂的變量和代碼送進了回收站。
最近放假實在是心動,我想,如果能把它用在51上該多好呀,于是乎就動手了。但是當我興沖沖地把它改了好半天,終于用在51上的時候,程序直接掛掉了——51速度太慢,消抖檢測周期內(nèi)不能跑完回調(diào)函數(shù),于是就會死機。
實驗環(huán)境是STC12C5A60S2 11.0592MHz 代碼8級優(yōu)化
對于51單片機來說,這個程序致命的缺點:
1. 51速度不夠,如上所述。我試著把KeyHandle函數(shù)里后三個功能的檢測注釋掉,就不會死機了。但是這不是寫這段程序的初衷,所以不能這么做。
2. 51內(nèi)存不夠。這段程序在定義4個按鍵3個事件的時候RAM占用量就過百了,看著51那可憐巴巴的128字節(jié)RAM,我都有點不忍了。至于STC自帶的擴展的RAM,速度實在是不夠,如果定義到xdata,回調(diào)函數(shù)里很簡短的操作都會死機。
結(jié)果是失敗了,芯片配置不行,但是代碼還是很有趣的。雖然下面說的這些因為51的速度被限制了,但是我還是想說一說,都是實際問題。
以往的按鍵掃描,按鍵IO口要用sbit或者#define,離掃描函數(shù)隔得老遠,16進制鍵碼還得自己算,算錯了就不響應,功能函數(shù)就更不忍直視了,和消抖攪和在一起……
再看這個按鍵掃描:
1. 按鍵IO直接在初始化函數(shù)里用字符串輸入,支持任意IO口連接的矩陣鍵盤和單線開關(guān)按鍵。
- void KeyInit(void) //按鍵掃描初始化
- {
- SingleKey[EnumKey_Left].IOPort1 = "P34"; SingleKey[EnumKey_Left].IOPort2 = "P30"; //注冊按鍵 Port1必須是IO口 Port2是IO口或"GND"
- SingleKey[EnumKey_Right].IOPort1 = "P35"; SingleKey[EnumKey_Right].IOPort2 = "P30";
- SingleKey[EnumKey_Up].IOPort1 = "P36"; SingleKey[EnumKey_Up].IOPort2 = "P30";
- SingleKey[EnumKey_Down].IOPort1 = "P37"; SingleKey[EnumKey_Down].IOPort2 = "P30";
- ...
復制代碼 矩陣鍵盤不一定要接在一個8
位的整組IO
上。對于40
腳直插的單片機來說,這反而復雜了些。但是呢,看看那些一不丟丟的小可憐單片機,比如STC15W408AS
的16腳封裝,一組完整引出的IO
都沒有,要是在這樣的單片機上用傳統(tǒng)的方式應用4x4
的矩陣鍵盤,那處理起來可難受死了……
10.png (71.78 KB, 下載次數(shù): 53)
下載附件
2021-9-14 20:07 上傳
2. 按鍵編碼就是從0開始到最大按鍵支持數(shù)量-1 ,放在一個enum枚舉里面,鍵碼就是移位,不用算,直接復制粘貼就可以。還需要把下面#define的按鍵成員總數(shù)也一起改了,注意不要超過最大值,最大值在KeyScan.h里定義,如果有需要可以修改。
- enum EnumUserKey //按鍵編號和鍵值枚舉 編號從0開始 不得超過(KEY_MAX_NUMBER-1)
- {
- EnumKey_Up = 0, EnumKey_Up_TriggerValue = 1<<EnumKey_Up,
- EnumKey_Down = 1, EnumKey_Down_TriggerValue = 1<<EnumKey_Down,
- EnumKey_Left = 2, EnumKey_Left_TriggerValue = 1<<EnumKey_Left,
- EnumKey_Right = 3, EnumKey_Right_TriggerValue = 1<<EnumKey_Right
- };
復制代碼
3. 功能函數(shù)作為事件單獨定義,我改進了一下原來的代碼,讓功能和按鍵互相獨立,用戶自定義觸發(fā)方式或按鍵組合,再用函數(shù)指針連接想要觸發(fā)的事件,邏輯簡潔清晰。
還需要把上面#define的用戶自定義的功能總數(shù)一起改了,就是KeyFuncs成員的數(shù)量,不一定和事件函數(shù)或者按鍵數(shù)量一致,只要內(nèi)存夠用,想要多少就要多少。
- void Key7ShortPressEvent(void)
- {
- static u8 i=0;
- i = (i+1)%CountOfArray(table);
- display(i);
- }
- void Key12ShortPressEvent(void)
- {
- static u8 i=0;
- i = (i-1)%CountOfArray(table);
- display(i);
- }
- void Key17_22ShortPressEvent(void)
- {
- Uart_SendString("Func2! \r\n");
- //這個太慢了 會死機! 放主函數(shù)里也不行 串口被打斷了就會卡死
- }
復制代碼- KeyFuncs[0].TriggerValue = EnumKey_Up_TriggerValue; //需要響應的鍵值 注意是鍵值! 不是鍵編號! 組合按鍵用或
- KeyFuncs[0].SingleClick = Key7ShortPressEvent; //注冊回調(diào)函數(shù)
- KeyFuncs[1].TriggerValue = EnumKey_Down_TriggerValue; //需要響應的鍵值 注意是鍵值! 不是鍵編號! 組合按鍵用或
- KeyFuncs[1].SingleClick = Key12ShortPressEvent; //注冊回調(diào)函數(shù)
- KeyFuncs[2].TriggerValue = EnumKey_Left_TriggerValue | EnumKey_Right_TriggerValue; //需要響應的鍵值 注意是鍵值! 不是鍵編號! 組合按鍵用或
- KeyFuncs[2].MultiPress = Key17_22ShortPressEvent; //注冊回調(diào)函數(shù)
復制代碼
到這里就算是完成了按鍵驅(qū)動的應用,這個思路是不是比傳統(tǒng)的方式簡單多了,嘿嘿。
除非要修改按鍵消抖的時間常數(shù),或者刪減按鍵功能(長按短按判定等),或者改變軟件支持的按鍵數(shù)量,不然不需要修改KeyScan.c和KeyScan.h,這樣就完全分離了驅(qū)動和應用,不管是移植維護還是調(diào)試,都非常方便。
說了這么多,結(jié)果不還是不能用嗎?我用STC12C5A60S2 11.0592MHz速度確實不夠,不過現(xiàn)在STC15W內(nèi)部IRC時鐘可以飆到30MHz,我沒有試過,不知道夠不夠。就算51用不了,移植到別的單片機上也是不錯的。狀態(tài)機和事件驅(qū)動的思路可以放到很多應用里去,雖然這是一個失敗的程序,但是到目前為止還沒發(fā)現(xiàn)邏輯問題,只是受硬件配置限制,就當是一次學習的過程吧。
失敗是成功之母。
GizwitsMCUSTM32F103C8x20170428114156281c5df12c.zip
(725.67 KB, 下載次數(shù): 19)
2018-10-9 10:50 上傳
點擊文件名下載附件
機智云的
下載積分: 黑幣 -5
狀態(tài)機按鍵20181008bak.zip
(63.99 KB, 下載次數(shù): 20)
2018-10-9 10:50 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者: lvsen963 時間: 2018-11-25 08:59
驅(qū)動和應用分離的思想真不錯
作者: 王朗的誘惑 時間: 2020-2-22 20:50
我最近突發(fā)奇想,如果定時器處理不了耗時長的任務,那就讓主函數(shù)處理。大概的想法是搞一個任務隊列,定時器只負責把任務添加到任務隊列里,主函數(shù)檢查任務隊列,如果有任務就依次執(zhí)行。最近忙,有時間的話我就試試。不知道看到這里的壇友有沒有什么好主意……
作者: pull1121 時間: 2020-2-24 12:16
剛開始學啊 一臉懵逼 現(xiàn)在用3個按鍵 LCD1602做的不斷電時鐘,邏輯沒弄清楚,可以指導下不
作者: 王朗的誘惑 時間: 2020-3-3 00:10
有什么問題?
| 歡迎光臨 (http://www.raoushi.com/bbs/) |
Powered by Discuz! X3.1 |