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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

基于單片機按鍵的長按與短按功能是實現(PS:有自己的想法)

[復制鏈接]
跳轉到指定樓層
樓主
ID:99624 發表于 2015-12-27 03:51 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
縱觀現在的智能硬件產品,按鍵少,功能多。在保證產品外觀漂亮的同時,如何用最少的按鍵,來實現較多的功能。
  所以就去網上搜了,按鍵長按與短按實現的方法。其中精華代碼,是我在其他人的博客【http://www.zg4o1577.cn/bbs/dpj-41706-1.html】學來的。他的核心代碼寫的很棒,但是在后邊函數調用的時候,要根據自己功能的實現去適當的更改代碼。
    核心算法

   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

   }

作為一個新手來說,還是要具體其分析分析的:

我們就按鍵開始為高電平 ,按下為低電平,進行分析。

程序解讀:

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

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

2:用來計算觸發變量;

3:用來計算連續變量。

(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會每隔一段時間就會,不斷的執行這個函數,那么下次執行的時候情況會是怎么樣的呢?

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只有在按一按鍵的時候才為0x01,只要按鍵沒有放開Trg從第二次進入KeyRead()后,就一直為0x00;Cout,只要按鍵是按下的,這個值就一直為0x01。

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

1:原文中博主的例子,有一個是這樣的,類似小時候玩過的電子表調節時間。

按一個鍵不放手(直到到達指定的功能在放手),從按下,到放手,這個鍵盤包含了兩個功能——切換模式、累計加數(針對他的例子說的功能,意會即可)。其實總的意思就是,從按下,到松手,Trg開始的時候(第一下)為0x01,因為沒有放手,故第二次執行KeyRead()的時候,Trg就變為了0x00;故根據原博主的if(Trg & 0x01)和if(Cont & 0x01)這個的判斷,從按下,到松手,這個兩個函數都會執行過去。[注:原博主的KEY_PLUS的宏定義應該為錯誤的,若為0x02,這個if永遠都不會執行]

上述講述的這個鍵盤的功能,做項目可能用得到。

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

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

   {
   運行代碼;

    b=0;
   }
  }
  
  if(Cout&0x01)    //長按
  {
   b++;
   if(b>20)
   {  
   運行代碼;

    b=0;
   }
  }
}

int main()

{

    KeyRead();

    Key_Proc();

    while(1)

   {

        DelayMs(10);

        break;

   }

}

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

其他的基本相同,這段代碼,主要解決長按按鍵,兩種功能同時出現的事件。

分析:按鍵按一下,即按下立馬松開。鍵盤一開始為高電平,Delay,消除鍵盤按下到放開的反應時間,200MS足以,然后在檢測按鍵輸入狀態,若為高,說明,已經放開了,判斷這是一次短按。

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

         為什么短按里面要加一個b=0呢?如果不加的話,你按鍵盤,若的時間為達到長按的要求,這時候b也會++,可能會出現這樣的情況,連續點擊鍵盤,按下松開,按下松開.......雖然你沒有長按,但是連續的點擊會使b++到20,導致觸發功能。故在短按里面加一個b=0.

大致就是這個樣子了,還有就是在一個程序中,一個鍵盤,在不同的地方有不同的功能,這個又該如何實現呢?


我想出來的就是用switch() case 語句實現。switch判斷處于程序的哪一個階段,在找對應的case去執行就好了。今天太累了,具體怎么實現我就不貼代碼了。


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

使用道具 舉報

沙發
ID:79544 發表于 2015-12-29 10:00 | 只看該作者
樓主辛苦啦,學習啦,學習分享!
回復

使用道具 舉報

板凳
ID:65323 發表于 2019-3-6 09:28 | 只看該作者
原博主的
#define KEY_MODE 0x01    // 模式按鍵
#define KEY_PLUS 0x02     // 加
這個是定義了兩個按鍵,在示例中,KEY_MODE鍵只有短按有效,KEY_PLUS鍵只有長按有效。
回復

使用道具 舉報

地板
ID:299626 發表于 2021-5-14 13:17 | 只看該作者
mark一下,學習了
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲狠狠| 超碰最新在线 | 一区二区三区欧美在线 | 日韩视频在线观看一区二区 | 麻豆hd| 成人深夜福利网站 | 日韩精品视频网 | 日韩五月天| 国产亚洲精品精品国产亚洲综合 | 国产精品欧美一区二区 | 日韩一级免费电影 | 亚洲人人| 精品久久久久久久久久久久 | 精品视频免费 | 国产剧情一区二区三区 | 视频在线亚洲 | 成人久久视频 | 亚洲国产成人在线视频 | 三级视频在线观看电影 | 久久久一二三 | 亚洲最新在线 | 欧美理伦片在线播放 | 7777奇米影视 | 久久久久久亚洲精品不卡 | 中文视频在线 | 麻豆精品一区二区三区在线观看 | 国产精品久久在线 | 污污免费网站 | 奇米超碰在线 | 久久小视频 | 伊人伊成久久人综合网站 | 日本电影韩国电影免费观看 | 久久久网| 国产精品高潮呻吟久久av野狼 | 一级特黄色毛片 | 91欧美| 极品销魂美女一区二区 | 99国产精品视频免费观看一公开 | 天堂影院av | 国产精品国产成人国产三级 | 国产福利免费视频 |