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

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

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

單片機(jī)狀態(tài)機(jī)按鍵程序怎么能響應(yīng)兩個(gè)不同時(shí)長(zhǎng)的長(zhǎng)按?

[復(fù)制鏈接]
ID:91521 發(fā)表于 2019-10-25 18:25 | 顯示全部樓層 |閱讀模式
我在學(xué)習(xí)狀態(tài)機(jī)按鍵程序時(shí)遇到一個(gè)問題:我用狀態(tài)機(jī)按鍵方法,只能實(shí)現(xiàn)一個(gè)長(zhǎng)按事件的響應(yīng)。如果要能夠響應(yīng)兩個(gè)不同時(shí)長(zhǎng)的長(zhǎng)按,程序該怎么修改呢?我試著修改了一下,可是不成功,百思不得其解,只好請(qǐng)各位高人指點(diǎn)迷津!

單片機(jī)程序如下(紅色部分是我自己修改的):

#include<reg52.h>

sbit LED0 = P0^7;
sbit LED1 = P0^6;
sbit LED2 = P0^5;
sbit LED3 = P0^4;

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

sbit KEY_INPUT = P2^4;    //  按鍵IO

#define KEY_STATE_0         0       //  按鍵狀態(tài)
#define KEY_STATE_1         1
#define KEY_STATE_2         2
#define KEY_STATE_3         3
#define KEY_STATE_4         4

#define SINGLE_KEY_TIME     3       //  SINGLE_KEY_TIME*10MS = 30MS     判定單擊的時(shí)間長(zhǎng)度,軟件消抖
#define KEY_INTERVAL        30      //  KEY_INTERVAL*10MS    = 300MS 判定雙擊的時(shí)間間隔
#define LONG_KEY_TIME       300     //  LONG_KEY_TIME*10MS   = 3S   判定長(zhǎng)按的時(shí)間長(zhǎng)度


#define N_KEY               0       //  no click
#define S_KEY               1       //  single click
#define D_KEY               2       //  double click
#define T_KEY               3       //  Triple click
#define L_KEY               10      //  long press

unsigned char g_u8_KeyValue;        // 按鍵值

// ----------------------------------- key_driver --------------------------
unsigned char key_driver(void)
{     
    static unsigned char key_state = 0;
    static unsigned int  key_time = 0;
    unsigned char key_press, key_return;

    key_return = N_KEY;                         //  清除 返回按鍵值

    key_press = KEY_INPUT;                      //  讀取當(dāng)前鍵值

    switch (key_state)     
    {      
        case KEY_STATE_0:                       //  按鍵狀態(tài)0:判斷有無按鍵按下
            if (!key_press)                     //  有按鍵按下
            {
                key_time = 0;                   //  清零時(shí)間間隔計(jì)數(shù)
                key_state = KEY_STATE_1;        //  然后進(jìn)入 按鍵狀態(tài)1
            }        
            break;

        case KEY_STATE_1:                       //  按鍵狀態(tài)1:軟件消抖(確定按鍵是否有效,而不是誤觸)。按鍵有效的定義:按鍵持續(xù)按下超過設(shè)定的消抖時(shí)間。
            if (!key_press)                     
            {
                key_time++;                     //  一次10ms
                if(key_time>=SINGLE_KEY_TIME)   //  消抖時(shí)間為:SINGLE_KEY_TIME*10ms = 30ms;
                {
                    key_state = KEY_STATE_2;    //  如果按鍵時(shí)間超過 消抖時(shí)間,即判定為按下的按鍵有效。按鍵有效包括兩種:?jiǎn)螕艋蛘唛L(zhǎng)按,進(jìn)入 按鍵狀態(tài)2, 繼續(xù)判定到底是那種有效按鍵
                }
            }         
            else key_state = KEY_STATE_0;       //  如果按鍵時(shí)間沒有超過,判定為誤觸,按鍵無效,返回 按鍵狀態(tài)0,繼續(xù)等待按鍵
            break;

        case KEY_STATE_2:                       //  按鍵狀態(tài)2:判定按鍵有效的種類:是單擊,還是長(zhǎng)按
            if(key_press)                       //  如果按鍵在 設(shè)定的長(zhǎng)按時(shí)間 內(nèi)釋放,則判定為單擊
            {
                 key_return = S_KEY;            //  返回 有效按鍵值:?jiǎn)螕?br />                  key_state = KEY_STATE_0;       //  返回 按鍵狀態(tài)0,繼續(xù)等待按鍵
            }
            else
            {
                key_time++;                     

                if(key_time >= LONG_KEY_TIME)   //  如果按鍵時(shí)間超過 設(shè)定的長(zhǎng)按時(shí)間(LONG_KEY_TIME*10ms=300*10ms=3000ms), 則判定為 長(zhǎng)按
                {
                    key_return = L_KEY;         //  返回 有效鍵值值:長(zhǎng)按
                    key_state = KEY_STATE_3;    //  去狀態(tài)3,等待按鍵釋放
                }
            }
            break;

      case KEY_STATE_3:    //我自己添加的代碼開始                     
            if(key_press)                       
            {
                 key_return = L_KEY;            
                 key_state = KEY_STATE_0;      
            }
            else
            {
                key_time++;                     

                if(key_time >= 600)   
                {
                    key_return = 5;         
                    key_state = KEY_STATE_4;   
                }
            }
            break;    //我自己添加的代碼結(jié)束


      case KEY_STATE_4:                         //  等待按鍵釋放
          if (key_press)
          {
              key_state = KEY_STATE_0;          //  按鍵釋放后,進(jìn)入 按鍵狀態(tài)0 ,進(jìn)行下一次按鍵的判定
          }        
          break;

        default:                                //  特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現(xiàn)在 沒有初始化key_state,第一次執(zhí)行這個(gè)函數(shù)的時(shí)候
            key_state = KEY_STATE_0;
            break;
    }

    return  key_return;                         //  返回 按鍵值
}

// ----------------------------------- key_read --------------------------------
unsigned char key_read(void)                           
{
    static unsigned char key_state1=0, key_time1=0;
    unsigned char key_return,key_temp;

    key_return = N_KEY;                         //  清零 返回按鍵值

    key_temp = key_driver();                    //  讀取鍵值

    switch(key_state1)
    {         
        case KEY_STATE_0:                       //  按鍵狀態(tài)0:等待有效按鍵(通過 key_driver 返回的有效按鍵值)
            if (key_temp == S_KEY)          //  如果是[單擊],不馬上返回單擊按鍵值,先進(jìn)入 按鍵狀態(tài)1,判斷是否有[雙擊]的可能
            {
                 key_time1 = 0;                 //  清零計(jì)時(shí)
                 key_state1 = KEY_STATE_1;
            }            
            else                                //  如果不是[單擊],直接返回按鍵值。這里的按鍵值可能是:[長(zhǎng)按],[無效按鍵]
            {
                 key_return = key_temp;         //  返回 按鍵值
            }
            break;

        case KEY_STATE_1:                       //  按鍵狀態(tài)1:判定是否有[雙擊]
            if (key_temp == S_KEY)              //  有[單擊]后,如果在 設(shè)定的時(shí)間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內(nèi),再次有[單擊],則為[雙擊],但是不馬上返回 有效按鍵值為[雙擊],先進(jìn)入 按鍵狀態(tài)2,判斷是否有[三擊]
            {
                key_time1 = 0;                  //  清零 時(shí)間間隔
                key_state1 = KEY_STATE_2;       //  改變 按鍵狀態(tài)值
            }
            else                                //  有[單擊]后,如果在 設(shè)定的時(shí)間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內(nèi),沒有[單擊]出現(xiàn),則判定為 [單擊]
            {
                key_time1++;                    //  計(jì)數(shù) 時(shí)間間隔
                if(key_time1 >= KEY_INTERVAL)   //  超過 時(shí)間間隔
                 {
                    key_return = S_KEY;         //  返回 有效按鍵:[單擊]
                    key_state1 = KEY_STATE_0;   //  返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;

        case KEY_STATE_2:                       // 按鍵狀態(tài)2:判定是否有[三擊]
            if (key_temp == S_KEY)              // 有[雙擊]后,如果在 設(shè)定的時(shí)間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內(nèi),再次有[單擊],則為[三擊],由于這里只擴(kuò)展到[三擊],所以馬上返回 有效按鍵值為[三擊]
            {
                 key_return = T_KEY;            // 返回 有效按鍵:[三擊]
                 key_state1 = KEY_STATE_0;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[雙擊]后,如果在 設(shè)定的時(shí)間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內(nèi),沒有[單擊],則判定為 [雙擊]
            {
                key_time1++;                    // 計(jì)數(shù) 時(shí)間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時(shí)間間隔
                 {
                      key_return = D_KEY;       // 返回 有效按鍵:[雙擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;

        default:                                //  特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現(xiàn)在 沒有初始化key_state,第一次執(zhí)行這個(gè)函數(shù)的時(shí)候
            key_state1 = KEY_STATE_0;
            break;
    }

    return key_return;                          // 返回 按鍵值
}

void main()
{
    ENLED = 0;
    ADDR3 = 1;
    ADDR2 = 1;
    ADDR1 = 1;
    ADDR0 = 0;

    P2 = 0xF7;

    TMOD = 0x01;
    TH0 = 0xDC;
    TL0 = 0x00;
    TR0 = 1;
     
    while(1)
    {
        if(TF0 == 1)                         // 等待10ms,定時(shí)完成
        {
            TF0 = 0;                    // 清零10ms定時(shí)標(biāo)志
            TH0 = 0xDC;
            TL0 = 0x00;

            g_u8_KeyValue = key_read();             // 讀取按鍵值

            switch(g_u8_KeyValue)
            {
                case 5: LED1 = !LED1; break;    // 單擊 取反LED1
                case D_KEY: LED2 = !LED2; break;    // 雙擊 取反LED2
                case L_KEY: LED3 = !LED3; break;    // 三擊 取反LED3
//                case L_KEY: LED_ALL_ON(); break;    // 長(zhǎng)按 點(diǎn)亮所有的LED
            }
        }
    }
}
回復(fù)

使用道具 舉報(bào)

ID:94031 發(fā)表于 2019-10-26 11:27 | 顯示全部樓層
用了定時(shí)0的中斷標(biāo)志TF0,卻沒有初始化定時(shí)器0以及相應(yīng)的中斷程序,說明沒有理解程序原理。
回復(fù)

使用道具 舉報(bào)

ID:405193 發(fā)表于 2019-10-26 22:09 | 顯示全部樓層
你case KEY_STATE_3不能依照 case KEY_STATE_2這樣復(fù)制下來,都有key_time++;    你應(yīng)該在   case KEY_STATE_2里根據(jù)設(shè)置key_time  不同的時(shí)間來設(shè)置功能達(dá)到  case KEY_STATE_3的目的。  
回復(fù)

使用道具 舉報(bào)

ID:192020 發(fā)表于 2024-6-28 18:21 | 顯示全部樓層
應(yīng)該是可以的,但是出現(xiàn)6秒長(zhǎng)按時(shí)必然先出現(xiàn)一次3秒長(zhǎng)按,這兩個(gè)沒做互斥。當(dāng)響應(yīng)3秒長(zhǎng)按功能時(shí)別松手繼續(xù)按住看看能不能出現(xiàn)6秒的功能
回復(fù)

使用道具 舉報(bào)

ID:329625 發(fā)表于 2024-7-2 09:05 來自手機(jī) | 顯示全部樓層
不同時(shí)長(zhǎng)后 判斷有無松手檢測(cè) 然后再判斷按鍵時(shí)長(zhǎng) 你可以試試
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 成人三级在线播放 | 一级高清视频 | 久久久激情 | 色综合网站| 天天色天天色 | 伊人网伊人网 | 中文字字幕一区二区三区四区五区 | 久久69精品久久久久久久电影好 | 欧美精品成人 | 久久久久91 | 欧美网站一区 | 国产精品毛片一区二区在线看 | 国产精品欧美一区二区三区不卡 | 国产精品777一区二区 | 国产一级大片 | 成在线人视频免费视频 | 日韩av一区二区在线观看 | 亚洲aⅴ| 精品欧美一区二区中文字幕视频 | 日批的视频 | 色秀网站 | 国产a一区二区 | 欧美成人第一页 | 在线日韩中文字幕 | 亚洲一区二区在线 | 久久久精品网站 | 一区二区精品电影 | 伊人免费在线观看 | 国产a级黄色录像 | 亚洲视频www | 午夜精品 | 国产91丝袜在线播放 | 久久国产视频网站 | 成人激情视频免费观看 | 国产日本精品视频 | 久久久久久久久久久久一区二区 | 99久久99久久精品国产片果冰 | 国精产品一区二区三区 | 日本一区二区三区在线观看 | 在线观看成年视频 | 天天久久 |