娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2024年12月29日(星期日)

2020年12月29日 | 新型的單片機按鍵掃描程序

發布者:小星星龍貓 來源: 51hei關鍵字:單片機  按鍵  掃描程序 手機看文章 掃描二維碼
隨時隨地手機看文章

不過我在網上游逛了很久,也看過不少源程序了,沒有發現這種按鍵處理辦法的蹤跡,所以,我將他共享出來,和廣大同僚們共勉。我非常堅信這種按鍵處理辦法的便捷和高效,你可以移植到任何一種嵌入式處理器上面,因為C語言強大的可移植性。
同時,這里面用到了一些分層的思想,在單片機當中也是相當有用的,也是本文的另外一個重點。
對于老鳥,我建議直接看那兩個表達式,然后自己想想就會懂的了,也不需要聽我后面的自吹自擂了,我可沒有班門弄斧的意思,hoho~~但是對于新手,我建議將全文看完。因為這是實際項目中總結出來的經驗,學校里面學不到的東西。
以下假設你懂C語言,因為純粹的C語言描述,所以和處理器平臺無關,你可以在MCS-51,AVR,PIC,甚至是ARM平臺上面測試這個程序性能。當然,我自己也是在多個項目用過,效果非常好的。
好了,工程人員的習慣,廢話就應該少說,開始吧。以下我以AVR的MEGA8作為平臺講解,沒有其它原因,因為我手頭上只有AVR的板子而已沒有51的。用51也可以,只是芯片初始化部分不同,還有寄存器名字不同而已。
核心算法:
unsigned char Trg;
unsigned char Cont;
void KeyRead( void )
{
    unsigned char ReadData = PINB^0xff;   // 1
    Trg = ReadData & (ReadData ^ Cont);      // 2
    Cont = ReadData;                                // 3
}
完了。有沒有一種不可思議的感覺?當然,沒有想懂之前會那樣,想懂之后就會驚嘆于這算法的精妙!!
下面是程序解釋:
Trg(triger) 代表的是觸發,Cont(continue)代表的是連續按下。
1:讀PORTB的端口數據,取反,然后送到ReadData 臨時變量里面保存起來。
2:算法1,用來計算觸發變量的。一個位與操作,一個異或操作,我想學過C語言都應該懂吧?Trg為全局變量,其它程序可以直接引用。
3:算法2,用來計算連續變量。
看到這里,有種“知其然,不知其所以然”的感覺吧?代碼很簡單,但是它到底是怎么樣實現我們的目的的呢?好,下面就讓我們繞開云霧看青天吧。
我們最常用的按鍵接法如下:AVR是有內部上拉功能的,但是為了說明問題,我是特意用外部上拉電阻。那么,按鍵沒有按下的時候,讀端口數據為1,如果按鍵按下,那么端口讀到0。下面就看看具體幾種情況之下,這算法是怎么一回事。
(1)       沒有按鍵的時候
端口為0xff,ReadData讀端口并且取反,很顯然,就是 0x00 了。
Trg = ReadData & (ReadData ^ Cont); (初始狀態下,Cont也是為0的)很簡單的數學計算,因為ReadData為0,則它和任何數“相與”,結果也是為0的。
Cont = ReadData; 保存Cont 其實就是等于ReadData,為0;
結果就是:
ReadData = 0;
Trg = 0;
Cont = 0;
(2)       第一次PB0按下的情況
端口數據為0xfe,ReadData讀端口并且取反,很顯然,就是 0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因為這是第一次按下,所以Cont是上次的值,應為為0。那么這個式子的值也不難算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01
Cont = ReadData = 0x01;
結果就是:
ReadData = 0x01;
Trg = 0x01;Trg只會在這個時候對應位的值為1,其它時候都為0
Cont = 0x01;
(3)       PB0按著不松(長按鍵)的情況
端口數據為0xfe,ReadData讀端口并且取反是 0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因為這是連續按下,所以Cont是上次的值,應為為0x01。那么這個式子就變成了 Trg = 0x01 & (0x01^0x01) = 0x00
Cont = ReadData = 0x01;
結果就是:
ReadData = 0x01;
Trg = 0x00;
Cont = 0x01;
因為現在按鍵是長按著,所以MCU會每個一定時間(20ms左右)不斷的執行這個函數,那么下次執行的時候情況會是怎么樣的呢?
ReadData = 0x01;這個不會變,因為按鍵沒有松開
Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按鍵沒有松開,這個Trg值永遠為 0 !!!
Cont = 0x01;只要按鍵沒有松開,這個值永遠是0x01!!
(4)       按鍵松開的情況
端口數據為0xff,ReadData讀端口并且取反是 0x00 了。
Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00
Cont = ReadData = 0x00;
結果就是:
ReadData = 0x00;
Trg = 0x00;
Cont = 0x00;
很顯然,這個回到了初始狀態,也就是沒有按鍵按下的狀態。
總結一下,不知道想懂了沒有?其實很簡單,答案如下:
Trg 表示的就是觸發的意思,也就是跳變,只要有按鍵按下(電平從1到0的跳變),那么Trg在對應按鍵的位上面會置一,我們用了PB0則Trg的值為0x01,類似,如果我們PB7按下的話,Trg 的值就應該為 0x80 ,這個很好理解,還有,最關鍵的地方,Trg 的值每次按下只會出現一次,然后立刻被清除,完全不需要人工去干預。所以按鍵功能處理程序不會重復執行,省下了一大堆的條件判斷,這個可是精粹哦!!Cont代表的是長按鍵,如果PB0按著不放,那么Cont的值就為 0x01,相對應,PB7按著不放,那么Cont的值應該為0x80,同樣很好理解。
如果還是想不懂的話,可以自己演算一下那兩個表達式,應該不難理解的。
因為有了這個支持,那么按鍵處理就變得很爽了,下面看應用:
應用一:一次觸發的按鍵處理
假設PB0為蜂鳴器按鍵,按一下,蜂鳴器beep的響一聲。這個很簡單,但是大家以前是怎么做的呢?對比一下看誰的方便?
#define KEY_BEEP 0x01
void KeyProc(void)
{
       if (Trg & KEY_BEEP) // 如果按下的是KEY_BEEP
    {
         Beep();            // 執行蜂鳴器處理函數
    }
}
怎么樣?夠ok不?記得前面解釋說Trg的精粹是什么?精粹就是只會出現一次。所以你按下按鍵的話,Trg & KEY_BEEP 為“真”的情況只會出現一次,所以處理起來非常的方便,蜂鳴器也不會沒事亂叫,hoho~~~
或者你會認為這個處理簡單,沒有問題,我們繼續。
應用2:長按鍵的處理
項目中經常會遇到一些要求,例如:一個按鍵如果短按一下執行功能A,如果長按2秒不放的話會執行功能B,又或者是要求3秒按著不放,計數連加什么什么的功能,很實際。不知道大家以前是怎么做的呢?我承認以前做的很郁悶。
但是看我們這里怎么處理吧,或許你會大吃一驚,原來程序可以這么簡單
這里具個簡單例子,為了只是說明原理,PB0是模式按鍵,短按則切換模式,PB1就是加,如果長按的話則連加(玩過電子表吧?沒錯,就是那個!)
#define KEY_MODE 0x01    // 模式按鍵
#define KEY_PLUS 0x02     // 加
void KeyProc(void)
{
       if (Trg & KEY_MODE) // 如果按下的是KEY_MODE,而且你常按這按鍵也沒有用,
    {                    //它是不會執行第二次的哦 , 必須先松開再按下
         Mode++;         // 模式寄存器加1,當然,這里只是演示,你可以執行你想
                         // 執行的任何代碼
    }
    if (Cont & KEY_PLUS) // 如果“加”按鍵被按著不放
    {
         cnt_plus++;       // 計時
         if (cnt_plus > 100) // 20ms*100 = 2S 如果時間到
         {
              Func();      // 你需要的執行的程序
         }         
    }
}
不知道各位感覺如何?我覺得還是挺簡單的完成了任務,當然,作為演示用代碼。
應用3:點觸型按鍵和開關型按鍵的混合使用
點觸形按鍵估計用的最多,特別是單片機。開關型其實也很常見,例如家里的電燈,那些按下就不松開,除非關。這是兩種按鍵形式的處理原理也沒啥特別,但是你有沒有想過,如果一個系統里面這兩種按鍵是怎么處理的?我想起了我以前的處理,分開兩個非常類似的處理程序,現在看起來真的是笨的不行了,但是也沒有辦法啊,結構決定了程序。不過現在好了,用上面介紹的辦法,很輕松就可以搞定。
原理么?可能你也會想到,對于點觸開關,按照上面的辦法處理一次按下和長按,對于開關型,我們只需要處理Cont就OK了,為什么?很簡單嘛,把它當成是一個長按鍵,這樣就找到了共同點,屏蔽了所有的細節。程序就不給了,完全就是應用2的內容,在這里提為了就是說明原理~~
好了,這個好用的按鍵處理算是說完了。可能會有朋友會問,為什么不說延時消抖問題?哈哈,被看穿了。果然不能偷懶。下面談談這個問題,順便也就非常簡單的談談我自己用時間片輪辦法,以及是如何消抖的。
延時消抖的辦法是非常傳統,也就是 第一次判斷有按鍵,延時一定的時間(一般習慣是20ms)再讀端口,如果兩次讀到的數據一樣,說明了是真正的按鍵,而不是抖動,則進入按鍵處理程序。
當然,不要跟我說你delay(20)那樣去死循環去,真是那樣的話,我衷心的建議你先放下手上所有的東西,好好的去了解一下操作系統的分時工作原理,大概知道思想就可以,不需要詳細看原理,否則你永遠逃不出“菜鳥”這個圈子。當然我也是菜鳥。我的意思是,真正的單片機入門,是從學會處理多任務開始的,這個也是學校程序跟公司程序的最大差別。當然,本文不是專門說這個的,所以也不獻丑了。
我的主程序架構是這樣的:
volatile unsigned char Intrcnt;
void InterruptHandle()    // 中斷服務程序
{
       Intrcnt++;          // 1ms 中斷1次,可變
}
void main(void)
{
       SysInit();
    while(1)           // 每20ms 執行一次大循環
    {
        KeyRead();             // 將每個子程序都掃描一遍
        KeyProc();
        Func1();
        Funt2();
        …
        …
           while(1)
        {
              if (Intrcnt>20)     // 一直在等,直到20ms時間到
              {
                   Intrcnt="0";
                   break;       // 返回主循環
              }
        }
       }
}
貌似扯遠了,回到我們剛才的問題,也就是怎么做按鍵消抖處理。我們將讀按鍵的程序放在了主循環,也就是說,每20ms我們會執行一次KeyRead()函數來得到新的Trg 和 Cont 值。好了,下面是我的消抖部分:很簡單
基本架構如上,我自己比較喜歡的,一直在用。當然,和這個配合,每個子程序必須執行時間不長,更加不能死循環,一般采用有限狀態機的辦法來實現,具體參考其它資料咯。
懂得基本原理之后,至于怎么用就大家慢慢思考了,我想也難不到聰明的工程師們。例如還有一些處理,
怎么判斷按鍵釋放?很簡單,Trg 和Cont都為0 則肯定已經釋放了。

關鍵字:單片機  按鍵  掃描程序 引用地址:新型的單片機按鍵掃描程序

上一篇:單片機串口收發程序分享
下一篇:51單片機串口通訊結合點陣顯示的實例

推薦閱讀

? ? ? ? 一直以來,三星手機的系統更新頻率并沒有像國產手機這樣頻繁,但是三星此次Galaxy S9和S9 +的Android 9 Pie穩定版本推出時間將比預期更早。本次更新可能不適用于全球范圍,僅在少數市場會推送該系統。三星Android 9升級計劃  根據三星土耳其分部網站上的一些新發現的信息顯示,三星Galaxy Note 9在1月15日就可以在更新Android 9...
隨著續航里程和駕乘品質的提升,越來越多的新能源汽車走進了廣大消費者懷抱。然而,由于配套基礎設施建設相對滯后,充電難問題困擾著許多新能源車用戶。在商場、寫字樓等公共場所,不時會出現充電樁數量不夠或充電車位被燃油車占據的情況,讓電動車車主很是頭疼。 為此,大眾集團發布了新的解決方案,利用移動式機器人來給新能源汽車充電。這一理念由大...
A股三大指數今日全天維持震蕩整理態勢,最終集體紅盤報收。兩市合計成交8811億元,行業板塊漲少跌多,釀酒板塊大漲。北向資金今日小幅凈賣出4.08億元。具體來看,滬指收盤上漲0.02%,收報3397.29點;深成指上漲0.19%,收報14044.10點;創業板指上漲0.07%,收報2842.81點。半導體板塊表現較差。集微網從電子元件、材料、設備、設計、制造、IDM、封測、分銷...
如果要用三個字來回答該問題,就是更安全,更安全,更安全,更安全。重要的事情說5遍!眾所周知,自動駕駛技術分為5個等級。級別越高,輔助系統代替駕駛員完成的工作量越多。5 級表示全自動化駕駛,可以在任何環境和情況下進行無人駕駛。當自動化等級達到 5 級時,任何時候都無需駕駛員控制車輛。說句人話,就是自動駕駛達到5級時,人就不用做駕駛員了...

史海拾趣

問答坊 | AI 解惑

3DSPI分析無鉛制造缺陷

首先,可以通過結構化實現的三維錫膏印刷檢測(3D SPI)識別這些根本原因,并且利用3D SPI更好的實現過程控制以及識別變化。此外,在電路板組裝后認真的檢查SPI數據可以找到問題的根本原因,這種智能可以輸入到檢測指標中,通過為錯誤和變化確定更有 ...…

查看全部問答∨

請問生產廠家:耗盡型高壓MOSFET

請問誰知道哪家廠家可以生產類似1N60的高壓MOSFET,但是溝道類型為耗盡型的,謝謝…

查看全部問答∨

超酷!兩款最拉風的另類手機

香煙手機 這款香煙手機就是獻給廣大煙民的禮物。表面上是一盒中華煙,里面或背面去藏著帶有LED顯示屏和攝像功能的手機                   廣播音響手機 帶有MP3功能的手機已經不新 ...…

查看全部問答∨

請高人明示vxworks5.5的82541網卡驅動修改

從82543改82541,改了gei82543end.h里的: #define PRO1000_PCI_DEVICE_ID   0x1001 /* device ID */, 順便把#define PRO1000_PCI_DEVICE_ID           0x1001 /* device ID */ #define PRO ...…

查看全部問答∨

請教SD16問題

請問同行,那位知道MSP430中,那款芯片SD16是單通道多組輸入端的,不像F425有3個通道 每個通道只有一組輸入端。且一定要有LCD驅動的。謝謝!…

查看全部問答∨

51單片機能控制的TFT觸摸屏

51單片機能控制的TFT觸摸屏 直接上一段源碼大家看看,希望大家多多支持啊 /************************************************  TFT6448BS-5.7  顯示武漢谷鑫為您添光增彩   www.mcutech.cn***************** ...…

查看全部問答∨

為什么我的流水燈這么難搞

          為什么還會有這么多錯誤啊              …

查看全部問答∨

用FPGA控制RTL8019AS,用verilog編寫初始化模塊

用FPGA控制RTL8019AS網卡芯片,由于對verilog不是很了解,對于RTL8019AS的初始化程序不知道該怎么寫?就是設置各個寄存器的值?誰能幫我一下嗎?…

查看全部問答∨

建立ANSI/ESD S20.20 靜電防控體系原則和措施

     隨著國際電子電器業對產品要求不斷提升, 買家在選擇產品供應商和合作伙伴時, 更加重視有沒有一個規范的防靜電控制體系。規模較大的國際性電子電器品牌已要求有關ESDS部件供應商定期按照ANSI/ESD S20.20標準執行內部、第二及或第三 ...…

查看全部問答∨

有人用過耐高溫的角度或位移傳感器嗎?

求助 有人用過耐高溫的角度或位移傳感器嗎?想找一種合適傳感器 長期工作在150°溫度下  直線量程是150mm左右…

查看全部問答∨
小廣播
設計資源 培訓 開發板 精華推薦

最新單片機文章
何立民專欄 單片機及嵌入式寶典

北京航空航天大學教授,20余年來致力于單片機與嵌入式系統推廣工作。

 
EEWorld訂閱號

 
EEWorld服務號

 
汽車開發圈

 
機器人開發圈

電子工程世界版權所有 京ICP證060456號 京ICP備10001474號-1 電信業務審批[2006]字第258號函 京公網安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 锡林郭勒盟| 抚松县| 井研县| 扶余县| 庆阳市| 岑溪市| 诸城市| 波密县| 临江市| 翁牛特旗| 蓬安县| 江安县| 时尚| 杨浦区| 咸丰县| 仁怀市| 民丰县| 南通市| 红安县| 江北区| 微博| 行唐县| 大安市| 宁夏| 内江市| 望城县| 贵阳市| 嘉黎县| 乌拉特后旗| 全州县| 盐边县| 祁东县| 竹山县| 龙口市| 抚顺市| 吉林市| 双辽市| 西畴县| 平武县| 田阳县| 尉氏县|