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

標題: 51單片機長按短按連擊2-10次函數 帶仿真演示程序 [打印本頁]

作者: gzyanbo    時間: 2023-12-20 08:24
標題: 51單片機長按短按連擊2-10次函數 帶仿真演示程序
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機源程序如下:
#ifndef _KEY_H
#define _KEY_H

//#include"reg51.h"
sbit KEY_INPUT  =        P1^2;    //  按鍵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 KEY_STATE_5         5
#define KEY_STATE_6         6
#define KEY_STATE_7         7
#define KEY_STATE_8         8
#define KEY_STATE_9         9

#define SINGLE_KEY_TIME     3       //  SINGLE_KEY_TIME*10MS = 30MS  判定單擊的時間長度,軟件消抖
#define KEY_INTERVAL        70      //  KEY_INTERVAL*10MS    = 300MS 判定雙擊的時間間隔(仿真調慢了700MS)實際30-40
#define LONG_KEY_TIME       300     //  LONG_KEY_TIME*10MS   = 3S    判定長按的時間長度


#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 F_KEY                 4        //4擊
#define FIVE_KEY              5        //5擊
#define SIX_KEY               6        //6擊
#define SEVEN_KEY             7        //7擊
#define EIGHT_KEY              8        //8擊
#define NINE_KEY               9        //9擊
#define TEN_KEY                10        //10擊
#define L_KEY                  15       //  long press
//unsigned char key_driver(void);
//unsigned char key_read(void);  
#endif

#include "key.h"
        // =========================== key.c ======================
// ----------------------------------- 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;                      //  讀取當前鍵值

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

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

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

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

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

        default:                                //  特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現在 沒有初始化key_state,第一次執(zhí)行這個函數的時候
            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 )             //  如果是[單擊],不馬上返回單擊按鍵值,先進入 按鍵狀態(tài)1,判斷是否有[雙擊]的可能
            {
                 key_time1 = 0;                 //  清零計時
                 key_state1 = KEY_STATE_1;
            }            
            else                                //  如果不是[單擊],直接返回按鍵值。這里的按鍵值可能是:[長按],[無效按鍵]
            {
                 key_return = key_temp;         //  返回 按鍵值
            }
            break;

        case KEY_STATE_1:                       //  按鍵狀態(tài)1:判定是否有[雙擊]
            if (key_temp == S_KEY)              //  有[單擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[雙擊],但是不馬上返回 有效按鍵值為[雙擊],先進入 按鍵狀態(tài)2,判斷是否有[三擊]
            {              
                key_time1 = 0;                  //  清零 時間間隔
                key_state1 = KEY_STATE_2;       //  改變 按鍵狀態(tài)值
        // key_return = D_KEY;            //  返回 有效按鍵:[雙擊]
   //            key_state1 = KEY_STATE_0;      //  返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                //  有[單擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[單擊]出現,則判定為 [單擊]
            {
                key_time1++;                    //  計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   //  超過 時間間隔
                 {
                      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)              // 有[雙擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[三擊],由于這里只擴展到[三擊],所以馬上返回 有效按鍵值為[三擊]
            {
           //  key_return = T_KEY;
               key_time1 = 0;                                                           // 返回 有效按鍵:[三擊]
                 key_state1 = KEY_STATE_3;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[雙擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[單擊],則判定為 [雙擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return =  D_KEY;       // 返回 有效按鍵 返回 有效按鍵:[2擊】
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;
                          case KEY_STATE_3:                       // 按鍵狀態(tài)3:判定是否有[4擊]
            if (key_temp == S_KEY)              // 有[3擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[三擊]
            {
               //  key_return = F_KEY;            // 返回 有效按鍵:[4擊]
                                                           key_time1 = 0;  
                 key_state1 = KEY_STATE_4;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[3擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[4擊],則判定為 [3擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = T_KEY;         // 返回 有效按鍵:[3擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;
                  case KEY_STATE_4:                       // 按鍵狀態(tài)4:判定是否有[5擊]
            if (key_temp == S_KEY)              // 有[4擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[5擊],由于這里只擴展到[5擊],
            {
                 //key_return = FIVE_KEY;            // 返回 有效按鍵:[5擊]
                                                           key_time1 = 0;
                 key_state1 = KEY_STATE_5;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[4擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[5擊],則判定為 [4擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = F_KEY;         // 返回 有效按鍵:[4擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;
                 case KEY_STATE_5:                       // 按鍵狀態(tài)5:判定是否有[5擊]
            if (key_temp == S_KEY)              // 有[5擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[6擊]
            {
                // key_return = SIX_KEY;            // 返回 有效按鍵:[6擊]
                                                          // key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                                                           key_time1 = 0;
                 key_state1 = KEY_STATE_6;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[5擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[6擊],則判定為 [5擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = FIVE_KEY;         // 返回 有效按鍵:[5擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;
                        case KEY_STATE_6:                       // 按鍵狀態(tài)6:判定是否有[6擊]
            if (key_temp == S_KEY)              // 有[6擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[7擊]
            {
                // key_return = SEVEN_KEY;            // 返回 有效按鍵:[7擊]
                // key_state1 = KEY_STATE_0;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                                                           key_time1 = 0;
                 key_state1 = KEY_STATE_7;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[6擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[7擊],則判定為 [6擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = SIX_KEY;         // 返回 有效按鍵:[6擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;         
                        case KEY_STATE_7:                       // 按鍵狀態(tài)7:判定是否有[7擊]
            if (key_temp == S_KEY)              // 有[7擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[8擊]
            {
                // key_return = EIGHT_KEY;            // 返回 有效按鍵:[8擊]
                // key_state1 = KEY_STATE_0;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                                                                key_time1 = 0;
                key_state1 = KEY_STATE_8;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[7擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[8擊],則判定為 [7擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = SEVEN_KEY;         // 返回 有效按鍵:[7擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;                 
                        case KEY_STATE_8:                       // 按鍵狀態(tài)7:判定是否有[8擊]
            if (key_temp == S_KEY)              // 有[8擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[9擊]
            {
                // key_return = NINE_KEY;            // 返回 有效按鍵:[9擊]
                // key_state1 = KEY_STATE_0;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                                                          key_time1 = 0;
                key_state1 = KEY_STATE_9;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵

            }
            else                                // 有[8擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[9擊],則判定為 [8擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = EIGHT_KEY;         // 返回 有效按鍵:[8擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;                 
                          case KEY_STATE_9:                       // 按鍵狀態(tài)7:判定是否有[9擊]
            if (key_temp == S_KEY)              // 有[9擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[9擊]
            {
                 key_return = TEN_KEY;            // 返回 有效按鍵:[10擊]
                 key_state1 = KEY_STATE_0;      // 返回 按鍵狀態(tài)0,等待新的有效按鍵
            }
            else                                // 有[9擊]后,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[10擊],則判定為 [9擊]
            {
                key_time1++;                    // 計數 時間間隔
                if(key_time1 >= KEY_INTERVAL)   // 超過 時間間隔
                 {
                      key_return = NINE_KEY;         // 返回 有效按鍵:[9擊]
                      key_state1 = KEY_STATE_0; // 返回 按鍵狀態(tài)0,等待新的有效按鍵
                 }              
             }              
             break;                                                         
   //=============================================================================================
        default:                                //  特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現在 沒有初始化key_state,第一次執(zhí)行這個函數的時候
            key_state1 = KEY_STATE_0;
            break;
    }

        return key_return;                      // 返回 按鍵值
}     

// =========================== main.c ======================

#include "reg51.h"
#include "key.c"
#define FOSC 11059200L

#define T1MS (65536-FOSC/12/100)   //1ms timer calculation method in 12T mode
sbit LED1 = P2^0;                   // 定義LEDIO口
sbit LED2 = P2^1;   
sbit LED3 = P2^2;                   // 定義LEDIO口
sbit LED4 = P2^3;
sbit LED5 = P2^4;                   // 定義LEDIO口
sbit LED6 = P2^5;
sbit LED7 = P2^6;
sbit LED8 = P2^7;

unsigned char g_u8_KeyValue;        // 按鍵值
unsigned char g_flag_10ms_key;      // 10ms 計時標志


unsigned char key_read();           // 聲明讀取按鍵函數


void T0_Init_10ms(void)             // timer0,初始化函數 ,定時時間為 10ms
{
    TMOD = 0x01;                    //set timer0 as mode1 (16-bit)
    TL0 = T1MS;                     //initial timer0 low byte
    TH0 = T1MS >> 8;                //initial timer0 high byte
    TR0 = 1;                        //timer0 start running
    ET0 = 1;                        //enable timer0 interrupt
    EA = 1;      
}

// 主函數
void main(void)
{
   // P1^2=1;                                   // P1.0 拉高
    T0_Init_10ms();                             // 定時器0,初始化,定時10ms

    while(1)
    {
        if(g_flag_10ms_key)                     // 等待10ms,定時完成
        {
            g_flag_10ms_key = 0;                // 清零10ms定時標志

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

            switch(g_u8_KeyValue)
            {
                case S_KEY:        LED1=0;LED2=1;LED3=1;LED4=1;LED5=1;LED6=1;LED7=1;LED8=1; break;       // 單擊 點亮LED1
                case D_KEY:        LED1=1;LED2=0;LED3=1;LED4=1;LED5=1;LED6=1;LED7=1;LED8=1; break;        // 雙擊
                                                          case T_KEY:        LED1=1;LED2=1;LED3=0;LED4=1;LED5=1;LED6=1;LED7=1;LED8=1; break;       // 三擊
                                                          case F_KEY:        LED1=1;LED2=1;LED3=1;LED4=0;LED5=1;LED6=1;LED7=1;LED8=1; break;      // 四擊                              
                                                          case FIVE_KEY:     LED1=1;LED2=1;LED3=1; LED4=1; LED5=0;LED6=1;LED7=1;LED8=1;break;    //五擊
                                                          case SIX_KEY:      LED1=1;LED2=1;LED3=1; LED4=1; LED5=1;LED6=0;LED7=1;LED8=1;break;     //六擊
                                                          case SEVEN_KEY:    LED1=1;LED2=1;LED3=1; LED4=1; LED5=1;LED6=1;LED7=0;LED8=1;break;     //7擊
                                                          case EIGHT_KEY:    LED1=1;LED2=1;LED3=1; LED4=1; LED5=1;LED6=1;LED7=1;LED8=0;break;     //8擊
                                                                case NINE_KEY:     LED1=0;LED2=0;LED3=0; LED4=0; LED5=1;LED6=1;LED7=1;LED8=1;break;      //9擊
                                                          case TEN_KEY:      LED1=1;LED2=1;LED3=1; LED4=1; LED5=0;LED6=0;LED7=0;LED8=0;break;      //10擊
                                                        
                                                                case L_KEY: LED1=1;LED2=1;LED3=1; LED4=1; LED5=1;LED6=1;LED7=1;break;      // 長按 熄滅所有LED
            }
        }
    }
}

// timer0 中斷服務程序
void IRQ_T0(void) interrupt 1
{
          TL0 = T1MS;                     //reload timer0 low byte
    TH0 = T1MS >> 8;                //reload timer0 high byte
    g_flag_10ms_key = 1;                        // 置位 10ms 定時標志
}

        
仿真程序: 按鍵單擊多擊長按掃描演示 -狀態(tài)機.7z (135.29 KB, 下載次數: 54)

作者: wmq1517fc    時間: 2024-1-4 15:28
這個程序的主要作用是什么?
作者: cooleaf    時間: 2024-1-4 16:04
可以用少量的按鍵,實現多個按鈕才能實現的功能。




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 欧美区在线 | 一区二区三区免费 | 一级做受毛片免费大片 | 羞羞视频在线观看免费观看 | 97av视频在线 | 国产真实精品久久二三区 | 亚洲成人免费在线观看 | 亚洲一区 | 国产精品一区二区免费看 | 欧美日韩综合精品 | 国产亚洲欧美日韩精品一区二区三区 | 免费在线观看一区二区 | 日本一本视频 | 99这里只有精品视频 | 成人av播放 | 国产在线精品一区二区 | 成人欧美一区二区三区在线播放 | 精品一区二区三区在线视频 | 精品国产欧美一区二区三区成人 | 天天艹逼网 | 午夜综合 | a在线视频| 成人国产精品久久 | 欧美精品a∨在线观看不卡 欧美日韩中文字幕在线播放 | 在线视频一区二区三区 | 亚洲欧美国产毛片在线 | 精品久久久久久久久久久久久久 | 视频在线一区二区 | 一级a爱片久久毛片 | 玖玖国产精品视频 | 精品久久久久久 | 亚洲视频免费在线观看 | 国产一区 | 偷拍亚洲色图 | h片在线免费观看 | 毛片大全 | 天天干.com| 欧美高清一区 | 精品国产一区二区三区久久 | 成人网视频 | 久久乐国产精品 |