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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2677|回復: 10
收起左側

單片機狀態機按鍵例程如何加入多個按鍵檢測長按短按和連發?

[復制鏈接]
ID:686513 發表于 2022-12-13 09:08 | 顯示全部樓層 |閱讀模式
看了uid:130230的狀態機按鍵掃描,感覺應該可以實現我想要的功能:多按鍵檢測長按,短按和連按(按下不放連加或連減),之前看到的例程多為短按和長按組合,或短按和連按組合,沒有看到過長按和連按如何識別,一直很糾結。
之前發過比較簡單有效的狀態機按鍵檢測的例程,但那個例程里沒有加入長按檢測,如果哪位高手有興趣,也可以在我之前的貼子里修改,不勝感激!
http://www.zg4o1577.cn/bbs/dpj-225323-1.html

下面這個例程是uid:130230高手寫的,原例程只有一個按鍵,現在我把我需要的按鍵放進去了,還加了一些注釋,不知道理解的對不對?還請各位大神們多多指點,先謝謝了!
  .h文件
#ifndef __key_H__
#define __key_H__

#include "xx.h"

#define PD 0x22|(P1&0x51)|(P2<<1&0x80)|(P3<<2&0x0c)   //P1.0/P3.0 p3.1/P4.2 p4.3組合5個按鍵為1個字節數據
//             |0101 0001   |0100 0000 |0000 0011
//   0010 0010 |0101 0001   |1000 0000 |0000 1100       1100 1101 移位后或:1111 1111  PD = 0xff;



sbit up   = P2^6;   //0111 1111  7f
sbit unit = P1^0;   //1111 1110  fe
sbit down = P3^0;   //1111 1011  fb
sbit md   = P1^6;   //1011 1111  bf
sbit k5   = P3^1;   //1111 0111  f7
sbit k6   = P1^4;   //1110 1111  ef

sbit md1  = P1^5;

//按鍵值
typedef enum
{
        NONE_CLICK = 0,    //無按鍵
        SINGLE_CLICK ,     //單擊
        DOUBLE_CLICK,      //雙擊
        LONG_PRESS,        //長按
              LIANFA_CLICK,       //連發
        NUM_KEY,           
}KEY_VALUE_EN;

//按鍵狀態
typedef enum
{
        KEY_IDLE = 0,          //空閑
        KEY_FILTER,            //去抖
        KEY_FIRST,             //第一次按下
        KEY_CHECK_FREE,        //抬起檢測(長按)
        NUM_KEY_STAUS,                        
}KEY_STATUS_EN;


//按鍵掃描狀態
typedef struct
{
        unsigned char Statu;
        unsigned char CntDly;
        unsigned char KeyValue;

}TASK_KEY_STATU_ST;


void Task_Keyscan(void);
void Switch_KeyState(unsigned char state);

#endif


.c文件
#include "key.h"


TASK_KEY_STATU_ST gstKey1 = {0};       //任務鍵狀態


/***********************************************
功能:按鍵掃描
作者:jzb2019年12月27日
備注:50ms運行一次這個函數,理論上可以擴展到n連擊
        最大響應延時500ms(單擊時)
***********************************************/
void Task_Keyscan(void)
{
        unsigned char key;
  key=PD&0xFF;
        
  switch (gstKey1.Statu)
      {
        case KEY_IDLE:                      //按鍵空閑
                                         {
                                                if(key!= 0xFF)
                                                        {
                Switch_KeyState(KEY_FILTER);//按鍵按下了去抖
              }
            }
            break;
                                         
         case KEY_FILTER:
            {
                                                 if(key!= 0xFF)
                                                                {
                                                                        gstKey1.CntDly++;
                                                                        if(gstKey1.CntDly >= 60)
                                                                                {
                                                                                        gstKey1.KeyValue = LONG_PRESS;//長按
                                                                                       
                                                                                        Switch_KeyState(KEY_CHECK_FREE);//抬起檢測
                                                                                }
                                                                 }
             else
                {
                                                                 if(gstKey1.CntDly == 0)
                                                                                {
                                                                                 Switch_KeyState(KEY_IDLE);//如果沒有計數則證明是毛刺濾掉
                                                                                }
                                                                        else
                                                                                {
                                                                                                                Switch_KeyState(KEY_FIRST);//轉到第一次按下狀態
                                                                                }
                 }
               }
               break;
                                                         
                                        case KEY_FIRST:
                                                        {
                                                                if(key == 0xff)//釋放了
                                                                        {        
                                                                                gstKey1.CntDly++;
                                                                                if(gstKey1.CntDly > 10)//500ms
                                                                                        {
                                                                                                gstKey1.KeyValue = SINGLE_CLICK;          //單擊
                                                                                       
                                                                                                Switch_KeyState(KEY_IDLE);//回到空閑
                                                                                        }
                                                                        }
                  else//按下了
                     {
                                                                                        if(gstKey1.CntDly == 0)//沒有計數證明是沒有釋放按鍵的動作
                                                                                          {
                                                                                            
                                                                                           }
                                                                                        else//這個分支里面已經是第二次按下了
                                                                                                {
                                                                                                        gstKey1.KeyValue = DOUBLE_CLICK;
                                                                                                
                                                                                                        Switch_KeyState(KEY_CHECK_FREE);//抬起檢測
                                                                                                }
                                                                                        }
                }
                break;
                                                               
           case KEY_CHECK_FREE:
                                                         {
                                                                 if(key == 0xff)
                                                                                {        
                                                                                        Switch_KeyState(KEY_IDLE);
                                                                                }
                                                         }
                                             break;
                                                         
                                         default :
                                                        {
                                                                Switch_KeyState(KEY_IDLE);
                                                        }
                                                        break;        
        }
}


/****************************************************************************
功能:執行切換狀態的動作,同時清掉當前狀態內的計數
入口:要切換的狀態
作者:jzb 2019年12月27日
備注:暫時先不考慮通用的問題,直接操作全局變量如果擴展按鍵再說
*****************************************************************************/
void Switch_KeyState(unsigned char state)
{
        gstKey1.CntDly = 0;
        gstKey1.Statu = state;
}



回復

使用道具 舉報

ID:96682 發表于 2022-12-13 10:38 | 顯示全部樓層
長按和連按一個意思,有必要細分么?如音量分成 100 短按減 1 長按減 10 以秒來劃定加減數值變化就行了
單鍵復用還是簡單些實用,不然會造成操作者困惑按鍵處在何種狀態
回復

使用道具 舉報

ID:686513 發表于 2022-12-13 11:31 | 顯示全部樓層
wc86110 發表于 2022-12-13 10:38
長按和連按一個意思,有必要細分么?如音量分成 100 短按減 1 長按減 10 以秒來劃定加減數值變化就行了
單 ...

比如我有五個按鍵,一個加,一個減 一個單位切換 一個開關LED燈,一個讓電機啟停;加減要短按+連按,單位切換要短按+長按,LED要短按+長按,電機要短按,在按鍵掃描中是不是要短按,長按和連按都要區分開來,才能控制?
回復

使用道具 舉報

ID:161164 發表于 2022-12-13 13:49 | 顯示全部樓層
zhth1979 發表于 2022-12-13 11:31
比如我有五個按鍵,一個加,一個減 一個單位切換 一個開關LED燈,一個讓電機啟停;加減要短按+連按,單位 ...

按鍵掃描不用區分
得出的鍵值就要區分處理
短按和長按的鍵值用完要清零
連按的鍵值用完不用清零,放開才清零


回復

使用道具 舉報

ID:69038 發表于 2022-12-15 09:42 | 顯示全部樓層
wc86110 發表于 2022-12-13 10:38
長按和連按一個意思,有必要細分么?如音量分成 100 短按減 1 長按減 10 以秒來劃定加減數值變化就行了
單 ...

長按和連按一個意思?表示不解。
按下、保持按下、放開, 是一個按鍵的完整過程,
比如單位時間內:(有效按鍵時)
“長按”主要檢測“保持按下”的時長,
“連按”則是檢測“按下”和“放開”的次數。
回復

使用道具 舉報

ID:686513 發表于 2022-12-30 09:21 | 顯示全部樓層
zhuls 發表于 2022-12-15 09:42
長按和連按一個意思?表示不解。
按下、保持按下、放開, 是一個按鍵的完整過程,
比如單位時間內:( ...

比較贊同您的理解,長按和連按(網上也有叫連發),連按如果是在長按的基礎上判斷,是不是不好區分出來?
回復

使用道具 舉報

ID:996773 發表于 2022-12-30 10:31 | 顯示全部樓層
連擊的話各個人手速和頻率不一樣,連擊很容易被識別成單擊誤操作,代碼時間間隔比較難做到高識別率,我覺得一個按鈕做單擊和長按區分就可以了,不要為了少一個按鈕反而增加操作設備復雜程度
回復

使用道具 舉報

ID:161164 發表于 2022-12-30 10:57 | 顯示全部樓層
2022-12-30_105338.png
回復

使用道具 舉報

ID:651494 發表于 2022-12-30 11:05 | 顯示全部樓層
按鍵的算法有問題,一個簡單地短按,長按,組合鍵,連發,不需要這么繁雜的想法,應該把這個做法徹底拋棄!附上一個程序給樓主參考

key.rar

4.26 KB, 下載次數: 35

回復

使用道具 舉報

ID:686513 發表于 2023-1-7 08:18 | 顯示全部樓層
feeling1791 發表于 2022-12-30 11:05
按鍵的算法有問題,一個簡單地短按,長按,組合鍵,連發,不需要這么繁雜的想法,應該把這個做法徹底拋棄! ...

按說用狀態機檢測按鍵很方便的,在這個掃描程序里同時檢測短按,長按和連發確實不好實現,可能自己愚笨,現在改用別的方法了。
回復

使用道具 舉報

ID:329625 發表于 2024-7-2 09:07 來自觸屏版 | 顯示全部樓層
長按需要加入上時刻和當前狀態判斷  短按的話加個松手檢測 連發的話 去掉松手檢測
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产欧美在线一区 | 在线视频一区二区三区 | 色婷婷久久久久swag精品 | 最近中文字幕免费 | 黑人精品| 国产精品久久久久久av公交车 | 日日操夜夜操天天操 | 看特级黄色片 | 国产精品女人久久久 | 欧美成人在线网站 | 午夜影院在线观看 | 亚洲精品一区二区三区在线 | 久久大陆 | 围产精品久久久久久久 | 另类在线 | 国产精品一区二区久久 | www.免费看片.com | 中文字幕不卡视频在线观看 | 国产欧美日韩久久久 | 成人在线视频一区 | 一区二区av | 亚洲视频三 | 古典武侠第一页久久777 | 欧美性生活网 | 懂色av一区二区三区在线播放 | 欧美精品免费观看二区 | 国产午夜视频 | 日韩成人在线播放 | 亚洲精品区| 日韩在线免费播放 | 国产精品日产欧美久久久久 | 99亚洲精品视频 | 毛片免费观看 | 九一精品 | 一区二区高清 | 一区二区三区日本 | 日韩在线视频播放 | 国产一区欧美一区 | 久久久不卡网国产精品一区 | 亚洲高清一区二区三区 | 亚洲午夜精品视频 |