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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機定時器中斷按鍵掃描程序如何檢測長按狀態?

[復制鏈接]
跳轉到指定樓層
樓主
ID:601478 發表于 2019-12-24 16:50 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

unsignedchar Trg;

unsignedchar Cont;

voidKeyRead( void )

{

   unsigned char ReadData = PINB^0xff;   // 1

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

   Cont =ReadData;                               // 3

}

網上流傳很廣的3句語句實現按鍵掃描,自己用卻不會用,只能做到檢測單擊按鍵,長按和雙擊檢測不會做,求大佬指點


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

使用道具 舉報

沙發
ID:601478 發表于 2019-12-24 17:24 | 只看該作者
void key_scan()
{
        uchar S,b;
        S = P1^0xff;
  if(0<S && S == R)
        {
                b = T;
                T = S&(S^R);
                R = S;
                if(b != T)
                {
                        if(S == 0x20) {key = 1;        return;}
                  if(S == 0x10) {key = 2; return;}
            if(S == 0x08) {key = 3; return;}
                  if(S == 0x18) {key = 8; return;}
                }
                else
                {
                        if(S == 0x20) {key = 4; return;}
                  if(S == 0x10) {key = 5; return;}
                  if(S == 0x08) {key = 6; return;}
                  if(S == 0x18) {key = 9; return;}
                }
        }
        else
        {
                T = S&(S^R);
                R = S;
        }
}
1238為對應按鍵的單擊標識,4569為對應按鍵的長按標識,共4個按鍵, key_scan()放在中斷函數里面,20MS掃描一次
while(1)
{
        switch (key)
        {
            case......
        }
}循環執行返回按鍵標識的對應程序
問題:無法辨別是單擊或是長按,按了幾下后卡死
回復

使用道具 舉報

板凳
ID:213173 發表于 2019-12-24 23:17 | 只看該作者
不是簡單的3條代碼就搞定的,這只是讀鍵過程,還要有其配套服務程序解讀才能生效。
應用示例:
  1. /*********************************************************
  2. 按時間片運行讀鍵與觸發的單片機程序,定時器0工作在時間片
  3. 定時器1做蜂鳴器振蕩器,LED演示任務狀態。
  4. *********************************************************/
  5. #include "STC89xx.H"                         //單片機頭文件
  6. #include <intrins.h>                        //
  7. #define uint unsigned int                 //宏定義變量uint為無符號整型數據(0-65535)
  8. #define uchar unsigned char         //宏定義變量uchar為無符號字符型數據(0-255)
  9. #define KEY_MODE 0x80                        //按鍵宏定義
  10. #define KEY_PLUO 0x80                        //按鍵宏定義
  11. #define KEY_MODE1 0x40                        //按鍵宏定義
  12. #define KEY_PLUO1 0x40                        //按鍵宏定義
  13. #define LED P1                                        //LED宏定義
  14. sbit Buzzer=P2^3;                                //蜂鳴器端口定義
  15. uchar Trg;                                                //Trg(triger) 單擊鍵值全局變量
  16. uchar Cont;                                                //Cont(continue)長擊鍵值全局變量
  17. uchar Repeat;                                        //蜂鳴器重復次數變量
  18. uchar Intrcnt;                                        //定時器1中斷時標
  19. bit Buzzer_sign=0;                                //蜂鳴器使能標志位
  20. void KeyRead();                                        //按鍵掃描程序
  21. void KeyProc();                                        //按鍵服務程序
  22. void Timer_Init();                                //初始化定時器0/1
  23. void BuzzerSign();                                //蜂鳴器驅動程序

  24. void main()                                                //主函數
  25. {                                                                //初始化數據       
  26.         LED=0xFE;                                        //LED初始化
  27.         Buzzer=1;                                        //蜂鳴器端口初始化
  28.         Timer_Init();                                //初始化定時器初始化

  29.         while(1)                                        //每20ms 執行一次大循環
  30.         {
  31.                 KeyRead();              //將每個子程序都掃描一遍
  32.                 KeyProc();
  33.                 BuzzerSign();
  34. /**************************************************/
  35.                 while(1)
  36.                 {
  37.                         if(Intrcnt>100)                // 一直在等,直到20ms時間到
  38.                         {
  39.                                 Intrcnt=0;
  40.                                 break;               // 返回主循環
  41.                         }
  42.                 }
  43.         }
  44. }

  45. void KeyRead()                                        //讀鍵獲取鍵值
  46. {
  47.     uchar ReadData = P3^0xFF;   //ReadData 臨時變量,"^"按位異或運算:如果a、b兩個值不相同!
  48.                                                                 //則異或結果為1。如果a、b兩個值相同,異或結果為0。
  49.     Trg = ReadData & (ReadData ^ Cont); //獲取短按鍵值
  50.     Cont = ReadData;                    //獲取長按鍵值
  51. }

  52. void KeyProc()                                                //判斷鍵值執行相應任務
  53. {
  54.         uchar cnt_plus,cnt_plus1;                //定義2個計時變量
  55.         if (Trg & KEY_MODE)                         // 如果按下的是KEY_MODE,而且你長按這按鍵也沒有用,
  56.         {
  57.                 Repeat = 1;                                        //賦值蜂鳴器重復次數變量
  58.                 LED=_cror_(LED,1);                        //LED循環右移1位// 可執行任何代碼
  59.         }
  60.         if (Cont & KEY_PLUO)                         //如果KEY_PLUO按著不放
  61.         {
  62.                 cnt_plus++;                              // 計時
  63.                 if(cnt_plus > 50)                         // 20ms*100 = 2S 如果時間到執行長按功能
  64.                 {
  65.                         cnt_plus = 50;                        //計數限制
  66.                         cnt_plus1++;
  67.                         if (cnt_plus1 >= 10)                //20ms*10 = 0.2S(長按功能啟動后每0.2S執行一次下層功能)
  68.                         {
  69.                                 cnt_plus1=0;
  70.                                 LED=_crol_(LED,1);        //LED循環左移1位
  71.                                 Repeat = 1;                        //賦值蜂鳴器重復次數變量
  72.                         }
  73.                 }         
  74.         }
  75.         else cnt_plus=cnt_plus1=0;                 //計時變量清0       
  76. }
  77. void BuzzerSign()                        //蜂鳴器驅動程序
  78. {
  79.         if (Repeat & (Repeat ^ Buzzer_sign))//如果蜂鳴器重復次數變量Repeat>0、
  80.                 //蜂鳴器使能標志Buzzer_sign=0
  81.                 TR1 = 1;                        //開啟定時器1
  82. }

  83. void Timer_Init()                        //200微秒@11.0592MHz
  84. {
  85. //        AUXR &= 0xBF;                        //定時器時鐘12T模式(1T要設置AUXR)
  86.         TMOD &= 0xFF;                        //設置定時器模式8位重載
  87.         TMOD |= 0x22;                        //設置定時器模式8位重載
  88.         TL1 = 0x48;                                //設置定時初值
  89.         TH1 = 0x48;                                //設置定時重載值
  90.         TL0 = 0x48;                                //設置定時初值
  91.         TH0 = 0x48;                                //設置定時重載值
  92.         TF1 = 0;                                        //清除TF1標志
  93.         TR0 = 1;                                        //定時器0開始計時
  94. //        TR1 = 1;                                        //定時器1開始計時
  95.         EA=1;                                                //開總中斷
  96.         ET0=1;                                        //開定時器0中斷       
  97.         ET1=1;                                        //開定時器1中斷       
  98. }

  99. void timer0() interrupt        1        //中斷服務程序(定時器中斷函數timer0)
  100. {                                                                        //interrupt        0:外部中斷0,1:定時器中斷0,
  101.                                                                         //2:外部中斷1,3:定時器中斷1、串行口中斷
  102.                                                                         //中斷程序不需要聲明
  103.         Intrcnt++;                                        //定時器中斷變量200us自+1
  104. }
  105. void timer1() interrupt        3        //中斷服務程序(定時器1中斷函數)
  106. {
  107.         uint Cnt200us;                        //定時器中斷計數變量
  108.         Cnt200us++;                                //中斷變量Cnt200us自+1

  109.         if(Cnt200us<=300)
  110.                 Buzzer=~Buzzer;                //蜂鳴器端口取反
  111.         if(Cnt200us>300)                //檢測中斷的次數>300                       
  112.                 Buzzer=1;                        //蜂鳴器端口清0
  113.                 Buzzer_sign=1;                //蜂鳴器使能標志位置1
  114.         if(Cnt200us>=900)                //檢測中斷的次數>=600
  115.         {                                                        //兩次鳴響之間間隔時間
  116.                 Buzzer_sign=0;                //蜂鳴器使能標志位清0
  117.                 Cnt200us=0;                        //計數清0
  118.                 TR1=0;                                //關閉定時器
  119.                 Repeat--;                        //蜂鳴器重復次數變量自-1                              
  120.                 if(Repeat<=0)                //判斷蜂鳴器重復次數
  121.                         Repeat=0;                //蜂鳴器重復次數變量清0
  122.         }
  123. }
復制代碼
回復

使用道具 舉報

地板
ID:601478 發表于 2019-12-25 08:58 | 只看該作者
wulin 發表于 2019-12-24 23:17
不是簡單的3條代碼就搞定的,這只是讀鍵過程,還要有其配套服務程序解讀才能生效。
應用示例:

我最搞不懂的就是這個按鍵掃描是怎樣做到消抖的,掃描我是放在中斷里面執行的,一旦有觸發信號(假設0x01),read Trg Con的值都為0x01,下一個中斷到來時如果是真的按下(read繼續讀到0x01)那經過這個按鍵掃描算法的處理就變為read 0x01     Trg 0x00  Con 0x01 ,那判斷兩次讀取的值一樣才算消抖啊,但是這樣就判斷不了長按了,因為一直長按 R  T  C 的值都沒變的,還是read 0x01     Trg 0x00  Con 0x01 ,這樣我就搞不懂了
回復

使用道具 舉報

5#
ID:213173 發表于 2019-12-25 10:38 | 只看該作者
PDDDF 發表于 2019-12-25 08:58
我最搞不懂的就是這個按鍵掃描是怎樣做到消抖的,掃描我是放在中斷里面執行的,一旦有觸發信號(假設0x01 ...

這是原作者的解釋,是在特定的程序構架下才有效。
一款精巧的按鍵處理程序.doc (36.5 KB, 下載次數: 51)

回復

使用道具 舉報

6#
ID:601478 發表于 2019-12-25 11:50 | 只看該作者
wulin 發表于 2019-12-25 10:38
這是原作者的解釋,是在特定的程序構架下才有效。

謝謝大佬
回復

使用道具 舉報

7#
ID:475247 發表于 2019-12-25 13:39 | 只看該作者
其實思路很簡單,在定時中斷中判斷一個按健按下來開始計數,然后這樣:if((K1<40) && (K1>5) && (ON_flag==1))//消抖時間+去抖時間+開關標記,后面處理好清0事宜就好了
回復

使用道具 舉報

8#
ID:584103 發表于 2019-12-25 18:37 | 只看該作者
太好了  又學到了新知識  好評
回復

使用道具 舉報

9#
ID:7485 發表于 2019-12-25 18:54 | 只看該作者
和處理鍵抖動一回事,N次檢測仍未釋放就是長按......,N次加或減1,2N次加減2......,快速雙擊道理一樣,檢測的時間間隔不同。
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩亚洲欧美一区 | 性生生活大片免费看视频 | 农村真人裸体丰满少妇毛片 | 国产一级免费视频 | 亚洲视频在线观看一区二区三区 | 久久com | 欧美性吧| 久久精品亚洲精品国产欧美kt∨ | 亚洲一区亚洲二区 | 成人免费视频网站 | 日本午夜网站 | 精品一区二区久久久久久久网站 | 国产激情一区二区三区 | 亚洲成人一二区 | 免费高潮视频95在线观看网站 | 日日天天 | 亚洲一区二区免费看 | 亚洲视频在线观看 | 金莲网 | 久久久久久久电影 | 日韩精品极品视频在线观看免费 | 亚洲 成人 在线 | 羞羞在线视频 | 午夜免费小视频 | 日本久久视频 | 久久久蜜臀国产一区二区 | 精品一区二区三区在线观看国产 | 亚洲天堂久久新 | xxxcom在线观看 | 在线观看视频中文字幕 | 精品久久久久久久久久久久久久 | 亚洲精品日韩在线观看 | 日本成人在线网址 | 精品久久久久久亚洲精品 | 毛片免费在线 | 亚洲精品成人 | 日韩视频在线免费观看 | 久久国产精品精品国产色婷婷 | av黄色免费| 亚洲一区二区视频在线播放 | 欧美精品一区二区三区在线 |