在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【RTT大賽作品連載】 按鍵濾波,按下,松手,長按,短按

閑來無事玩單片機呀 ? 2021-12-06 09:23 ? 次閱讀

本文主要以AB32VG1作為主控,結(jié)合板載按鍵實現(xiàn)按鍵的軟件濾波,按下時間判斷(長按,短按),按下判斷,松手判斷等,可以應(yīng)對各種按鍵使用的場合,多種按鍵方式結(jié)合使用可以在只有一個按鍵的情況下實現(xiàn)多種按鍵操作邏輯。

一、創(chuàng)建工程

創(chuàng)建工程比較簡單,在這里不在贅述,可以參考官方的操作文檔:https://file.elecfans.com/web2/M00/14/6F/pYYBAGE-y4WAGoojANBtfI0No2g719.pdf

二、按鍵邏輯初始化

1. 創(chuàng)建按鍵線程

static void KEY_ThreadManage(void)
{
    rt_thread_t key_thread;

    key_thread = rt_thread_create("KEY Thread Manage",     /*線程名字*/
                                   KEY_ManageEntry,/*線程入口函數(shù)*/
                                   RT_NULL, /*線程入口函數(shù)參數(shù)*/
                                   2048,    /*線程棧大小*/
                                   5,       /*線程優(yōu)先級*/
                                   10);     /*線程時間片*/
                                   
    rt_thread_startup (key_thread);
}

2. 按鈕初始化

初始化函數(shù)需要在mian函數(shù)的while循環(huán)之前調(diào)用,也可以使用RT-Thread提供的硬件初始化宏來初始化。

本程序中設(shè)置了按鍵的狀態(tài)有三種:

typedef enum
{
    KEY_PRESSED  = 0u,
    KEY_RELEASED = 1u,
    KEY_UNKNOW   = 2u
} E_KeySt;

主要作用:

1)設(shè)置按鍵引腳;

2)設(shè)置引腳狀態(tài)為輸入;

3)設(shè)置按鍵濾波結(jié)構(gòu)體,設(shè)置按鍵初始狀態(tài)為UNKNOW

原理圖如下:

S2 — PF1

S3 — PF0

S4 — PA2

poYBAGGqFY6Ae6-3AAAoQKbRhtg315.png

void KEY_AppInit(void)
{
    uint8_t i = 0u;

    Key_pin.Key1 = rt_pin_get("PF.1");
    Key_pin.Key2 = rt_pin_get("PF.0");
    Key_pin.Key3 = rt_pin_get("PA.2");

    rt_pin_mode(Key_pin.Key1, PIN_MODE_INPUT);
    rt_pin_mode(Key_pin.Key2, PIN_MODE_INPUT);
    rt_pin_mode(Key_pin.Key3, PIN_MODE_INPUT);

    for(i=0; i

三、按鍵濾波

按鍵濾波邏輯:檢測按鍵引腳狀態(tài)是否連續(xù)40ms都為低電平,如果都為低電平的話就認為是真的按下了,邏輯如下,修改KEY_SW_FILTER_THD可以修改按鍵的濾波時間,當前值為4,按鍵線程的運行周期為10ms,所以濾波時間為40ms:

static void KEY_KeySwFilterCounting(S_KeyStatusStr *paraKeySta)
{
    if(0u == paraKeySta->m_key_pin_st)
    {
        if(paraKeySta->m_filter_cnt >= KEY_SW_FILTER_THD)
        {
            paraKeySta->m_status = KEY_PRESSED;
        }
        else
        {
            paraKeySta->m_filter_cnt ++;
        }
    }
    else
    {
        paraKeySta->m_filter_cnt = 0u;
        paraKeySta->m_status = KEY_RELEASED;
    }
}

四、按鍵按下狀態(tài)判斷
按鍵按下狀態(tài)的判斷邏輯:

1)代碼中有一個變量定義為用于記錄上一個周期的按鍵按下的狀態(tài)

static E_KeySt Last_KeyStatus[KEY_NUM] = {KEY_UNKNOW, KEY_UNKNOW, KEY_UNKNOW};

2)讀取濾波之后的按鍵狀態(tài)變量

3)如果上一次按鍵的狀態(tài)為KEY_RELEASED,本次的按鍵狀態(tài)為KEY_PRESSED,則認為按鍵按下了

        if((KEY_PRESSED == KEY_GetKeyStatus(i))
            && (KEY_RELEASED== Last_KeyStatus[i]))
        {
            key_Pressed[i] = KEY_PRESSED;
        }

五、按鍵松手狀態(tài)判斷

與按鍵的按下邏輯相似,不同點在于上一次的按鍵按下狀態(tài)為KEY_PRESSE,這一次為KEY_RELEASED就認為按鍵釋放了。

        if((KEY_RELEASED == KEY_GetKeyStatus(i))
            && (KEY_PRESSED == Last_KeyStatus[i]))
        {
            key_Pressed[i] = KEY_RELEASED;
        }

六、按鍵按下時間判斷

按鍵按下時間可以用來區(qū)別按鍵是長安還是短按,可以用一個按鍵實現(xiàn)兩種或多種功能。

具體實現(xiàn)方式需要結(jié)合按鍵松手判斷一起時間,當按鍵按下的時候需要一個counter來記錄按鍵按下的時間,然后按鍵松手的時候讀取這個counter值的時間來判斷是長按還是短按。

時間counter的累積邏輯為:

if((KEY_PRESSED == KEY_GetKeyStatus(i))
            && (KEY_PRESSED == Last_KeyStatus[i]))
        {
            key_pressed_counter[i] ++;
        }

七、實現(xiàn)效果

按鈕按下會打印:Key [1,2,3] Pressed

按鈕松開會打印:Key [1,2,3] Released, 同時會打印按下的時間:Hold Key [1,2,3] for xxx ms

pYYBAGGqHRGANUz2AALpzzOwAxg160.png

八、代碼實現(xiàn)

貼上完整代碼實現(xiàn),有問題歡迎指正

代碼直接粘貼可能存在遺漏,建議移步gitee:https://gitee.com/hehung/ab32-vg1_-rt-thread

.c文件

#include "app_key.h"
#include "board.h"

typedef struct
{
uint8_t Key1;
uint8_t Key2;
uint8_t Key3;
} S_key_pin;

typedef struct
{
uint8_t m_filter_cnt;
E_KeySt m_status;
uint8_t m_key_pin_st;
} S_KeyStatusStr;

S_key_pin Key_pin;
S_KeyStatusStr Key_Status[KEY_NUM];
E_KeySt key_Pressed[KEY_NUM] = {KEY_UNKNOW, KEY_UNKNOW, KEY_UNKNOW};
uint16_t key_pressed_counter[KEY_NUM] = {0, 0, 0};


static void KEY_ReadKeyLevel(void);
static void KEY_KeySwFilterCounting(S_KeyStatusStr *paraKeySta);
static void KEY_KeySwFilter(void);
static void KEY_ManageEntry(void *parameter);
static void KEY_ThreadManage(void);
static void KEY_JudgeKeyPressed(void);


void KEY_AppInit(void)
{
uint8_t i = 0u;

Key_pin.Key1 = rt_pin_get("PF.1");
Key_pin.Key2 = rt_pin_get("PF.0");
Key_pin.Key3 = rt_pin_get("PA.2");

rt_pin_mode(Key_pin.Key1, PIN_MODE_INPUT);
rt_pin_mode(Key_pin.Key2, PIN_MODE_INPUT);
rt_pin_mode(Key_pin.Key3, PIN_MODE_INPUT);

for(i=0; i {
Key_Status[i].m_filter_cnt = 0u;
Key_Status[i].m_key_pin_st = 0u;
Key_Status[i].m_status = KEY_UNKNOW;
}

KEY_ThreadManage();
}

E_KeySt KEY_GetKeyStatus(uint8_t paraKeyNum)
{
return Key_Status[paraKeyNum].m_status;
}

E_KeySt KEY_GetKeyPressedStatus(uint8_t paraKeyNum)
{
return key_Pressed[paraKeyNum];
}


static void KEY_ReadKeyLevel(void)
{
Key_Status[KEY_NUM_1].m_key_pin_st = (uint8_t)rt_pin_read(Key_pin.Key1);
Key_Status[KEY_NUM_2].m_key_pin_st = (uint8_t)rt_pin_read(Key_pin.Key2);
Key_Status[KEY_NUM_3].m_key_pin_st = (uint8_t)rt_pin_read(Key_pin.Key3);
}

static void KEY_KeySwFilterCounting(S_KeyStatusStr *paraKeySta)
{
if(0u == paraKeySta->m_key_pin_st)
{
if(paraKeySta->m_filter_cnt >= KEY_SW_FILTER_THD)
{
paraKeySta->m_status = KEY_PRESSED;
}
else
{
paraKeySta->m_filter_cnt ++;
}
}
else
{
paraKeySta->m_filter_cnt = 0u;
paraKeySta->m_status = KEY_RELEASED;
}
}

static void KEY_KeySwFilter(void)
{
KEY_KeySwFilterCounting(&Key_Status[KEY_NUM_1]);
KEY_KeySwFilterCounting(&Key_Status[KEY_NUM_2]);
KEY_KeySwFilterCounting(&Key_Status[KEY_NUM_3]);
}

static void KEY_JudgeKeyPressed(void)
{
uint8_t i = 0u;
static E_KeySt Last_KeyStatus[KEY_NUM] = {KEY_UNKNOW, KEY_UNKNOW, KEY_UNKNOW};

for(i=0u; i {
/*Key pressed this cycle*/
if((KEY_PRESSED == KEY_GetKeyStatus(i))
&& (KEY_RELEASED == Last_KeyStatus[i]))
{
key_Pressed[i] = KEY_PRESSED;
key_pressed_counter[i] = 0u;
rt_kprintf("KEY: Key %d Pressedn", i);

}
else if((KEY_RELEASED == KEY_GetKeyStatus(i))
&& (KEY_PRESSED == Last_KeyStatus[i]))
{
key_Pressed[i] = KEY_RELEASED;
rt_kprintf("KEY: Key %d Releasedn", i);
rt_kprintf("KEY: Hold Key for %d msn", key_pressed_counter[i]*10);
}
else if((KEY_PRESSED == KEY_GetKeyStatus(i))
&& (KEY_PRESSED == Last_KeyStatus[i]))
{
key_pressed_counter[i] ++;
}

Last_KeyStatus[i] = KEY_GetKeyStatus(i);
}
}

static void KEY_ManageEntry(void *parameter)
{
while(1)
{
KEY_ReadKeyLevel();
KEY_KeySwFilter();
KEY_JudgeKeyPressed();
rt_thread_mdelay(10);
}
}

static void KEY_ThreadManage(void)
{
rt_thread_t key_thread;

key_thread = rt_thread_create("KEY Thread Manage", /*線程名字*/
KEY_ManageEntry,/*線程入口函數(shù)*/
RT_NULL, /*線程入口函數(shù)參數(shù)*/
2048, /*線程棧大小*/
5, /*線程優(yōu)先級*/
10); /*線程時間片*/

if(key_thread != RT_NULL)
{
rt_kprintf("KEY Thread Created Success!n");
rt_thread_startup (key_thread);
}
else
{
rt_kprintf("KEY Thread Create Failed!n");
}
}

.h文件

#ifndef APPLICATIONS_APP_KEY_H_
#define APPLICATIONS_APP_KEY_H_

#include "stdint.h"

typedef enum
{
    KEY_PRESSED  = 0u,
    KEY_RELEASED = 1u,
    KEY_UNKNOW   = 2u
} E_KeySt;

#define KEY_NUM                           (3u)
#define KEY_NUM_1                         (0u)
#define KEY_NUM_2                         (1u)
#define KEY_NUM_3                         (2u)

#define KEY_SW_FILTER_THD                 (4u)

#define KEY_SAMPLE_PERIOD                 (10u)
#define KEY_HOLD_SHORT_TIME               (500u) /*ms*/
#define KEY_HOLD_MIDDLE_TIME              (1500u) /*ms*/
#define KEY_HOLD_LONG_TIME                (1500u) /*ms*/

extern E_KeySt KEY_GetKeyStatus(uint8_t paraKeyNum);
extern E_KeySt KEY_GetKeyPressedStatus(uint8_t paraKeyNum);

void KEY_AppInit(void);

#endif
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 濾波
    +關(guān)注

    關(guān)注

    10

    文章

    674

    瀏覽量

    57074
  • 按鍵
    +關(guān)注

    關(guān)注

    4

    文章

    225

    瀏覽量

    57897
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1355

    瀏覽量

    41395
收藏 人收藏

    評論

    相關(guān)推薦
    熱點推薦

    RTT大賽作品連載】AB32VG1評估板到貨控制彩燈測試

    RTT大賽作品連載】AB32VG1評估板到貨控制彩燈測試篇;接下來看看在如何AB32VG1評估板控制彩燈! 在RT-ThreadStudio新建項目到對應(yīng)開發(fā)配置及下載及驗證測試!
    的頭像 發(fā)表于 11-07 19:39 ?5378次閱讀
    【<b class='flag-5'>RTT</b><b class='flag-5'>大賽</b><b class='flag-5'>作品</b><b class='flag-5'>連載</b>】AB32VG1評估板到貨控制彩燈測試

    RTT大賽作品連載】AB32VG1評估板 音樂播放器

    RTT大賽作品連載】AB32VG1評估板 音樂播放器
    的頭像 發(fā)表于 11-12 21:11 ?6464次閱讀
    【<b class='flag-5'>RTT</b><b class='flag-5'>大賽</b><b class='flag-5'>作品</b><b class='flag-5'>連載</b>】AB32VG1評估板 音樂播放器

    RTT大賽作品連載】中科藍訊AB32VG1開發(fā)板開箱篇

    介紹電路原理圖分析接口說明,AB32VG1開發(fā)板是以中科藍訊(Bluetrum)公司推出的基于RISC-V架構(gòu)的高配置芯片AB5301A為核心所組成的。【RTT大賽作品連載】中科藍訊A
    的頭像 發(fā)表于 11-13 10:01 ?1.1w次閱讀
    【<b class='flag-5'>RTT</b><b class='flag-5'>大賽</b><b class='flag-5'>作品</b><b class='flag-5'>連載</b>】中科藍訊AB32VG1開發(fā)板開箱篇

    跪求基于verilog的短按鍵長按鍵的程序

    小弟新手,只會短按鍵的程序,跪求基于verilog的短按鍵長按鍵的程序,不勝感激
    發(fā)表于 03-18 14:47

    CY方案,想做一個按鍵短按長按功能

    請教各位大神,我在用CY方案時,需要做一個按鍵短按長按功能,一直沒成功,代碼如下:if (index == 0x00) // 按鍵
    發(fā)表于 05-26 17:01

    mico按鍵長按短按怎么實現(xiàn)

    mico按鍵長按短按怎么實現(xiàn)?
    發(fā)表于 07-31 17:02

    【文章連載】RT-Thread創(chuàng)新應(yīng)用大賽文章匯總

    連載】中科藍訊AB32VG1開發(fā)板開箱篇專欄作者:煲仔鹵煮的煉鋼【RTT大賽作品連載】CH32V103開發(fā)板資料及上電首測專欄作者:AB32
    發(fā)表于 10-11 15:13

    stm32按鍵長按/短按怎么實現(xiàn)?

    stm32按鍵長按/短按怎么實現(xiàn)?
    發(fā)表于 12-02 07:41

    實現(xiàn)單片機按鍵長按短按功能的方法

    寫在前面?一般我們在寫單片機程序的時候都要用到按鍵,在按鍵較少的情況我們需要一個按鍵可以返回不同的
    發(fā)表于 12-06 07:40

    單片機狀態(tài)機按鍵長按短按實現(xiàn)

    本文只介紹主要代碼段,完整代碼可參考我的“藍橋杯單片機狀態(tài)機按鍵和松開實現(xiàn)不同功能”藍橋杯單片機狀態(tài)機按鍵長按
    發(fā)表于 01-06 08:26

    按鍵長按短按效果

    按鍵長按短按效果 C51單片機源碼,KEIL源文件,C語言編寫
    發(fā)表于 06-20 16:15 ?64次下載

    基于狀態(tài)機的單片機按鍵短按長按功能的實現(xiàn)

    本文主要介紹了基于狀態(tài)機的單片機按鍵短按長按功能的實現(xiàn),按鍵的擊鍵過程也是一種狀態(tài)的切換,也可以看著是一個狀態(tài)機,一個按鍵的擊鍵過程包括:
    發(fā)表于 12-28 08:43 ?2w次閱讀
    基于狀態(tài)機的單片機<b class='flag-5'>按鍵</b><b class='flag-5'>短按</b><b class='flag-5'>長按</b>功能的實現(xiàn)

    單片機按鍵進行長按短按的流程分析和程序代碼免費下載

    在寫單片機程序的過程中,難免會遇到按鍵的寫法,比如一個按鍵實現(xiàn)長按短按。本文只針對這些操作說明一自己
    發(fā)表于 09-19 17:20 ?9次下載
    單片機<b class='flag-5'>按鍵</b>進行<b class='flag-5'>長按</b>和<b class='flag-5'>短按</b>的流程分析和程序代碼免費下載

    如何實現(xiàn)單片機按鍵長按短按功能

    寫在前面?一般我們在寫單片機程序的時候都要用到按鍵,在按鍵較少的情況我們需要一個按鍵可以返回不同的
    發(fā)表于 11-23 18:06 ?39次下載
    如何實現(xiàn)單片機<b class='flag-5'>按鍵</b><b class='flag-5'>長按</b>和<b class='flag-5'>短按</b>功能

    如何區(qū)分按鈕的短按長按

    怎樣區(qū)分按鈕的短按后松開)與長按并保持一段時間)。說實話,在工業(yè)現(xiàn)場,按鈕
    的頭像 發(fā)表于 02-07 13:53 ?4165次閱讀
    如何區(qū)分按鈕的<b class='flag-5'>短按</b>與<b class='flag-5'>長按</b>?
    主站蜘蛛池模板: 久久久久久91精品色婷婷 | 国产在线精品一区二区夜色 | 国产亚洲精品久久yy5099 | 亚洲免费在线观看视频 | 国产内地激情精品毛片在线一 | 亚洲操综合| 天使色吧 | 亚洲精品成人久久久影院 | 欧美乱理伦另类视频 | 黄色视屏免费在线观看 | 久久ww | 五月天色婷婷丁香 | 中文字幕二区 | 亚洲性色成人 | 久久91精品牛牛 | 日本三级视频在线播放 | 婷婷激情久久 | 插综合网 | 久久综合综合久久 | 又大又粗进出白浆直流动态图 | 天天综合网天天综合色不卡 | 伊人伊成久久人综合网777 | 欧美在线资源 | 午夜一级福利 | 亚洲深夜在线 | 性生大片一级毛片免费观看 | 怡红院免费va男人的天堂 | 欧美成人午夜精品一区二区 | 国产三级黄色毛片 | 天天干 夜夜操 | 婷婷丁香在线观看 | 国产主播在线观看 | 国产成人毛片亚洲精品不卡 | 免费一级毛片清高播放 | 国产小视频在线 | 日本黄色www | 亚洲丁香婷婷 | 黄色免费网站在线播放 | 免费成人毛片 | 日本免费黄色大片 | 草草影院www色极品欧美 |