欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4484|回復: 4
打印 上一主題 下一主題
收起左側

[失敗]狀態機+事件驅動 按鍵掃描

[復制鏈接]
跳轉到指定樓層
樓主
首先說明:這是一個失敗的按鍵掃描程序。它的前身是機智云的STM32按鍵掃描代碼。
不管是用什么芯片,按鍵掃描的延時去抖總是令人心痛,費CPU費電費時間,于是各種各樣好玩有趣的按鍵掃描代碼誕生了。就比如我曾經下載的這個機智云的代碼,使用狀態機+事件驅動,看起來非常漂亮。
使用狀態機和一個定時器,就可以去除消抖延時,提高按鍵掃描效率,還可以在里面添加各種各樣的功能判斷,好處說不完吶。
而事件驅動,把按鍵和按鍵對應的功能隔離開,使用函數指針連接,這樣分隔開了按鍵掃描和事件處理。回想起多級菜單,每一級菜單按鍵功能都不一樣,處理起來簡直就是噩夢。如果用事件機制來做的話,就可以通過函數指針動態改變按鍵功能,終于把重復混亂的變量和代碼送進了回收站。
最近放假實在是心動,我想,如果能把它用在51上該多好呀,于是乎就動手了。但是當我興沖沖地把它改了好半天,終于用在51上的時候,程序直接掛掉了——51速度太慢,消抖檢測周期內不能跑完回調函數,于是就會死機。
實驗環境是STC12C5A60S2  11.0592MHz  代碼8級優化
對于51單片機來說,這個程序致命的缺點:
1.      51速度不夠,如上所述。我試著把KeyHandle函數里后三個功能的檢測注釋掉,就不會死機了。但是這不是寫這段程序的初衷,所以不能這么做。
2.      51內存不夠。這段程序在定義4個按鍵3個事件的時候RAM占用量就過百了,看著51那可憐巴巴的128字節RAM,我都有點不忍了。至于STC自帶的擴展的RAM,速度實在是不夠,如果定義到xdata,回調函數里很簡短的操作都會死機。

結果是失敗了,芯片配置不行,但是代碼還是很有趣的。雖然下面說的這些因為51的速度被限制了,但是我還是想說一說,都是實際問題。
以往的按鍵掃描,按鍵IO口要用sbit或者#define,離掃描函數隔得老遠,16進制鍵碼還得自己算,算錯了就不響應,功能函數就更不忍直視了,和消抖攪和在一起……
再看這個按鍵掃描:
1.      按鍵IO直接在初始化函數里用字符串輸入,支持任意IO口連接的矩陣鍵盤和單線開關按鍵。
  1. void KeyInit(void)                //按鍵掃描初始化
  2. {
  3. SingleKey[EnumKey_Left].IOPort1 = "P34"; SingleKey[EnumKey_Left].IOPort2 = "P30";                //注冊按鍵 Port1必須是IO口 Port2是IO口或"GND"
  4.         SingleKey[EnumKey_Right].IOPort1 = "P35"; SingleKey[EnumKey_Right].IOPort2 = "P30";
  5.         SingleKey[EnumKey_Up].IOPort1 = "P36"; SingleKey[EnumKey_Up].IOPort2 = "P30";
  6.         SingleKey[EnumKey_Down].IOPort1 = "P37"; SingleKey[EnumKey_Down].IOPort2 = "P30";
  7.         ...
復制代碼
矩陣鍵盤不一定要接在一個8位的整組IO上。對于40腳直插的單片機來說,這反而復雜了些。但是呢,看看那些一不丟丟的小可憐單片機,比如STC15W408AS的16腳封裝,一組完整引出的IO都沒有,要是在這樣的單片機上用傳統的方式應用4x4的矩陣鍵盤,那處理起來可難受死了……


2.      按鍵編碼就是從0開始到最大按鍵支持數量-1 ,放在一個enum枚舉里面,鍵碼就是移位,不用算,直接復制粘貼就可以。還需要把下面#define的按鍵成員總數也一起改了,注意不要超過最大值,最大值在KeyScan.h里定義,如果有需要可以修改。
  1. enum EnumUserKey                                 //按鍵編號和鍵值枚舉 編號從0開始 不得超過(KEY_MAX_NUMBER-1)
  2. {
  3.         EnumKey_Up  = 0, EnumKey_Up_TriggerValue = 1<<EnumKey_Up,
  4.         EnumKey_Down  = 1, EnumKey_Down_TriggerValue = 1<<EnumKey_Down,
  5.         EnumKey_Left  = 2, EnumKey_Left_TriggerValue = 1<<EnumKey_Left,
  6.         EnumKey_Right  = 3, EnumKey_Right_TriggerValue = 1<<EnumKey_Right
  7. };
復制代碼

3.      功能函數作為事件單獨定義,我改進了一下原來的代碼,讓功能和按鍵互相獨立,用戶自定義觸發方式或按鍵組合,再用函數指針連接想要觸發的事件,邏輯簡潔清晰。
還需要把上面#define的用戶自定義的功能總數一起改了,就是KeyFuncs成員的數量,不一定和事件函數或者按鍵數量一致,只要內存夠用,想要多少就要多少。

  1. void Key7ShortPressEvent(void)
  2. {
  3.         static u8 i=0;
  4.         i = (i+1)%CountOfArray(table);
  5.         display(i);
  6. }
  7. void Key12ShortPressEvent(void)
  8. {
  9.         static u8 i=0;
  10.         i = (i-1)%CountOfArray(table);
  11.         display(i);
  12. }
  13. void Key17_22ShortPressEvent(void)
  14. {
  15.         Uart_SendString("Func2! \r\n");
  16.         //這個太慢了 會死機! 放主函數里也不行 串口被打斷了就會卡死
  17. }
復制代碼
  1.         KeyFuncs[0].TriggerValue = EnumKey_Up_TriggerValue;                        //需要響應的鍵值 注意是鍵值! 不是鍵編號! 組合按鍵用或
  2.         KeyFuncs[0].SingleClick = Key7ShortPressEvent;                //注冊回調函數
  3.         KeyFuncs[1].TriggerValue = EnumKey_Down_TriggerValue;                //需要響應的鍵值 注意是鍵值! 不是鍵編號! 組合按鍵用或
  4.         KeyFuncs[1].SingleClick = Key12ShortPressEvent;                //注冊回調函數
  5.         KeyFuncs[2].TriggerValue = EnumKey_Left_TriggerValue | EnumKey_Right_TriggerValue;                //需要響應的鍵值 注意是鍵值! 不是鍵編號! 組合按鍵用或
  6.         KeyFuncs[2].MultiPress = Key17_22ShortPressEvent;                //注冊回調函數
復制代碼



到這里就算是完成了按鍵驅動的應用,這個思路是不是比傳統的方式簡單多了,嘿嘿。
除非要修改按鍵消抖的時間常數,或者刪減按鍵功能(長按短按判定等),或者改變軟件支持的按鍵數量,不然不需要修改KeyScan.c和KeyScan.h,這樣就完全分離了驅動和應用,不管是移植維護還是調試,都非常方便。

說了這么多,結果不還是不能用嗎?我用STC12C5A60S2  11.0592MHz速度確實不夠,不過現在STC15W內部IRC時鐘可以飆到30MHz,我沒有試過,不知道夠不夠。就算51用不了,移植到別的單片機上也是不錯的。狀態機和事件驅動的思路可以放到很多應用里去,雖然這是一個失敗的程序,但是到目前為止還沒發現邏輯問題,只是受硬件配置限制,就當是一次學習的過程吧。
失敗是成功之母。

GizwitsMCUSTM32F103C8x20170428114156281c5df12c.zip (725.67 KB, 下載次數: 19)

狀態機按鍵20181008bak.zip (63.99 KB, 下載次數: 20)

評分

參與人數 1黑幣 +15 收起 理由
凌凈清河 + 15 絕世好帖!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:127533 發表于 2018-11-25 08:59 | 只看該作者
驅動和應用分離的思想真不錯
回復

使用道具 舉報

板凳
ID:84652 發表于 2020-2-22 20:50 | 只看該作者
我最近突發奇想,如果定時器處理不了耗時長的任務,那就讓主函數處理。大概的想法是搞一個任務隊列,定時器只負責把任務添加到任務隊列里,主函數檢查任務隊列,如果有任務就依次執行。最近忙,有時間的話我就試試。不知道看到這里的壇友有沒有什么好主意……
回復

使用道具 舉報

地板
ID:535242 發表于 2020-2-24 12:16 | 只看該作者
剛開始學啊 一臉懵逼  現在用3個按鍵 LCD1602做的不斷電時鐘,邏輯沒弄清楚,可以指導下不
回復

使用道具 舉報

5#
ID:84652 發表于 2020-3-3 00:10 | 只看該作者
pull1121 發表于 2020-2-24 12:16
剛開始學啊 一臉懵逼  現在用3個按鍵 LCD1602做的不斷電時鐘,邏輯沒弄清楚,可以指導下不

有什么問題?
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表