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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

求教,7個獨立按鍵都不在同一單片機IO上,狀態機按鍵檢測咋實現?

[復制鏈接]
跳轉到指定樓層
樓主
7個獨立按鍵都不在同一IO上,狀態機按鍵檢測咋實現?
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:190577 發表于 2020-3-17 18:44 | 只看該作者
假如3個獨立按鍵,分別對應3個I/O,這3個I/O口分屬于P1、P2、P3的某個引腳,怎樣用狀態機的思路進行檢測,一個按鍵的已經會了,但怎樣用狀態機方法同時檢測3個按鍵的動作?另外如果是組合按鍵(2個或者3個同時按下才生效)又該怎樣處理?能否提供思路!!!
回復

使用道具 舉報

板凳
ID:687694 發表于 2020-3-17 22:23 | 只看該作者
if(a&&b)or if(b&&c)多按鍵狀態判斷,各個IO的狀態判斷跟1個IO一樣的。
回復

使用道具 舉報

地板
ID:709787 發表于 2020-3-17 22:28 來自觸屏版 | 只看該作者
首先,單片機運行速度是很快的。你按一次按鈕的時間,單片機都檢測了一二十次了!不同同時檢測,挨個檢測也行!!要同時按下,用if語句:if(按鈕一按下){if(按鈕二按下){執行動作}}
回復

使用道具 舉報

5#
ID:687694 發表于 2020-3-18 18:56 | 只看該作者
天地一微塵 發表于 2020-3-17 22:28
首先,單片機運行速度是很快的。你按一次按鈕的時間,單片機都檢測了一二十次了!不同同時檢測,挨個檢測也 ...

樓主說的是在狀態機狀態下由狀態標志判斷。
回復

使用道具 舉報

6#
ID:742384 發表于 2020-5-1 17:58 | 只看該作者
用位移將7個IO口狀態賦值到一個變量中
回復

使用道具 舉報

7#
ID:420836 發表于 2020-5-2 02:56 | 只看該作者
如果狀態機檢查基于時間,則必須在實時系統中的不同單芯片計算機之間同步時間。
回復

使用道具 舉報

8#
ID:190577 發表于 2020-7-25 12:47 | 只看該作者
// 按鍵
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
#define key_no 0
#define key_click 1
#define key_double 2
#define key_long 3
sbit KEY = P0^4;
sbit key1=P5^0;// 紅光
sbit key2=P3^0;//綠光開關
sbit key3=P0^2;        //藍
sbit key4=P4^0;        //白
sbit key5=P0^3; //加濕度
sbit key6=P5^2;//自動

static unsigned char key_read(void)
{
        static unsigned char key_state_buffer1 = key_state_0;
        static unsigned char key_timer_cnt1 = 0;
                static         unsigned char temp=0;
        unsigned char key_return = key_no;
       // unsigned char key;

        //key = KEY;  //read the I/O states

        switch(key_state_buffer1)
        {
                case key_state_0:
                        if((KEY == 0)||(key1 == 0)||(key2==0)||(key3==0)||(key4==0)||(key5==0)||(key6==0))
                         {  key_state_buffer1 = key_state_1; temp=0;
                                                         return 0;
                                                 }
                                //按鍵被按下,狀態轉換到按鍵消抖和確認狀態//
                        break;
                case key_state_1:
                        if(KEY== 0)
                        {
                                temp=1;
                                                            key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                //按鍵仍然處于按下狀態
                                //消抖完成,key_timer開始準備計時
                                //狀態切換到按下時間計時狀態
                        }
                                                else if(key1==0)
                                                {
                                                           temp=2;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key2==0)
                                                {
                                                            temp=4;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key3==0)
                                                {
                                                            temp=5;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key4==0)
                                                {
                                                            temp=6;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key5==0)
                                                {
                                                            temp=7;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key6==0)
                                                {
                                                            temp=8;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                        else
                                                {
                                key_state_buffer1 = key_state_0; temp=0;
                                                }
                                //按鍵已經抬起,回到按鍵初始狀態
                        break;  //完成軟件消抖
                case key_state_2:
                                                 if((KEY == 0)||(key1 == 0)||(key2==0)||(key3==0)||(key4==0)||(key5==0)||(key6==0))
                                                {
                                                         key_state_buffer1 = key_state_2;
                                                         if(temp==1)
                                                         {
                                                                 if(++key_timer_cnt1 >= 100)  //按鍵繼續按下,計時超過1000ms
                                                                 {
                                                                    
                                        key_return = key_long;  //送回長按事件
                                        key_state_buffer1 = key_state_3;  //轉換到等待按鍵釋放狀態
                                                                 }
                                                          }
                                                }
                                                else
                                                {
                                                         key_return = temp;  //按鍵抬起,產生一次click操作
                             key_state_buffer1 = key_state_0;  //轉換到按鍵初始狀態
                                                }
                       /* if(KEY == 1)
                        {
                                key_return = key_click;  //按鍵抬起,產生一次click操作
                                key_state_buffer1 = key_state_0;  //轉換到按鍵初始狀態
                        }
                        else if(++key_timer_cnt1 >= 100)  //按鍵繼續按下,計時超過1000ms
                        {
                                key_return = key_long;  //送回長按事件
                                key_state_buffer1 = key_state_3;  //轉換到等待按鍵釋放狀態
                        } */
                        break;
                case key_state_3:  //等待按鍵釋放
                        if((KEY == 0)||(key1 == 0)||(key2==0)||(key3==0)||(key4==0)||(key5==0)||(key6==0)) //按鍵釋放
                                key_state_buffer1 = key_state_3;  //切回按鍵初始狀態
                                                 else //按鍵釋放
                                key_state_buffer1 = key_state_0;  //切回按鍵初始狀態
                        break;
        }
        return key_return;
}

回復

使用道具 舉報

9#
ID:311846 發表于 2020-7-27 17:23 | 只看該作者
有個東西叫寄存器,讀取IO口的寄存器,比如你7個IO同在P1,那么P1寄存器讀出來,對應位為1則為高電平,32自行研究,
回復

使用道具 舉報

10#
ID:213173 發表于 2020-7-28 09:28 | 只看該作者
bbxyliyang 發表于 2020-3-17 18:44
假如3個獨立按鍵,分別對應3個I/O,這3個I/O口分屬于P1、P2、P3的某個引腳,怎樣用狀態機的思路進行檢測, ...

給你寫一個示例程序,你按實際需要修改。

  1. #include <reg51.H>

  2. #define PD 0x80|(P1<<3&0x60)|(P2>>1&0x18)|(P3&0x07)//P1.2~3/P2.4~5/P3.0~2組合7個按鍵為1個字節數據

  3. unsigned char code table[]={//共陽數碼管段碼"0~f-."
  4.                 0xc0,0xf9,0xa4,0xb0,
  5.                 0x99,0x92,0x82,0xf8,
  6.                 0x80,0x90,0x88,0x83,
  7.                 0xc6,0xa1,0x86,0x8e,0xbf,0x7f};

  8. unsigned char KeySec=0;//鍵值變量

  9. //延時程序
  10. void delayms(unsigned int k)
  11. {
  12.         unsigned int i,j;
  13.         for(i=k;i>0;i--)
  14.                 for(j=110;j>0;j--);
  15. }

  16. //按鍵掃描
  17. void keyscan()
  18. {
  19.         static unsigned int count=0;//計數變量
  20.         static bit key_sign=0;     //按鍵狀態標志
  21.         unsigned char time;                        //臨時變量

  22.         if((PD&0xff)!= 0xff)//有按鍵按下
  23.         {
  24.                 count++;                //計數變量自加1
  25.                 if(count>500)
  26.                         count=501;//防止溢出

  27.                 if(count>10 && key_sign==0)//10ms消抖與按鍵狀態識別
  28.                 {//使用組合鍵要適當延長消抖時間
  29.                         key_sign=1;//確認按鍵按下
  30.                         time=PD&0xff;//保存鍵態值
  31.                 }
  32.                 if(count==500)//判斷按下0.5s長按有效
  33.                 {
  34.                         switch(time)
  35.                         {
  36.                                 //單鍵
  37.                                 case 0xfe: KeySec=8;  break;
  38.                                 case 0xfd: KeySec=9;  break;
  39.                                 case 0xfb: KeySec=10; break;
  40.                                 case 0xf7: KeySec=11; break;
  41.                                 case 0xef: KeySec=12; break;
  42.                                 case 0xdf: KeySec=13; break;
  43.                                 case 0xbf: KeySec=14; break;
  44.                         // 組合鍵
  45.                         //        case 0xee: KeySec=?; break;
  46.                         }
  47.                 }
  48.         }
  49.         else //沒有按或按下后松手
  50.         {
  51.                 if(key_sign==1)//判斷是按鍵按下后松手
  52.                 {
  53.                         key_sign=0; //按鍵狀態標志清0
  54.                         if(count>10 && count<500)//小于0.5s判斷為短按
  55.                         {
  56.                                 switch(time)
  57.                                 {
  58.                                         //單鍵
  59.                                         case 0xfe: KeySec=1; break;
  60.                                         case 0xfd: KeySec=2; break;
  61.                                         case 0xfb: KeySec=3; break;
  62.                                         case 0xf7: KeySec=4; break;
  63.                                         case 0xef: KeySec=5; break;
  64.                                         case 0xdf: KeySec=6; break;
  65.                                         case 0xbf: KeySec=7; break;
  66.                                 // 組合鍵
  67.                                 //        case 0xee: KeySec=?; break;
  68.                                 }
  69.                         }
  70.                 }
  71.                 count=0;//計數變量清0
  72.         }
  73. }
  74. //主函數
  75. void main()
  76. {
  77.         P0=table[KeySec];//初始顯示狀態0
  78.         while(1)
  79.         {
  80.                 keyscan();        //按鍵掃描
  81.                 if(KeySec!=0)//刷新顯示
  82.                 {
  83.                         P0=table[KeySec];//顯示鍵值
  84.                         KeySec=0;//鍵值清0
  85.                 }
  86.                 delayms(1);//控制主循環周期1ms
  87.         }
  88. }
復制代碼



回復

使用道具 舉報

11#
ID:808700 發表于 2020-7-28 11:37 | 只看該作者
7個獨立按鍵狀態,直接放進一個8位的數據里面,最高位或者最低位不要
回復

使用道具 舉報

12#
ID:190577 發表于 2020-7-30 22:18 | 只看該作者
感覺狀態機應用比較廣,這個程序我已經學會了狀態的使用。
回復

使用道具 舉報

13#
ID:548551 發表于 2020-7-31 09:29 | 只看該作者
7個獨立按鍵? 7個獨立IO口? 然后你就不知道怎么控制了?
回復

使用道具 舉報

14#
ID:190577 發表于 2020-7-31 11:52 | 只看該作者
xqleft 發表于 2020-7-31 09:29
7個獨立按鍵? 7個獨立IO口? 然后你就不知道怎么控制了?

已經學會了
回復

使用道具 舉報

15#
ID:190577 發表于 2020-7-31 19:11 | 只看該作者
有限狀態機由有限的狀態和相互之間的轉移構成,在任何時候只
能處于給定數目的狀態中的一個。當接收到一個輸入事件時,狀態機產生一個輸出,同時也可能伴隨著狀態的轉移。
#define key_input    PIND.7      // 按鍵輸入口
#define key_state_0  0
#define key_state_1  1
#define key_state_2  2
char read_key(void)
{
static char key_state = 0;
char key_press, key_return = 0;
key_press = key_input;        // 讀按鍵 I/O (狀態機的輸入)
switch (key_state)
{
case key_state_0:        // 按鍵初始態
        if (!key_press) key_state = key_state_1;  // 鍵被按下,狀態轉換到鍵確認態 , 確定下一次按鍵的狀態值
break;
case key_state_1:        // 按鍵確認態
if (!key_press)
{
            key_return = 1;      // 按鍵仍按下,按鍵確認輸出為“1”
            key_state = key_state_2;  // 狀態轉換到鍵釋放態
}
else
            key_state = key_state_0;  // 按鍵已抬起,轉換到 按鍵初始態
       break;
case key_state_2:
            if (key_press) key_state = key_state_0;  //按鍵已釋放,轉換到按鍵初始態
       break;
}  
      return key_return;
}
該簡單按鍵接口函數 read_key()在整個系統程序中應每隔10ms
調用執行一次,每次執行時將先讀取與按鍵連接的 I/O 的電平到變量 key_press 中,然后進入用 switch 結構構成的狀態機。switch 結構中的 case 語句分別實現了 3 個不同狀態的處理判別過程,在每個狀態中將根據狀態的不同,以及 key_press 的值(狀態機的輸入)確定輸出值(key_return),和確定下一次按鍵的狀態值(key_state) 。 函數 read_key()的返回參數提供上層程序使用。返回值為 0 時,表示按鍵無動作;而返回 1 表示有一次按鍵閉合動作,需要進入按鍵處理程序做相應的鍵處理。在函數 read_key()中定義了 3 個局部變量,其中 key_press和key_return為一般普通的局部變量,每次函數執行時,key_press 中保存著剛檢測的按鍵值。key_return 為函數的返回值,總是先初始化為 0,只有在狀態 1 中重新置 1,作為表示按鍵確認的標志返回。變量 key_state 非常重要,它保存著按鍵的狀態值,該變量的值在函數調用結束后不能消失,
必須保留原值,因此在程序中定義為“局部靜態變量” ,用static 聲明。如果使用的語言環境不支持 static 類型的局部變量,應將 key_state 定義為全局變量(關于局部靜態變量的特點請參考相關介紹 C 語言程序設計的書籍) 。
回復

使用道具 舉報

16#
ID:190577 發表于 2021-1-21 15:29 | 只看該作者
bbxyliyang 發表于 2020-7-30 22:18
感覺狀態機應用比較廣,這個程序我已經學會了狀態的使用。

對的,狀態機比較常見的。
回復

使用道具 舉報

17#
ID:190577 發表于 2021-6-14 19:39 | 只看該作者
xqleft 發表于 2020-7-31 09:29
7個獨立按鍵? 7個獨立IO口? 然后你就不知道怎么控制了?

知道控制
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲 欧美 日韩 在线 | 精品综合在线 | 亚洲精选一区 | 久久久久国产精品免费免费搜索 | 99国产精品久久久久老师 | 亚洲精品一区在线 | 特黄特色大片免费视频观看 | 成人综合在线视频 | 精品欧美一区免费观看α√ | 久久久久国产精品 | 综合成人在线 | 成人视屏在线观看 | 国产高清精品一区二区三区 | 国产精品国产三级国产播12软件 | 精品久久香蕉国产线看观看亚洲 | 激情自拍偷拍 | 亚洲视频欧美视频 | www.嫩草| 免费电影av | 一区二区不卡 | 成人黄色三级毛片 | 人碰人操 | 亚av在线| 亚洲国产情侣自拍 | 国产精品夜间视频香蕉 | 国产h在线| 日韩欧美国产一区二区三区 | 亚洲免费影院 | 久久久久国产一区二区三区 | 亚洲一区久久 | 欧美一级在线 | 久久国产精品偷 | 狠狠操操| 国产精品久久久久久久久久 | 久久一区| 一级做a爰片性色毛片视频停止 | 欧美精品一区二区三区在线播放 | 视频1区2区 | 91色在线| 中文字幕不卡在线观看 | 中文字幕视频免费 |