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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2855|回復(fù): 14
收起左側(cè)

5個按鍵分別接在MCU單片機(jī)P1 P3 P4 IO口上,如何用狀態(tài)機(jī)檢測?

  [復(fù)制鏈接]
ID:686513 發(fā)表于 2022-8-20 14:50 | 顯示全部樓層 |閱讀模式
/*******************************************************************************
* 文件名:單片機(jī)MCU按鍵函數(shù)
* 描  述:
* 功  能:
* 參  數(shù):無
*******************************************************************************/                                                                       
#define PD 0xe0|(P1<<4&0x10)|(P4&0x0c)|(P3&0x03)   //P1.0/P3.0 p3.1/P4.2 p4.3組合5個按鍵為1個字節(jié)數(shù)據(jù)
//   1110 0000 |0000 0001   |0000 1100 |0000 0011
//   移位后    |0001 0000   |0000 1100 |0000 0011  

#define S0 0   //狀態(tài)0
#define S1 1   //狀態(tài)1
#define S2 2   //狀態(tài)2
#define S3 3   //狀態(tài)3
                                          
void key_scan()     //放在10ms的定時器中掃描
{
        static u8 state=S0,key_time;
        u8 key;
        key=PD&0xff;                                
       switch(state)                                 
            {
         case S0:                                     //狀態(tài)0
                  if(key!= 0xff) state = S1; break;        //判斷輸入是否為0,為0轉(zhuǎn)入狀態(tài)1
               
        case S1:                                    //狀態(tài)1
                if(key==0xff) state = S0;                //判斷輸入是否為1,為1返回狀態(tài)0
                else                                     //否則,轉(zhuǎn)入狀態(tài)2,執(zhí)行按鍵程序
                 {
                         state=S2;  
                switch(key)
                 {
                                 case 0xfe:
                                  //執(zhí)行任務(wù)1; break;                                                                                          
                                
                                                                                                        
                                 case 0xef:
                                        //執(zhí)行任務(wù)2; break;        
                                       
                                 case 0xfd:
                                        //執(zhí)行任務(wù)3; break;        
                                                        
                                 case 0xfb:
                                //執(zhí)行任務(wù)4; break;        
                                                
                                 case 0xf7:
                                //執(zhí)行任務(wù)5; break;                                                                        
                                 default:break;                                                   
                     }
                     break;

       case S2:                                                  //狀態(tài)2
               if(key==0xff) state = S0;                              //判斷輸入是否為1,為1返回狀態(tài)0
               else if(++key_time==60) {key_time=0;state=S3;}        //否則開始計時,計時結(jié)束轉(zhuǎn)入狀態(tài)3
                 break;

        case S3:                                                  //狀態(tài)3
                    if(key==0xff)  state=S0;                               //判斷輸入是否為1,為1返回狀態(tài)0
                    else if(++key_time==5)                                 //否則開始計時,計時結(jié)束按鍵連擊
                             {
                                key_time=0;
                                switch(key)
                                        {
                                        case 0xfe:                                                                                                                                       
                                                //執(zhí)行任務(wù)6; break;               
                                                
                                        case 0xfd:
                                                //執(zhí)行任務(wù)1; break;                                                                                                                                                                                                                                                                                                
                                      }
                         }
                   break;
  }
}                                                                                                                                                                                                                    如果5個按鍵都接同一組IO口,沒問題,但分別接在不同組IO上(如分別接在P1 P3 P4某個IO口上),目前重定義把5個按鍵組成為1個字節(jié)數(shù)據(jù),再判斷就不能識別了,我也明白switch(key)中的key值不能識別是P1 P3 P4上某個真正的IO口導(dǎo)致的,但我不知道怎么還原到P1 P3 P4上具體識別出哪個IO為有效。
回復(fù)

使用道具 舉報

ID:213173 發(fā)表于 2022-8-20 21:17 | 顯示全部樓層
換一種寫法可能比較好理解

  1. #define PD 0x80   | (P1<<3&0x60)|(P2>>1&0x18)|(P3&0x07)//P1.2~3/P2.4~5/P3.0~2組合7個按鍵為1個字節(jié)數(shù)據(jù)
  2. //      1000 0000    0000 1100    0011 0000   0000 0111
  3. //
  4. /*******************************************************************************
  5. * 文件名:按鍵函數(shù)
  6. * 描  述:
  7. * 功  能:
  8. * 參  數(shù):無
  9. *************************************************/
  10. void key_scan()     //放在10ms的定時器中掃描
  11. {
  12.         static u8  key_time=0;
  13.         static bit key_sign=0;
  14.         u8 key;
  15.         key=PD&0xff;
  16.         if(key!=0xff)//有鍵按下
  17.         {
  18.                 if(++key_time>=2 && !key_sign)//
  19.                 {
  20.                         key_sign=1;
  21.                         switch(key)
  22.                         {
  23.                                 case 0xfe:/*執(zhí)行任務(wù)1;*/ break;
  24.                                 case 0xfd:/*執(zhí)行任務(wù)2;*/ break;
  25.                                 case 0xfb:/*執(zhí)行任務(wù)3;*/ break;
  26.                                 case 0xf7:/*執(zhí)行任務(wù)4;*/ break;
  27.                                 case 0xef:/*執(zhí)行任務(wù)5;*/ break;
  28.                                 //case 0xdf:/*執(zhí)行任務(wù)6;*/ break;
  29.                                 //case 0xbf:/*執(zhí)行任務(wù)7;*/ break;
  30.                                   //case 0x7f:/************/ break;
  31.                                 default:break;
  32.                         }
  33.                 }
  34.         }
  35.         else                 //松手
  36.         {
  37.                 key_time=0;
  38.                 key_sign=0;
  39.         }
  40. }

復(fù)制代碼
回復(fù)

使用道具 舉報

ID:146878 發(fā)表于 2022-8-20 22:59 | 顯示全部樓層
sbit P_KEY1= P1^2;
sbit P_KEY2= P1^3;
sbit P_KEY3......
sbit P_KEY4......
sbit P_KEY5......
void key_scan()     //放在10ms的定時器中掃描
{
        static u8 state=S0,key_time;
        u8 key=0;
        if(P_KEY1)  key|=0x01;
        if(P_KEY2)  key|=0x02;
        if(P_KEY3)  key|=0x04;
        if(P_KEY4)  key|=0x08;
        if(P_KEY5)  key|=0x10;                             
       switch(state)   
       ......
       .......
       .......
}
回復(fù)

使用道具 舉報

ID:146878 發(fā)表于 2022-8-20 23:01 | 顯示全部樓層
這點彎都轉(zhuǎn)不過來的話,那你路還很長啊,小伙子。。
回復(fù)

使用道具 舉報

ID:686513 發(fā)表于 2022-8-21 08:24 | 顯示全部樓層
本帖最后由 zhth1979 于 2022-8-21 09:05 編輯
wulin 發(fā)表于 2022-8-20 21:17
換一種寫法可能比較好理解

上面5個按鍵為:P1.0/P3.0 p3.1/P4.2 p4.3  現(xiàn)在改過來了。 #define PD 0xe0|(P1<<4&0x10)|(P4&0x0c)|(P3&0x03)   //P1.0/P3.0 p3.1/P4.2 p4.3組合5個按鍵為1個字節(jié)數(shù)據(jù) //   1110 0000 |0000 0001   |0000 1100 |0000 0011
//   移位后    |0001 0000   |0000 1100 |0000 0011  
switch(key)中key判斷是PD的值,怎么能說明case 0xfe(1111 1110)中0xfe代表是P3.2口?而不是P1或P2中的某個IO口。  
回復(fù)

使用道具 舉報

ID:686513 發(fā)表于 2022-8-21 08:38 | 顯示全部樓層
本帖最后由 zhth1979 于 2022-8-21 09:05 編輯
pdwdzz 發(fā)表于 2022-8-20 22:59
sbit P_KEY1= P1^2;
sbit P_KEY2= P1^3;
sbit P_KEY3......

上面5個按鍵為:P1.0/P3.0 p3.1/P4.2 p4.3  現(xiàn)在改過來了。 #define PD 0xe0|(P1<<4&0x10)|(P4&0x0c)|(P3&0x03)   //P1.0/P3.0 p3.1/P4.2 p4.3組合5個按鍵為1個字節(jié)數(shù)據(jù) //   1110 0000 |0000 0001   |0000 1100 |0000 0011
//   移位后    |0001 0000   |0000 1100 |0000 0011  
switch(key)中key判斷是PD的值,怎么能說明case 0xfe(1111 1110)中0xfe代表是P3.2口?而不是P1或P2中的某個IO口。  
回復(fù)

使用道具 舉報

ID:686513 發(fā)表于 2022-8-21 08:38 | 顯示全部樓層
本帖最后由 zhth1979 于 2022-8-21 09:04 編輯
pdwdzz 發(fā)表于 2022-8-20 23:01
這點彎都轉(zhuǎn)不過來的話,那你路還很長啊,小伙子。。
上面5個按鍵為:P1.0/P3.0 p3.1/P4.2 p4.3  現(xiàn)在改過來了。 #define PD 0xe0|(P1<<4&0x10)|(P4&0x0c)|(P3&0x03)   //P1.0/P3.0 p3.1/P4.2 p4.3組合5個按鍵為1個字節(jié)數(shù)據(jù) //   1110 0000 |0000 0001   |0000 1100 |0000 0011
//   移位后    |0001 0000   |0000 1100 |0000 0011  
switch(key)中key判斷是PD的值,怎么能說明case 0xfe(1111 1110)中0xfe代表是P3.2口?而不是P1或P2中的某個IO口。      
回復(fù)

使用道具 舉報

ID:213173 發(fā)表于 2022-8-21 18:16 | 顯示全部樓層
zhth1979 發(fā)表于 2022-8-21 08:24
上面5個按鍵為:P1.0/P3.0 p3.1/P4.2 p4.3  現(xiàn)在改過來了。 #define PD 0xe0|(P1

1.jpg
單片機(jī)源程序如下:

  1. #include <reg51.H>
  2. sfr P4   =   0xC0;   //1111,1111 端口4
  3. sfr AUXR =   0x8E;   //0000,0000 輔助寄存器
  4. #define u8 unsigned int
  5. #define u16 unsigned char
  6. #define PD (P1<<4&0x10)|(P4&0x0c)|(P3&0x03)

  7. void Timer0Init()                //10毫秒@12.000MHz
  8. {
  9.         AUXR &= 0x7F;                //定時器時鐘12T模式
  10.         TMOD &= 0xF0;                //設(shè)置定時器模式
  11.         TMOD |= 0x01;                //設(shè)置定時器模式
  12.         TL0 = 0xF0;                //設(shè)置定時初始值
  13.         TH0 = 0xD8;                //設(shè)置定時初始值
  14.         TF0 = 0;                //清除TF0標(biāo)志
  15.         TR0 = 1;                //定時器0開始計時
  16.         EA  = 1;
  17.         ET0 = 1;

  18. }

  19. /***********************************************
  20. * 文件名:按鍵函數(shù)
  21. * 描  述:
  22. * 功  能:
  23. * 參  數(shù):無
  24. *************************************************/
  25. void key_scan()     //放在10ms的定時器中掃描
  26. {
  27.         static u8  key_time=0;
  28.         static bit key_sign=0;
  29.         u8 key;
  30.         key=PD&0x1f;
  31.         if(key!=0x1f)//有鍵按下
  32.         {
  33.                 if(++key_time>=2 && !key_sign)//
  34.                 {
  35.                         key_sign=1;
  36.                         switch(key)
  37.                         {
  38.                                 case 0x1e:P2=0xfe; break;
  39.                                 case 0x1d:P2=0xfd; break;
  40.                                 case 0x1b:P2=0xfb; break;
  41.                                 case 0x17:P2=0xf7; break;
  42.                                 case 0x0f:P2=0xef; break;
  43.                                 default:break;
  44.                         }
  45.                 }
  46.         }
  47.         else                 //松手
  48.         {
  49.                 key_time=0;
  50.                 key_sign=0;
  51.         }
  52. }


  53. void main()
  54. {
  55.         Timer0Init();
  56.         while(1)
  57.         {
  58.         
  59.         }
  60. }

  61. void Timer0Interrupt(void) interrupt 1
  62. {
  63.         TH0 = 0xD8;                //設(shè)置定時初始值
  64.         TL0 = 0xF0;                //設(shè)置定時初始值
  65.         key_scan();
  66. }
復(fù)制代碼
回復(fù)

使用道具 舉報

ID:161164 發(fā)表于 2022-8-22 09:42 | 顯示全部樓層
  1. u8 bdata GPIO = 0xff;
  2. sbit Key0 = GPIO^0;
  3. sbit Key1 = GPIO^1;
  4. sbit Key2 = GPIO^2;
  5. sbit Key3 = GPIO^3;
  6. sbit Key4 = GPIO^4;
  7. u8 PD()
  8. {
  9.         Key4 = (bit)(P0 & 0x01);
  10.         Key3 = (bit)(P4 & 0x08);
  11.         Key2 = (bit)(P4 & 0x04);
  12.         Key1 = (bit)(P3 & 0x02);
  13.         Key0 = (bit)(P3 & 0x01);
  14.         return GPIO;
  15. }
復(fù)制代碼
回復(fù)

使用道具 舉報

ID:686513 發(fā)表于 2022-8-22 10:14 | 顯示全部樓層
本帖最后由 zhth1979 于 2022-8-22 12:39 編輯

找到原因了,這個單機(jī)的P4有ADC輸入,不能做普通的雙向口接按鍵了。把P4去除掉就好了。
回復(fù)

使用道具 舉報

ID:1034262 發(fā)表于 2022-8-22 10:36 | 顯示全部樓層
按鍵都是按時隙讀取,我常用32ms,即每隔32ms讀一次按鍵,值需要花費1~2us。
回復(fù)

使用道具 舉報

ID:686513 發(fā)表于 2022-8-22 12:41 | 顯示全部樓層
coody_sz 發(fā)表于 2022-8-22 10:36
按鍵都是按時隙讀取,我常用32ms,即每隔32ms讀一次按鍵,值需要花費1~2us。

它的速度不是很快嗎?10ms檢測,剛好同時也做按鍵的消抖了。
回復(fù)

使用道具 舉報

ID:509408 發(fā)表于 2022-8-22 14:21 | 顯示全部樓層
zhth1979 發(fā)表于 2022-8-21 08:38
上面5個按鍵為:P1.0/P3.0 p3.1/P4.2 p4.3  現(xiàn)在改過來了。 #define PD 0xe0|(P1

key讀到case :0xfe 把它換成二進(jìn)制1111 1110 對應(yīng)到你的PD宏定義,不就是P3口的P3.0=0?即P30被按下?
說白了還是對位操作不熟練 轉(zhuǎn)不過彎來
回復(fù)

使用道具 舉報

ID:123289 發(fā)表于 2022-8-22 14:43 | 顯示全部樓層
1、一位一位讀出來判斷。
2、各個IO口讀出來,按位分析。
你認(rèn)為哪個方法適合你,就用哪個方法,都行。
回復(fù)

使用道具 舉報

ID:509408 發(fā)表于 2022-8-22 14:43 | 顯示全部樓層
tzs233 發(fā)表于 2022-8-22 14:21
key讀到case :0xfe 把它換成二進(jìn)制1111 1110 對應(yīng)到你的PD宏定義,不就是P3口的P3.0=0?即P30被按下?
說 ...

先掌握好二進(jìn)制和16進(jìn)制轉(zhuǎn)換關(guān)系。我再問你如果KEY= 0xf9,是哪幾個按鍵被按下了 你想得清楚嗎? 代碼精簡了是好事,但犧牲了可讀性。在你不熟練或思路不清晰的時候,還是按樓上的做法封裝成一個函數(shù)。通過變量或返回值讀出來。精簡代碼那是最后的事情。調(diào)試的時候也時如此的,哪能一步到位。
回復(fù)

使用道具 舉報

ID:190577 發(fā)表于 2022-8-24 09:05 | 顯示全部樓層

// 按鍵
#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;//綠光開關(guān)
sbit key3=P0^2;        //藍(lán)
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;
                                                 }
                                //按鍵被按下,狀態(tài)轉(zhuǎn)換到按鍵消抖和確認(rèn)狀態(tài)//
                        break;
                case key_state_1:
                        if(KEY== 0)
                        {
                                temp=1;
                                                            key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                //按鍵仍然處于按下狀態(tài)
                                //消抖完成,key_timer開始準(zhǔn)備計時
                                //狀態(tài)切換到按下時間計時狀態(tài)
                        }
                                                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;
                                                }
                                //按鍵已經(jīng)抬起,回到按鍵初始狀態(tài)
                        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)  //按鍵繼續(xù)按下,計時超過1000ms
                                                                 {
                                                                    
                                        key_return = key_long;  //送回長按事件
                                        key_state_buffer1 = key_state_3;  //轉(zhuǎn)換到等待按鍵釋放狀態(tài)
                                                                 }
                                                          }
                                                }
                                                else
                                                {
                                                         key_return = temp;  //按鍵抬起,產(chǎn)生一次click操作
                             key_state_buffer1 = key_state_0;  //轉(zhuǎn)換到按鍵初始狀態(tài)
                                                }
                       /* if(KEY == 1)
                        {
                                key_return = key_click;  //按鍵抬起,產(chǎn)生一次click操作
                                key_state_buffer1 = key_state_0;  //轉(zhuǎn)換到按鍵初始狀態(tài)
                        }
                        else if(++key_timer_cnt1 >= 100)  //按鍵繼續(xù)按下,計時超過1000ms
                        {
                                key_return = key_long;  //送回長按事件
                                key_state_buffer1 = key_state_3;  //轉(zhuǎn)換到等待按鍵釋放狀態(tài)
                        } */
                        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;  //切回按鍵初始狀態(tài)
                                                 else //按鍵釋放
                                key_state_buffer1 = key_state_0;  //切回按鍵初始狀態(tài)
                        break;
        }
        return key_return;
}
回復(fù)

使用道具 舉報

ID:686513 發(fā)表于 2022-8-24 10:24 | 顯示全部樓層
tzs233 發(fā)表于 2022-8-22 14:43
先掌握好二進(jìn)制和16進(jìn)制轉(zhuǎn)換關(guān)系。我再問你如果KEY= 0xf9,是哪幾個按鍵被按下了 你想得清楚嗎? 代碼精簡 ...

KEY= 0xf9      1111 1001  對應(yīng)我上面的是控制P3.1和P4.2對嗎?不過現(xiàn)在已經(jīng)可以了。
回復(fù)

使用道具 舉報

ID:624769 發(fā)表于 2022-8-24 16:09 來自觸屏版 | 顯示全部樓層
恕我才疏學(xué)淺,       key=PD & 0xff;    這種寫法的意義何在?  為什么不寫成  key=PD | 0x00;    或者  key=PD % 0x100;    ?
回復(fù)

使用道具 舉報

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

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 黄色片网站在线观看 | 日本在线免费看最新的电影 | 一区二区福利视频 | 国产精品久久久亚洲 | 国产www成人| 成人老司机 | 欧美日韩成人影院 | a黄视频| 亚洲精品免费视频 | 亚洲成人免费视频 | 成人av播放 | 欧美一区二区久久 | 欧美高清视频一区 | 久久久久国产精品午夜一区 | 欧美精品综合在线 | 黄色在线免费观看视频网站 | 99欧美精品 | 国产精品视频入口 | 久久久久久成人 | 成人一区二区三区在线观看 | 国产成人高清视频 | 波多野结衣一区二区三区 | 亚洲精品乱码8久久久久久日本 | 五月激情综合网 | 一区二区三区韩国 | 夜夜精品浪潮av一区二区三区 | 国产日韩一区二区三免费高清 | 日韩乱码一二三 | 九九九视频精品 | 中文在线a在线 | 亚洲精品1区 | 久草免费在线视频 | 成人免费一区二区三区视频网站 | 亚洲精品高清视频 | 欧美精品一区二区免费 | 国产1页 | 亚洲成人精品在线观看 | 亚洲精品一区二区网址 | 国产欧美一区二区三区国产幕精品 | 欧美一区二区三区国产 | 欧美99 |