久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 4366|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

[失敗]狀態(tài)機(jī)+事件驅(qū)動(dòng) 按鍵掃描

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

結(jié)果是失敗了,芯片配置不行,但是代碼還是很有趣的。雖然下面說(shuō)的這些因?yàn)?1的速度被限制了,但是我還是想說(shuō)一說(shuō),都是實(shí)際問題。
以往的按鍵掃描,按鍵IO口要用sbit或者#define,離掃描函數(shù)隔得老遠(yuǎn),16進(jìn)制鍵碼還得自己算,算錯(cuò)了就不響應(yīng),功能函數(shù)就更不忍直視了,和消抖攪和在一起……
再看這個(gè)按鍵掃描:
1.      按鍵IO直接在初始化函數(shù)里用字符串輸入,支持任意IO口連接的矩陣鍵盤和單線開關(guān)按鍵。
  1. void KeyInit(void)                //按鍵掃描初始化
  2. {
  3. SingleKey[EnumKey_Left].IOPort1 = "P34"; SingleKey[EnumKey_Left].IOPort2 = "P30";                //注冊(cè)按鍵 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.         ...
復(fù)制代碼
矩陣鍵盤不一定要接在一個(gè)8位的整組IO上。對(duì)于40腳直插的單片機(jī)來(lái)說(shuō),這反而復(fù)雜了些。但是呢,看看那些一不丟丟的小可憐單片機(jī),比如STC15W408AS的16腳封裝,一組完整引出的IO都沒有,要是在這樣的單片機(jī)上用傳統(tǒng)的方式應(yīng)用4x4的矩陣鍵盤,那處理起來(lái)可難受死了……


2.      按鍵編碼就是從0開始到最大按鍵支持?jǐn)?shù)量-1 ,放在一個(gè)enum枚舉里面,鍵碼就是移位,不用算,直接復(fù)制粘貼就可以。還需要把下面#define的按鍵成員總數(shù)也一起改了,注意不要超過最大值,最大值在KeyScan.h里定義,如果有需要可以修改。
  1. enum EnumUserKey                                 //按鍵編號(hào)和鍵值枚舉 編號(hào)從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. };
復(fù)制代碼

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

  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.         //這個(gè)太慢了 會(huì)死機(jī)! 放主函數(shù)里也不行 串口被打斷了就會(huì)卡死
  17. }
復(fù)制代碼
  1.         KeyFuncs[0].TriggerValue = EnumKey_Up_TriggerValue;                        //需要響應(yīng)的鍵值 注意是鍵值! 不是鍵編號(hào)! 組合按鍵用或
  2.         KeyFuncs[0].SingleClick = Key7ShortPressEvent;                //注冊(cè)回調(diào)函數(shù)
  3.         KeyFuncs[1].TriggerValue = EnumKey_Down_TriggerValue;                //需要響應(yīng)的鍵值 注意是鍵值! 不是鍵編號(hào)! 組合按鍵用或
  4.         KeyFuncs[1].SingleClick = Key12ShortPressEvent;                //注冊(cè)回調(diào)函數(shù)
  5.         KeyFuncs[2].TriggerValue = EnumKey_Left_TriggerValue | EnumKey_Right_TriggerValue;                //需要響應(yīng)的鍵值 注意是鍵值! 不是鍵編號(hào)! 組合按鍵用或
  6.         KeyFuncs[2].MultiPress = Key17_22ShortPressEvent;                //注冊(cè)回調(diào)函數(shù)
復(fù)制代碼



到這里就算是完成了按鍵驅(qū)動(dòng)的應(yīng)用,這個(gè)思路是不是比傳統(tǒng)的方式簡(jiǎn)單多了,嘿嘿。
除非要修改按鍵消抖的時(shí)間常數(shù),或者刪減按鍵功能(長(zhǎng)按短按判定等),或者改變軟件支持的按鍵數(shù)量,不然不需要修改KeyScan.c和KeyScan.h,這樣就完全分離了驅(qū)動(dòng)和應(yīng)用,不管是移植維護(hù)還是調(diào)試,都非常方便。

說(shuō)了這么多,結(jié)果不還是不能用嗎?我用STC12C5A60S2  11.0592MHz速度確實(shí)不夠,不過現(xiàn)在STC15W內(nèi)部IRC時(shí)鐘可以飆到30MHz,我沒有試過,不知道夠不夠。就算51用不了,移植到別的單片機(jī)上也是不錯(cuò)的。狀態(tài)機(jī)和事件驅(qū)動(dòng)的思路可以放到很多應(yīng)用里去,雖然這是一個(gè)失敗的程序,但是到目前為止還沒發(fā)現(xiàn)邏輯問題,只是受硬件配置限制,就當(dāng)是一次學(xué)習(xí)的過程吧。
失敗是成功之母。

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

狀態(tài)機(jī)按鍵20181008bak.zip (63.99 KB, 下載次數(shù): 20)

評(píng)分

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

查看全部評(píng)分

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

使用道具 舉報(bào)

沙發(fā)
ID:127533 發(fā)表于 2018-11-25 08:59 | 只看該作者
驅(qū)動(dòng)和應(yīng)用分離的思想真不錯(cuò)
回復(fù)

使用道具 舉報(bào)

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

使用道具 舉報(bào)

地板
ID:535242 發(fā)表于 2020-2-24 12:16 | 只看該作者
剛開始學(xué)啊 一臉懵逼  現(xiàn)在用3個(gè)按鍵 LCD1602做的不斷電時(shí)鐘,邏輯沒弄清楚,可以指導(dǎo)下不
回復(fù)

使用道具 舉報(bào)

5#
ID:84652 發(fā)表于 2020-3-3 00:10 | 只看該作者
pull1121 發(fā)表于 2020-2-24 12:16
剛開始學(xué)啊 一臉懵逼  現(xiàn)在用3個(gè)按鍵 LCD1602做的不斷電時(shí)鐘,邏輯沒弄清楚,可以指導(dǎo)下不

有什么問題?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 亚洲一区二区三区久久久 | 欧美精品在线免费观看 | 欧美日韩三级 | 成人激情视频在线观看 | 亚洲成人福利在线观看 | 一区在线观看视频 | jdav视频在线观看免费 | 在线观看av中文字幕 | 一区二区三区在线免费看 | 羞羞视频免费观看 | 精品亚洲国产成av人片传媒 | 一级日批片 | 成人免费在线 | 欧美成人免费在线 | 精精国产xxxx视频在线播放 | 久久一二区 | 日日综合 | 农村真人裸体丰满少妇毛片 | 秋霞在线一区 | av国产精品 | 久久99这里只有精品 | 91亚洲精品国偷拍自产在线观看 | 在线视频 亚洲 | 国内精品久久久久久久 | 日本在线网站 | 国产在线拍偷自揄拍视频 | 中文字幕av在线播放 | 国产成人精品一区二区三区在线观看 | 性色av一区| 国产精品毛片一区二区三区 | 久久网亚洲 | 国产一区久久 | 国产一区二区三区 | av资源在线看 | 中文字幕一区二区三区四区五区 | 国产一区成人 | 日本一区二区三区四区 | 天天夜夜人人 | 精品欧美乱码久久久久久 | 国产精品亚洲一区二区三区在线 | 99精品国产一区二区三区 |