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

標(biāo)題: 基于單片機(jī)按鍵的長(zhǎng)按與短按功能是實(shí)現(xiàn)(PS:有自己的想法) [打印本頁(yè)]

作者: 51黑ren    時(shí)間: 2015-12-27 03:51
標(biāo)題: 基于單片機(jī)按鍵的長(zhǎng)按與短按功能是實(shí)現(xiàn)(PS:有自己的想法)
縱觀現(xiàn)在的智能硬件產(chǎn)品,按鍵少,功能多。在保證產(chǎn)品外觀漂亮的同時(shí),如何用最少的按鍵,來(lái)實(shí)現(xiàn)較多的功能。
  所以就去網(wǎng)上搜了,按鍵長(zhǎng)按與短按實(shí)現(xiàn)的方法。其中精華代碼,是我在其他人的博客【http://m.zg4o1577.cn/bbs/dpj-41706-1.html】學(xué)來(lái)的。他的核心代碼寫(xiě)的很棒,但是在后邊函數(shù)調(diào)用的時(shí)候,要根據(jù)自己功能的實(shí)現(xiàn)去適當(dāng)?shù)母拇a。
    核心算法

   unsigned char Trg;

   unsigned char Cont;

   void KeyRead( void )

    {

       unsigned char ReadData =GPIO_ReadInputDataBit(GPIO*,GPIO_Pin)^0xff;  // 1

       Trg = ReadData & (ReadData ^Cont);     // 2

        Cont=ReadData;                              // 3

   }

作為一個(gè)新手來(lái)說(shuō),還是要具體其分析分析的:

我們就按鍵開(kāi)始為高電平 ,按下為低電平,進(jìn)行分析。

程序解讀:

Trg(triger) 代表的是觸發(fā),Cont(continue)代表的是連續(xù)按下。

1:GPIO_ReadInputDataBit()這個(gè)函數(shù),就是讀取按鍵GPIO*按鍵引腳的輸入狀態(tài)。^0xff,和前面讀取到的狀態(tài),取反。并將數(shù)值儲(chǔ)存到ReadData中;

2:用來(lái)計(jì)算觸發(fā)變量;

3:用來(lái)計(jì)算連續(xù)變量。

(1)沒(méi)有按鍵的時(shí)候

端口為0xff,ReadData讀端口并且取反,很顯然,就是 0x00 了。

Trg = ReadData & (ReadData ^ Cont);(初始狀態(tài)下,Cont也是為0的)很簡(jiǎn)單的數(shù)學(xué)計(jì)算,因?yàn)镽eadData為0,則它和任何數(shù)“相與”,結(jié)果也是為0的。

Cont = ReadData; 保存Cont 其實(shí)就是等于ReadData,為0;

結(jié)果就是:

ReadData = 0;

Trg = 0;

Cont = 0;

(2) 第一次PB0按下的情況

端口數(shù)據(jù)為0xfe,ReadData讀端口并且取反,很顯然,就是 0x01 了。

Trg = ReadData & (ReadData ^ Cont);因?yàn)檫@是第一次按下,所以Cont是上次的值,應(yīng)為為0。那么這個(gè)式子的值也不難算,也就是 Trg = 0x01 &(0x01^0x00) = 0x01

Cont = ReadData = 0x01;

結(jié)果就是:

ReadData = 0x01;

Trg = 0x01;  (Trg只會(huì)在這個(gè)時(shí)候?qū)?yīng)位的值為1,其它時(shí)候都為0)

Cont = 0x01;

(3)      PB0按著不松(長(zhǎng)按鍵)的情況

端口數(shù)據(jù)為0xfe,ReadData讀端口并且取反是 0x01 了。

Trg = ReadData & (ReadData ^ Cont);因?yàn)檫@是連續(xù)按下,所以Cont是上次的值,應(yīng)為為0x01。那么這個(gè)式子就變成了 Trg = 0x01 &(0x01^0x01) = 0x00

Cont = ReadData = 0x01;

結(jié)果就是:

ReadData = 0x01;

Trg = 0x00;

Cont = 0x01;

因?yàn)楝F(xiàn)在按鍵是長(zhǎng)按著,所以MCU會(huì)每隔一段時(shí)間就會(huì),不斷的執(zhí)行這個(gè)函數(shù),那么下次執(zhí)行的時(shí)候情況會(huì)是怎么樣的呢?

ReadData = 0x01;這個(gè)不會(huì)變,因?yàn)榘存I沒(méi)有松開(kāi)

Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) =0 ,只要按鍵沒(méi)有松開(kāi),這個(gè)Trg值永遠(yuǎn)為 0 !!!

Cont = 0x01;只要按鍵沒(méi)有松開(kāi),這個(gè)值永遠(yuǎn)是0x01!!

(4)      按鍵松開(kāi)的情況

端口數(shù)據(jù)為0xff,ReadData讀端口并且取反是 0x00 了。

Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) =0x00

Cont = ReadData = 0x00;

結(jié)果就是:

ReadData = 0x00;

Trg = 0x00;

Cont = 0x00;

很顯然,這個(gè)回到了初始狀態(tài),也就是沒(méi)有按鍵按下的狀態(tài)。

該代碼的精華之處就在于:Trg只有在按一按鍵的時(shí)候才為0x01,只要按鍵沒(méi)有放開(kāi)Trg從第二次進(jìn)入KeyRead()后,就一直為0x00;Cout,只要按鍵是按下的,這個(gè)值就一直為0x01。

理解基本就是這樣了,下面說(shuō)一下用到的例子:

1:原文中博主的例子,有一個(gè)是這樣的,類似小時(shí)候玩過(guò)的電子表調(diào)節(jié)時(shí)間。

按一個(gè)鍵不放手(直到到達(dá)指定的功能在放手),從按下,到放手,這個(gè)鍵盤(pán)包含了兩個(gè)功能——切換模式、累計(jì)加數(shù)(針對(duì)他的例子說(shuō)的功能,意會(huì)即可)。其實(shí)總的意思就是,從按下,到松手,Trg開(kāi)始的時(shí)候(第一下)為0x01,因?yàn)闆](méi)有放手,故第二次執(zhí)行KeyRead()的時(shí)候,Trg就變?yōu)榱?x00;故根據(jù)原博主的if(Trg & 0x01)和if(Cont & 0x01)這個(gè)的判斷,從按下,到松手,這個(gè)兩個(gè)函數(shù)都會(huì)執(zhí)行過(guò)去。[注:原博主的KEY_PLUS的宏定義應(yīng)該為錯(cuò)誤的,若為0x02,這個(gè)if永遠(yuǎn)都不會(huì)執(zhí)行]

上述講述的這個(gè)鍵盤(pán)的功能,做項(xiàng)目可能用得到。

2:在一個(gè)就是,我自己做東西遇到的一個(gè)問(wèn)題。按鍵,短按一個(gè)功能,長(zhǎng)按一個(gè)功能(兩個(gè)功能不能同時(shí)到來(lái))。顯然例子1的代碼滿足不了我的需求。下面看我的代碼:

void Key_Proc(void)
{
  if(Trg&0x01)    //短按
  {
   DelayMs(200);   //200ms
   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1)   //判斷讀取出的鍵盤(pán)輸入狀態(tài)是否為高電平

   {
   運(yùn)行代碼;

    b=0;
   }
  }
  
  if(Cout&0x01)    //長(zhǎng)按
  {
   b++;
   if(b>20)
   {  
   運(yùn)行代碼;

    b=0;
   }
  }
}

int main()

{

    KeyRead();

    Key_Proc();

    while(1)

   {

        DelayMs(10);

        break;

   }

}

我改的代碼,除了   DelayMs(200);   //200ms
                              if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1)   //判斷讀取出的鍵盤(pán)輸入狀態(tài)是否為高電平

其他的基本相同,這段代碼,主要解決長(zhǎng)按按鍵,兩種功能同時(shí)出現(xiàn)的事件。

分析:按鍵按一下,即按下立馬松開(kāi)。鍵盤(pán)一開(kāi)始為高電平,Delay,消除鍵盤(pán)按下到放開(kāi)的反應(yīng)時(shí)間,200MS足以,然后在檢測(cè)按鍵輸入狀態(tài),若為高,說(shuō)明,已經(jīng)放開(kāi)了,判斷這是一次短按。

         按下不放手,按鍵開(kāi)始為高電平,不放手,延遲過(guò)后,檢測(cè)按鍵依然為低,不進(jìn)入if,也就屏蔽掉了這個(gè)短,按的功能,然后進(jìn)行后邊的if(Cout&0x01),判斷為真,進(jìn)入,b++,后邊有10MS的延遲。b一會(huì)就會(huì)加到20,執(zhí)行程序,并清除b的值。

         為什么短按里面要加一個(gè)b=0呢?如果不加的話,你按鍵盤(pán),若的時(shí)間為達(dá)到長(zhǎng)按的要求,這時(shí)候b也會(huì)++,可能會(huì)出現(xiàn)這樣的情況,連續(xù)點(diǎn)擊鍵盤(pán),按下松開(kāi),按下松開(kāi).......雖然你沒(méi)有長(zhǎng)按,但是連續(xù)的點(diǎn)擊會(huì)使b++到20,導(dǎo)致觸發(fā)功能。故在短按里面加一個(gè)b=0.

大致就是這個(gè)樣子了,還有就是在一個(gè)程序中,一個(gè)鍵盤(pán),在不同的地方有不同的功能,這個(gè)又該如何實(shí)現(xiàn)呢?


我想出來(lái)的就是用switch() case 語(yǔ)句實(shí)現(xiàn)。switch判斷處于程序的哪一個(gè)階段,在找對(duì)應(yīng)的case去執(zhí)行就好了。今天太累了,具體怎么實(shí)現(xiàn)我就不貼代碼了。



作者: 騰飛的龍    時(shí)間: 2015-12-29 10:00
樓主辛苦啦,學(xué)習(xí)啦,學(xué)習(xí)分享!
作者: ♂娿裏旺卐♀    時(shí)間: 2019-3-6 09:28
原博主的
#define KEY_MODE 0x01    // 模式按鍵
#define KEY_PLUS 0x02     // 加
這個(gè)是定義了兩個(gè)按鍵,在示例中,KEY_MODE鍵只有短按有效,KEY_PLUS鍵只有長(zhǎng)按有效。
作者: nqwang    時(shí)間: 2021-5-14 13:17
mark一下,學(xué)習(xí)了




歡迎光臨 (http://m.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 亚洲欧洲日韩精品 中文字幕 | 成人小视频在线观看 | 成人做爰69片免费观看 | 在线视频国产一区 | 日韩亚洲一区二区 | 国产成人精品久久二区二区91 | 武道仙尊动漫在线观看 | 婷婷激情在线 | 高清视频一区二区三区 | 91久久国产精品 | 亚洲精品区 | 日韩一区二区av | 国产视频2021| 亚洲一区二区三区在线 | 日韩电影在线一区 | 成人精品视频在线观看 | 网色| 国产一区二区三区 | 91在线视频在线观看 | 成人免费观看视频 | av喷水 | 福利视频网址 | 精品亚洲国产成av人片传媒 | 中文一区二区 | www.中文字幕.com | 久久综合久久综合久久综合 | 天堂成人国产精品一区 | 在线精品亚洲欧美日韩国产 | 欧美日韩黄色一级片 | 羞羞视频免费在线 | 一a一片一级一片啪啪 | 日韩视频―中文字幕 | 九九久久免费视频 | 精品在线播放 | 麻豆视频在线看 | 亚洲一二三区在线观看 | 免费黄色录像片 | 欧美一区2区三区4区公司二百 | a黄在线观看 | 日本三级在线网站 | 欧美一区二区三区,视频 |