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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

簡單按鍵掃描程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:85148 發(fā)表于 2015-7-9 00:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
核心算法:
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) 代表的是觸發(fā),Cont(continue)代表的是連續(xù)按下。
1:讀PORTB的端口數(shù)據(jù),取反,然后送到ReadData 臨時變量里面保存起來。
2:算法1,用來計算觸發(fā)變量的。一個位與操作,一個異或操作,我想學(xué)過C語言都應(yīng)該懂吧?Trg為全局變量,其它程序可以直接引用。
3:算法2,用來計算連續(xù)變量。
看到這里,有種“知其然,不知其所以然”的感覺吧?代碼很簡單,但是它到底是怎么樣實現(xiàn)我們的目的的呢?好,下面就讓我們繞開云霧看青天吧。
我們最常用的按鍵接法如下:AVR是有內(nèi)部上拉功能的,但是為了說明問題,我是特意用外部上拉電阻。那么,按鍵沒有按下的時候,讀端口數(shù)據(jù)為1,如果按鍵按下,那么端口讀到0。下面就看看具體幾種情況之下,這算法是怎么一回事。
(1)       沒有按鍵的時候
端口為0xff,ReadData讀端口并且取反,很顯然,就是 0x00 了。
Trg = ReadData & (ReadData ^ Cont); (初始狀態(tài)下,Cont也是為0的)很簡單的數(shù)學(xué)計算,因為ReadData為0,則它和任何數(shù)“相與”,結(jié)果也是為0的。
Cont = ReadData; 保存Cont 其實就是等于ReadData,為0;
結(jié)果就是:
ReadData = 0;
Trg = 0;
Cont = 0;
(2)       第一次PB0按下的情況
端口數(shù)據(jù)為0xfe,ReadData讀端口并且取反,很顯然,就是 0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因為這是第一次按下,所以Cont是上次的值,應(yīng)為為0。那么這個式子的值也不難算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01
Cont = ReadData = 0x01;
結(jié)果就是:
ReadData = 0x01;
Trg = 0x01;Trg只會在這個時候?qū)?yīng)位的值為1,其它時候都為0
Cont = 0x01;
(3)       PB0按著不松(長按鍵)的情況
端口數(shù)據(jù)為0xfe,ReadData讀端口并且取反是 0x01 了。
Trg = ReadData & (ReadData ^ Cont); 因為這是連續(xù)按下,所以Cont是上次的值,應(yīng)為為0x01。那么這個式子就變成了 Trg = 0x01 & (0x01^0x01) = 0x00
Cont = ReadData = 0x01;
結(jié)果就是:
ReadData = 0x01;
Trg = 0x00;
Cont = 0x01;
因為現(xiàn)在按鍵是長按著,所以MCU會每個一定時間(20ms左右)不斷的執(zhí)行這個函數(shù),那么下次執(zhí)行的時候情況會是怎么樣的呢?
ReadData = 0x01;這個不會變,因為按鍵沒有松開
Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按鍵沒有松開,這個Trg值永遠(yuǎn)為 0 !!!
Cont = 0x01;只要按鍵沒有松開,這個值永遠(yuǎn)是0x01!!
(4)       按鍵松開的情況
端口數(shù)據(jù)為0xff,ReadData讀端口并且取反是 0x00 了。
Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00
Cont = ReadData = 0x00;
結(jié)果就是:
ReadData = 0x00;
Trg = 0x00;
Cont = 0x00;
很顯然,這個回到了初始狀態(tài),也就是沒有按鍵按下的狀態(tài)。
總結(jié)一下,不知道想懂了沒有?其實很簡單,答案如下:
Trg 表示的就是觸發(fā)的意思,也就是跳變,只要有按鍵按下(電平從1到0的跳變),那么Trg在對應(yīng)按鍵的位上面會置一,我們用了PB0則Trg的值為0x01,類似,如果我們PB7按下的話,Trg 的值就應(yīng)該為 0x80 ,這個很好理解,還有,最關(guān)鍵的地方,Trg 的值每次按下只會出現(xiàn)一次,然后立刻被清除,完全不需要人工去干預(yù)。所以按鍵功能處理程序不會重復(fù)執(zhí)行,省下了一大堆的條件判斷,這個可是精粹哦!!Cont代表的是長按鍵,如果PB0按著不放,那么Cont的值就為 0x01,相對應(yīng),PB7按著不放,那么Cont的值應(yīng)該為0x80,同樣很好理解。
如果還是想不懂的話,可以自己演算一下那兩個表達(dá)式,應(yīng)該不難理解的。
應(yīng)用一:一次觸發(fā)的按鍵處理
假設(shè)PB0為蜂鳴器按鍵,按一下,蜂鳴器beep的響一聲。這個很簡單,但是大家以前是怎么做的呢?對比一下看誰的方便?
#define KEY_BEEP 0x01
void KeyProc(void)
{
       if (Trg & KEY_BEEP) // 如果按下的是KEY_BEEP
    {
         Beep();            // 執(zhí)行蜂鳴器處理函數(shù)
    }
}
應(yīng)用2:長按鍵的處理
這里具個簡單例子,為了只是說明原理,PB0是模式按鍵,短按則切換模式,PB1就是加,如果長按的話則連加(玩過電子表吧?沒錯,就是那個!)
#define KEY_MODE 0x01    // 模式按鍵
#define KEY_PLUS 0x02     // 加
void KeyProc(void)
{
       if (Trg & KEY_MODE) // 如果按下的是KEY_MODE,而且你常按這按鍵也沒有用,
    {                    //它是不會執(zhí)行第二次的哦 , 必須先松開再按下
         Mode++;         // 模式寄存器加1,當(dāng)然,這里只是演示,你可以執(zhí)行你想
                         // 執(zhí)行的任何代碼
    }
    if (Cont & KEY_PLUS) // 如果“加”按鍵被按著不放
    {
         cnt_plus++;       // 計時
         if (cnt_plus > 100) // 20ms*100 = 2S 如果時間到
         {
              Func();      // 你需要的執(zhí)行的程序
         }         
    }
}
應(yīng)用3:點觸型按鍵和開關(guān)型按鍵的混合使用
volatile unsigned char Intrcnt;
void InterruptHandle()    // 中斷服務(wù)程序
{
       Intrcnt++;          // 1ms 中斷1次,可變
}
void main(void)
{
       SysInit();
    while(1)           // 每20ms 執(zhí)行一次大循環(huán)
    {
        KeyRead();             // 將每個子程序都掃描一遍
        KeyProc();
        Func1();
        Funt2();
        …
        …
           while(1)
        {
              if (Intrcnt>20)     // 一直在等,直到20ms時間到
              {
                   Intrcnt="0";
                   break;       // 返回主循環(huán)
              }
        }
       }
}

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

使用道具 舉報

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

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 国产精品久久久久久久7777 | 婷婷福利视频导航 | 黄色在线免费播放 | 成人黄色a| 精品91久久| 美女天天干天天操 | 91精品久久久久久久久99蜜臂 | 欧美 日韩 国产 在线 | 毛片一级电影 | 视频精品一区 | 欧美激情精品久久久久久变态 | 日本三级电影在线免费观看 | 日韩欧美在线视频 | 无毛av | 天天爽夜夜操 | 日韩毛片 | 欧美精品一区二区三区四区 在线 | 免费高潮视频95在线观看网站 | 伊人伊人 | 超碰在线97国产 | 男女av| 国产精品爱久久久久久久 | 成人免费视频观看视频 | 久久久久久亚洲精品不卡 | 日韩精品一区二区三区在线播放 | 蜜桃av鲁一鲁一鲁一鲁 | 久久新| 成人免费影院 | 日韩欧美一区二区三区免费观看 | 免费一区 | 日韩免费高清视频 | 欧美成人综合 | 黄色成人av| 美日韩免费| 亚洲第一中文字幕 | 亚洲天堂免费 | 色视频网站在线观看 | 久久精品网 | 午夜久久久 | 91电影 | 91精品国产91久久久久久不卞 |