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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

這段網上廣為流傳的MCU按鍵消抖程序怎么理解?

  [復制鏈接]
跳轉到指定樓層
樓主
ID:997026 發表于 2022-2-9 17:15 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
最近在看按鍵消抖程序,在網上找到流傳很廣的利用定時器消抖的單片機程序,這段程序我看很多人都在使用,但是有一部分我百思不得其解,特分享出來與大家探討:

MCU程序如下:

#define const_key_time1  60    /*按鍵去抖動延時的時間*/
#define const_time_0_25s  200    /*0.25秒鐘的時間需要的定時中斷次數*/
#define const_time_1s   800     /*1秒鐘的時間需要的定時中斷次數*/



//定義按鍵S1
sbit Key_S1 = P0^0;


unsigned char ucKeySec = 0;     //被觸發的按鍵編號
unsigned int  uiKeyTimeCnt1 = 0;   //按鍵去抖動延時計數器
unsigned char ucKeyLock1 = 0;   //按鍵觸發后自鎖的變量標志
unsigned char uiKeyCtntyCnt1=0;   //按鍵連續觸發的間隔延時計數器





void Key_Scan(void)  //按鍵掃描
{
        /*掃描S1*/
        if(Key_S1 == 1)            //如果按鍵沒有被按下(高電平),將一些標志位及時清零
        {
                ucKeyLock1 = 0;   //自鎖標志位清
                uiKeyTimeCnt1 = 0;  //按鍵去抖動延時計數器清零
                uiKeyCtntyCnt1 = 0;   //連續累加的時間間隔延時計數器清零
        }
        else if(ucKeyLock1 == 0)        //如果有按鍵按下,且是第一次按下  備注:這里不太理解,為什么ucKeyLock1 == 0可以表示按鍵按下???
        {
                uiKeyTimeCnt1 ++;
                if(uiKeyTimeCnt1 > const_key_time1)   //判定按下
                {
                        uiKeyTimeCnt1 = 0;
                        ucKeyLock1 = 1;
                        ucKeySec = 1;    // 觸發S1
                }
        }
        else if(uiKeyTimeCnt1 < const_time_1s)    //按鍵已按下,按鍵去抖動延時計數器自增到1s
        {
                uiKeyTimeCnt1 ++;   
        }
        else                // 按住累加到1秒后仍然不放手,這個時候進入有節奏的連續觸發
        {
                uiKeyCtntyCnt1 ++;       //連續觸發延時計數器累加
                if(uiKeyCtntyCnt1 > const_time_0_25s)     //按住沒松手,每0.25秒就觸發一次
                {
                        uiKeyCtntyCnt1 = 0;  
                        ucKeySec = 1;      //觸發S1
                }
        }
  }



上面這段程序網上廣為流傳,很多人都在使用,其中有一段我看了好久沒看明白,除了這段,其他地方基本都弄懂了。
就是上面備注紅色的地方,為什么用ucKeyLock1 == 0 可以指示按鍵已經被按下了?因為ucKeyLock1只是定義的一個變量而已,沒有和P0這個IO口發生任何關聯,為什么這段程序中用ucKeyLock1 == 0 就能指示按鍵已經被按下了?按鍵被按下不是應該用Key_S1==0來判斷嗎?


而且ucKeyLock1這個變量在如下程序中當按鍵沒有按下的時候已經被置0了,上面的程序又以ucKeyLock1 == 0 來指示按鍵被按下,感覺是自相矛盾的,不太理解,還是有其他妙用?網上很多都這么寫,但實在是沒理解?希望大家能看懂我在說什么,誰能解釋下呢?感謝!


if(Key_S1 == 1)            //如果按鍵沒有被按下(高電平),將一些標志位及時清零
        {
                ucKeyLock1 = 0;   //自鎖標志位清
                uiKeyTimeCnt1 = 0;  //按鍵去抖動延時計數器清零
                uiKeyCtntyCnt1 = 0;   //連續累加的時間間隔延時計數器清零
        }



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

使用道具 舉報

沙發
ID:213173 發表于 2022-2-9 22:34 | 只看該作者
else if(ucKeyLock1 == 0)        這里else對應上面的if(Key_S1 == 1)表示有按鍵按下,接著的if(ucKeyLock1 == 0)是判斷條件,ucKeyLock1 == 0 才可以執行花括號內語句。也就是按鍵按下后,CPU要執行61次Key_Scan函數(延時消抖)才能滿足條件,ucKeyLock1 = 1;破壞上述條件,按鍵不松手也不會重復執行這段語句。
回復

使用道具 舉報

板凳
ID:514254 發表于 2022-2-10 00:28 | 只看該作者
找找程序段中其他的地方的ucKeyLock1 = 0
回復

使用道具 舉報

地板
ID:161164 發表于 2022-2-10 01:44 | 只看該作者
  1. if(Key_S1 == 1)            //如果按鍵沒有被按下(高電平),將一些標志位及時清零
  2.         {
  3.         }else if(ucKeyLock1 == 0)        
復制代碼

這樣來看會不會清晰一點?
回復

使用道具 舉報

5#
ID:276761 發表于 2022-2-10 09:18 | 只看該作者
你只要理解if-else if就能明白了,上面if(Key_S1 == 1)只要成立,就不會執行else if(ucKeyLock1 == 0),只要上面if(Key_S1 == 1)不成立了,就執行else if(ucKeyLock1 == 0)
回復

使用道具 舉報

6#
ID:997026 發表于 2022-2-10 10:00 | 只看該作者
wulin 發表于 2022-2-9 22:34
else if(ucKeyLock1 == 0)        這里else對應上面的if(Key_S1 == 1)表示有按鍵按下,接著的if(ucKeyLock ...

按我的理解,if-else if-else語句類似條件選擇吧,沒有所謂某個else if對應哪個吧,滿足哪個條件就執行哪個,都不滿足就執行最后else里面的,應該是這樣的邏輯才對。如果要滿足你說的這種判斷,我感覺應該用if-else才對,而不是if-else if-else。ucKeyLock1 == 0這個判斷條件就像是憑空產生的,不理解
回復

使用道具 舉報

7#
ID:997026 發表于 2022-2-10 10:30 | 只看該作者
cliang223 發表于 2022-2-10 09:18
你只要理解if-else if就能明白了,上面if(Key_S1 == 1)只要成立,就不會執行else if(ucKeyLock1 == 0),只 ...

謝謝回復,其實你仔細看這其實是一個if-else if-else選擇語句,并不是if-esle語句,if-else if-else語句中,會判斷每一個if和else if中的表示式,如果滿足就執行,不滿足就執行最后一個else中的語句,邏輯應該是這樣嗎?其實我的意思主要是ucKeyLock1 == 0為啥可以用來判斷按鍵被按下了?

Key_S1 == 1中,Key_S1表示的是IO口,可以檢測到高低電平,用來判斷按鍵狀態,但是ucKeyLock1只是個變量,在上面if(Key_S1 == 1)成立時,已經將ucKeyLock1 == 0清零了,這里怎么又用ucKeyLock1 == 0來表示按鍵被按下???感覺是矛盾的。
回復

使用道具 舉報

8#
ID:213173 發表于 2022-2-10 11:09 | 只看該作者
hxdby 發表于 2022-2-10 10:00
按我的理解,if-else if-else語句類似條件選擇吧,沒有所謂某個else if對應哪個吧,滿足哪個條件就執行哪 ...

ucKeyLock1 == 0這個判斷條件不是憑空產生的,是按鍵松手的結果之一。ucKeyLock1為1也不是按鍵按下的識別標志,是按鍵按下并經過消抖后才能賦值的自鎖標志。在這段代碼中只有 if(Key_S1 == 1) 表示松手,對應的3個else都是在按鍵按下后才順序判斷執行相應語句。
回復

使用道具 舉報

9#
ID:997026 發表于 2022-2-10 12:07 | 只看該作者
wulin 發表于 2022-2-10 11:09
ucKeyLock1 == 0這個判斷條件不是憑空產生的,是按鍵松手的結果之一。ucKeyLock1為1也不是按鍵按下的識別 ...

謝謝回復。

如果按鍵松手,那執行的應該是 if(Key_S1 == 1) 里面的語句,其他都不執行。我的疑問是,如果按鍵按下,那應該執行哪條語句呢?上面的代碼說的是按鍵按下會執行else if(ucKeyLock1 == 0),但是我不太明白,因為ucKeyLock1沒有和P0口發生關聯,也不是標志位,為啥這個能表示按鍵被按下?
回復

使用道具 舉報

10#
ID:276761 發表于 2022-2-10 13:59 | 只看該作者
hxdby 發表于 2022-2-10 10:30
謝謝回復,其實你仔細看這其實是一個if-else if-else選擇語句,并不是if-esle語句,if-else if-else語句 ...

你還是沒有明白if,else if,else,你看上面的程序,if(Key_S1 == 1) ,else if(ucKeyLock1 == 0) ,else if(uiKeyTimeCnt1 < const_time_1s) ,else,不管中間有多少個else if,你說的是會判斷每一個if和else if中的表達式,但不是滿足就執行的,如果前面的if滿足了,后面的else if就算滿足了都不會執行的,就是一次只能執行一個,先滿足的先執行。那么if(Key_S1 == 1),如果滿足,表示按鍵沒有按下,那么后面的else if就不會執行了,如果不滿足,說明按鍵按下了,那么就開始判斷后面的else if,第一個else if(ucKeyLock1 == 0),是定義的一個變量,是滿足的,那么就執行它。下面你就應該明白了吧
回復

使用道具 舉報

11#
ID:997026 發表于 2022-2-10 19:45 | 只看該作者
cliang223 發表于 2022-2-10 13:59
你還是沒有明白if,else if,else,你看上面的程序,if(Key_S1 == 1) ,else if(ucKeyLock1 == 0) ,else ...

非常感謝你的回復。

我確實弄錯了else if這個語句,因為比較少用else if, 以為是一個選擇語句,其實這個選擇是由條件的,就是必須是第一個if條件不滿足的時候才會執行后面的語句,其實if-else if-else語句相當于是if else語句的變體,后面的所有else if相當于是嵌套在if -else的else后面的,if滿足,永遠不會執行后面的else if, if不滿足,才會按照后面else if順序判斷執行。

這個程序很精妙,關鍵在于ucKeyLock這個變量,當按鍵按下的時候,其實ucKeyLock仍然是為0的,如果此時按一下松手,則觸發一個鍵值輸出,程序跳轉到Key_S1==1下。如果持續按不松手,則ucKeyLock被賦值1,同時跳轉到后面的程序。

經過大家的積極回復,我大概搞懂了,感謝大家的幫助!
回復

使用道具 舉報

12#
ID:1063563 發表于 2023-6-4 11:48 | 只看該作者
else if(uiKeyTimeCnt1 < const_time_1s)    //按鍵已按下,按鍵去抖動延時計數器自增到1s
        {
                uiKeyTimeCnt1 ++;   
        }
這段是什么意思沒看懂
回復

使用道具 舉報

13#
ID:883242 發表于 2023-6-4 15:55 | 只看該作者
芯菲 發表于 2023-6-4 11:48
else if(uiKeyTimeCnt1 < const_time_1s)    //按鍵已按下,按鍵去抖動延時計數器自增到1s
        {
   ...

按下1s以內單次按下,按下時間超過1s進入連續按下狀態。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲手机视频在线 | 久久国产区 | 欧美一区二区三区久久精品视 | 亚洲第一av | 中文字幕 国产 | 欧美精品一二三区 | 午夜99| www.天天操 | 日韩免费一区二区 | 久久99久久 | 久久久综合 | 一区二区三区精品视频 | 在线亚洲一区 | 亚洲国产高清高潮精品美女 | 97久久超碰 | 一级毛片中国 | 国产精品成人一区二区 | av电影一区二区 | 午夜av毛片 | 成人av网站在线观看 | 色播久久| 日本一区二区三区四区 | 福利视频网站 | 午夜视频在线免费观看 | 国产精品99久久久久久久vr | 亚洲精品在线免费看 | 黑人一级黄色大片 | 中文字幕国产视频 | 成人精品一区二区三区四区 | 成人久久18免费网站 | 国产精品一区二区在线播放 | 国产成人精品免费视频 | 四虎影音 | 亚洲iv一区二区三区 | 久久最新 | 一本一道久久a久久精品综合蜜臀 | 久久亚洲精品国产精品紫薇 | 美日韩精品 | 亚洲欧美日本在线 | 国产精品久久av | 亚洲网站在线播放 |