国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【嵌入式】使用MultiButton開源庫驅(qū)動按鍵并控制多級界面切換

這篇具有很好參考價值的文章主要介紹了【嵌入式】使用MultiButton開源庫驅(qū)動按鍵并控制多級界面切換。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

一 背景說明

二 參考資料

三 MultiButton開源庫移植

四 設計實現(xiàn)--驅(qū)動按鍵

五 設計實現(xiàn)--界面處理


一 背景說明

? ? ? ? 需要做一個通過不同按鍵控制多級界面切換以及界面動作的程序。

????????查閱相關資料,發(fā)現(xiàn)網(wǎng)上大多數(shù)的應用都比較繁瑣,且對于多級界面的切換邏輯可讀性較差。所幸找到一篇使用開源庫 MultiButton 來驅(qū)動按鍵,并控制多級界面切換的博文。按圖索驥實現(xiàn)了預期的需求。

?????????開源庫 MultiButton 是一個小巧簡單易用的事件驅(qū)動型按鍵驅(qū)動模塊,作者 0x1abin。這個項目非常精簡,只有兩個文件,可無限量擴展按鍵,按鍵事件的回調(diào)異步處理方式可以簡化程序結(jié)構,去除冗余的按鍵處理硬編碼,讓你的按鍵業(yè)務邏輯更清晰。

????????MultiButton 支持如下的按鈕事件:

【嵌入式】使用MultiButton開源庫驅(qū)動按鍵并控制多級界面切換,開源,嵌入式硬件,單片機,stm32

? ? ? ? MultiButton的狀態(tài)機如下:

【嵌入式】使用MultiButton開源庫驅(qū)動按鍵并控制多級界面切換,開源,嵌入式硬件,單片機,stm32

二 參考資料

? ? ? ? 【1】MultiButton開源庫:mirrors / 0x1abin / MultiButton · GitCode

? ? ? ? 【2】MultiButton博文:MultiButton | 一個小巧簡單易用的事件驅(qū)動型按鍵驅(qū)動模塊-CSDN博客

? ? ? ? 【3】MultiTimer開源庫:mirrors / 0x1abin / MultiTimer · GitCode

? ? ? ? 【4】MultiTimer博文:【嵌入式開源庫】MultiTimer 的使用,一款可無限擴展的軟件定時器_multi_timer-CSDN博客

? ? ? ? 【5】MultiButton+MultiTimer+菜單操作博文:開源按鍵組件MultiButton支持菜單操作(事件驅(qū)動型)-阿里云開發(fā)者社區(qū)

? ? ? ? 【注】:我下面的實現(xiàn)沒有用到MultiTimer,僅單列出來備查。

三 MultiButton開源庫移植

? ? ? ? 從上面的開源庫或者github下載該開源庫,主要用到就兩個文件 multi_button.c/multi_button.h 。將這兩個文件直接添加到自己的工程中,并關聯(lián)頭文件。

【嵌入式】使用MultiButton開源庫驅(qū)動按鍵并控制多級界面切換,開源,嵌入式硬件,單片機,stm32

? ? ? ? 到這邊編譯應該沒有問題。

四 設計實現(xiàn)--驅(qū)動按鍵

? ? ? ? 【1】首先初始化自己用到的幾個按鍵GPIO口:

void KNOB_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin  = KNOB_1_PIN | KNOB_2_PIN | KNOB_3_PIN | KNOB_4_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //設置成上拉輸入
    GPIO_Init(KNOB_PORT, &GPIO_InitStructure);
}

????????【2】由于這邊用到了四個按鍵,申請四個按鍵結(jié)構:

struct Button knob_1;
struct Button knob_2;
struct Button knob_3;
struct Button knob_4;

? ? ? ? 【3】編寫回調(diào)函數(shù),綁定按鍵的GPIO電平讀取接口:

u8 knobRead(u8 button_id)
{
	switch(button_id)
	{
		case 0:
			return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_1_PIN);
		case 1:
			return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_2_PIN);
        case 2:
            return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_3_PIN);
        case 3:
            return GPIO_ReadInputDataBit(KNOB_PORT,KNOB_4_PIN);
		default:
			return 0;
	}
}

? ? ? ? 【4】關聯(lián)?MultiButton ,使用上面的按鍵結(jié)構以及回調(diào)函數(shù)初始化按鍵對象:

button_init(&knob_1, knobRead, 0, 0);
button_init(&knob_2, knobRead, 0, 1);
button_init(&knob_3, knobRead, 0, 2);
button_init(&knob_4, knobRead, 0, 3);

????????【5】注冊按鍵事件(根據(jù)實際需要注冊按鍵事件,不必一次性全注冊,我這邊只用到點按和長按,所以只注冊了 SINGLE_CLICK 和 LONG_PRESS_START 兩個事件)。

? ? ? ? ? ? ? ? 其中的回調(diào)函數(shù) knobCallback_1/2/3/4 先空著,后面需要結(jié)合界面切換來實現(xiàn):

button_attach(&knob_1, SINGLE_CLICK,     knobCallback_1);
button_attach(&knob_1, LONG_PRESS_START, knobCallback_1);
button_attach(&knob_2, SINGLE_CLICK,     knobCallback_2);
button_attach(&knob_2, LONG_PRESS_START, knobCallback_2);
button_attach(&knob_3, SINGLE_CLICK,     knobCallback_3);
button_attach(&knob_3, LONG_PRESS_START, knobCallback_3);
button_attach(&knob_4, SINGLE_CLICK,     knobCallback_4);
button_attach(&knob_4, LONG_PRESS_START, knobCallback_4);

? ? ? ? 【6】啟動按鍵:

button_start(&knob_1);
button_start(&knob_2);
button_start(&knob_3);
button_start(&knob_4);

? ? ? ? 【7】將上面【4】【5】【6】的三個步驟整個成一個按鍵注冊接口:

void KNOB_Reg(void)
{
    button_init(&knob_1, knobRead, 0, 0);
    button_init(&knob_2, knobRead, 0, 1);
    button_init(&knob_3, knobRead, 0, 2);
    button_init(&knob_4, knobRead, 0, 3);

    button_attach(&knob_1, SINGLE_CLICK,     knobCallback_1);
    button_attach(&knob_1, LONG_PRESS_START, knobCallback_1);
    button_attach(&knob_2, SINGLE_CLICK,     knobCallback_2);
    button_attach(&knob_2, LONG_PRESS_START, knobCallback_2);
    button_attach(&knob_3, SINGLE_CLICK,     knobCallback_3);
    button_attach(&knob_3, LONG_PRESS_START, knobCallback_3);
    button_attach(&knob_4, SINGLE_CLICK,     knobCallback_4);
    button_attach(&knob_4, LONG_PRESS_START, knobCallback_4);

    button_start(&knob_1);
    button_start(&knob_2);
    button_start(&knob_3);
    button_start(&knob_4);
}

? ? ? ? 【8】至此,按鍵驅(qū)動還不能生效,還需要添加一個心跳,一般采用5ms間隔定時器來循環(huán)調(diào)用這個心跳函數(shù),定時器相關函數(shù)如下:

//Timer14 5ms定時器
#define TIMER14_ARR  (500-1)
#define TIMER14_PSC  (960-1)

void Timer14_Config(void)
{
    TIM_TimeBaseInitTypeDef TIM_StructInit;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM14, ENABLE);//使能定時器時鐘

    //定時器基礎配置
    TIM_StructInit.TIM_Period = TIMER14_ARR;            //自動重裝值
    TIM_StructInit.TIM_Prescaler = TIMER14_PSC;         //預分頻系數(shù)
    TIM_StructInit.TIM_ClockDivision = TIM_CKD_DIV1;    //時鐘分頻
    TIM_StructInit.TIM_CounterMode = TIM_CounterMode_Up;//向上計數(shù)
    TIM_StructInit.TIM_RepetitionCounter = 0;           //不重復計數(shù)
    TIM_TimeBaseInit(TIM14, &TIM_StructInit);
    
    //NVIC中斷配置
    NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 3;     //數(shù)字越小優(yōu)先級越高
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    TIM_ClearFlag(TIM14, TIM_FLAG_Update);
    TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE);          //使能更新中斷
    TIM_Cmd(TIM14, ENABLE);
}

extern void button_ticks(void);
void TIM14_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM14, TIM_IT_Update) != RESET)
    {
        button_ticks();     //旋鈕驅(qū)動心跳
        TIM_ClearITPendingBit(TIM14, TIM_IT_Update);
    }
}

? ? ? ? 【9】在主函數(shù)的初始化中加上上面幾個接口:

void main(void)
{
    //定時器初始化
    Timer14_Config();
    //旋鈕初始化/注冊
    KNOB_Init();
    KNOB_Reg();

    while(1)
    {
        //...
    }
}

????????至此,MultiButton 開源庫移植完畢,并將所用的四個按鈕關聯(lián)到?MultiButton ,按鍵事件待擴展。

五 設計實現(xiàn)--界面處理

? ? ? ? 【1】新建頭文件,新增界面相關的結(jié)構體定義等:

typedef enum tagMenuTree    //菜單樹
{
    MENU_MAIN = 0,
    MEUN_LOG
}MENU_TREE;

typedef enum tagEventCode   //事件值
{
    NULL_EVENT = 0,
    KNOB_1_SHORT = 1,
    KNOB_1_LONG  = 2,
    KNOB_2_SHORT = 3,
    KNOB_2_LONG = 4,
    KNOB_3_SHORT = 5,
    KNOB_3_LONG = 6,
    KNOB_4_SHORT = 7,
    KNOB_4_LONG = 8
}EVENT_CODE;

typedef struct tagMenuInfo  //界面信息
{
    u8 cur_page;    //正在執(zhí)行的界面
    u8 knb_evnt;    //當前觸發(fā)的事件
}MENU_INFO;
extern MENU_INFO menu;


extern void Menu_Init(MENU_INFO *handle, u8 p_page, u8 p_evnt);
extern void Set_Menu(MENU_INFO *handle, u8 p_page);
extern u8 Get_Menu(MENU_INFO *handle);
extern void Set_Event_Code(MENU_INFO *handle, u8 p_evnt);
extern int Get_Event_Code(MENU_INFO *handle);
extern void Menu_Handler(MENU_INFO *handle);

? ? ? ? 【2】新建源文件,新增界面相關的接口函數(shù)等:

/**************************************************************************
* 函數(shù)名稱: Menu_Init
* 功能描述: 菜單初始化
**************************************************************************/
void Menu_Init(MENU_INFO *handle, u8 p_page, u8 p_evnt)
{
    memset(handle, 0, sizeof(MENU_INFO));
    handle->cur_page = p_page;
    handle->knb_evnt = p_evnt;
}

/**************************************************************************
* 函數(shù)名稱: Set_Menu/Get_Menu
* 功能描述: 菜單跳轉(zhuǎn)/獲取當前菜單
**************************************************************************/
void Set_Menu(MENU_INFO *handle, u8 p_page)
{
    handle->cur_page = p_page;
}

u8 Get_Menu(MENU_INFO *handle)
{
    return handle->cur_page;
}

/**************************************************************************
* 函數(shù)名稱: Set_Event_Code/Get_Event_Code
* 功能描述: 設置當前事件值/獲取當前事件值
**************************************************************************/
void Set_Event_Code(MENU_INFO *handle, u8 p_evnt)
{
    handle->knb_evnt = p_evnt;
}

int Get_Event_Code(MENU_INFO *handle)
{
    return handle->knb_evnt;
}

????????【3】結(jié)合上述菜單處理函數(shù),關聯(lián)“設計實現(xiàn)--驅(qū)動按鍵”中的【5】,完善 knobCallback_1/2/3/4 的實現(xiàn)。

????????????????主要邏輯就是將按鍵的動作,通過回調(diào),傳遞給菜單結(jié)構 menu (單列出knobCallback_1,其他按鈕的回調(diào)一樣實現(xiàn)):

void knobCallback_1(void *p_btn)
{
    u8 btn_event_val; 
    
    btn_event_val = get_button_event((struct Button *)p_btn); 
  
    switch(btn_event_val)
    {
        case SINGLE_CLICK:
            Set_Event_Code(&menu, KNOB_1_SHORT);
            break ;
        case LONG_PRESS_START:
            Set_Event_Code(&menu, KNOB_1_LONG);
            break ;
        default:
            break ;
    }
}

????????【4】菜單處理函數(shù) Menu_Handler 的實現(xiàn):

void Menu_Handler(MENU_INFO *handle)
{
	switch(handle->cur_page)
	{
		case MENU_MAIN:
			menuMainHandle(handle->knb_evnt);
			break ;
		case MEUN_LOG:
			menuLogHandle(handle->knb_evnt);
			break ;
		default:
			break ;
	}
    Set_Event_Code(handle, NULL_EVENT);     //及時將事件清除,防止重復觸發(fā)
}

? ? ? ? 其中,menuMainHandle/menuLogHandle 就是每個界面的具體實現(xiàn)了:

void menuMainHandle(u8 p_evnt)
{
    cleanAll();  //清屏
    //主界面顯示
    
    switch(p_evnt)
    {
        case KNOB_1_SHORT:
            break ;
        case KNOB_1_LONG:
            Set_Menu(&menu, MEUN_LOG);  //進入登錄界面
            break ;
        default:
            break;
    }
}
void menuLogHandle(u8 p_evnt)
{
    cleanAll();  //清屏
    //登錄界面的顯示
    
    switch(p_evnt)
    {
        case KNOB_2_SHORT:
            break ;
        case KNOB_2_LONG:
            Set_Menu(&menu, MENU_MAIN);  //返回主界面
            break ;
        default:
            break;
    }
}

? ? ? ? 【5】在主函數(shù)的初始化中加上上面界面初始化接口,同時界面處理函數(shù)置于主循環(huán)中執(zhí)行:

void main(void)
{
    //定時器初始化
    Timer14_Config();
    //旋鈕初始化/注冊
    KNOB_Init();
    KNOB_Reg();
    //界面初始化
    Menu_Init(&menu, MENU_MAIN, NULL_EVENT);

    while(1)
    {
        Menu_Handler(&menu);  //界面處理函數(shù)
        
        LCD_Update();  //用緩存刷新屏幕
        
        //...
    }
}

? ? ? ? 至此,完成了通過 MultiButton 開源庫驅(qū)動按鍵并控制多級界面切換的工作。

? ? ? ? 上述DEMO中,上電默認進入主界面,可以通過長按 knob_1 進入登陸界面。在登陸界面中,通過長按 knob_2 返回主界面(長按的時間可以在 multi_button.h 中設置)文章來源地址http://www.zghlxwxcb.cn/news/detail-730065.html

到了這里,關于【嵌入式】使用MultiButton開源庫驅(qū)動按鍵并控制多級界面切換的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • STM32之按鍵驅(qū)動的使用和自定義(MultiButton)

    STM32之按鍵驅(qū)動的使用和自定義(MultiButton)

    Github地址 調(diào)整內(nèi)容 將宏定義轉(zhuǎn)換成配置結(jié)構體 頭文件 源文件 驅(qū)動使用 執(zhí)行循環(huán)邏輯 (在RTOS的定時器中執(zhí)行) 測試結(jié)果

    2024年02月16日
    瀏覽(59)
  • 【速成】藍橋杯嵌入式省一教程:(五)用按鍵和屏幕實現(xiàn)嵌入式交互系統(tǒng)

    【速成】藍橋杯嵌入式省一教程:(五)用按鍵和屏幕實現(xiàn)嵌入式交互系統(tǒng)

    一個完整的嵌入式系統(tǒng),包括任務執(zhí)行部分和人機交互部分。在前四節(jié)中,我們已經(jīng)講解了LED、LCD和按鍵,用這三者就能夠?qū)崿F(xiàn)一個人機交互系統(tǒng),也即搭建整個嵌入式系統(tǒng)的框架。在后續(xù),只要將各個功能加入到這個交互系統(tǒng)中,即可完成整個嵌入式系統(tǒng)的設計。因此,盡

    2024年02月09日
    瀏覽(40)
  • 速通藍橋杯嵌入式省一教程:(五)用按鍵和屏幕實現(xiàn)嵌入式交互系統(tǒng)

    速通藍橋杯嵌入式省一教程:(五)用按鍵和屏幕實現(xiàn)嵌入式交互系統(tǒng)

    一個完整的嵌入式系統(tǒng),包括任務執(zhí)行部分和人機交互部分。在前四節(jié)中,我們已經(jīng)講解了LED、LCD和按鍵,用這三者就能夠?qū)崿F(xiàn)一個人機交互系統(tǒng),也即搭建整個嵌入式系統(tǒng)的框架。在后續(xù),只要將各個功能加入到這個交互系統(tǒng)中,即可完成整個嵌入式系統(tǒng)的設計。因此,盡

    2024年02月12日
    瀏覽(18)
  • 嵌入式51單片機04-矩陣按鍵系列

    嵌入式51單片機04-矩陣按鍵系列

    一、矩陣按鍵基礎知識 矩陣按鍵工作原理 : 逐行掃描 :通過高四位輪流輸出低電平來對矩陣鍵盤進行掃描,當?shù)退奈唤邮盏降臄?shù)據(jù)不全為1的時候,說明有按鍵按下,然后通過判斷低四位數(shù)據(jù)中哪一位為零來判斷哪一個按鍵被按下。 逐列掃描 :通過低四位輪流輸出低電平來

    2024年02月07日
    瀏覽(49)
  • 【嵌入式系統(tǒng)課設】單個按鍵控制LED燈

    【嵌入式系統(tǒng)課設】單個按鍵控制LED燈

    合工大嵌入式系統(tǒng)課程設計 設計要求: 根據(jù)單個按鍵輸入情況控制LED燈的不同顯示效果。K1連續(xù)按下偶數(shù)次時,四個LED燈(LED1~LED4)按1秒(定時器中斷實現(xiàn))的間隔同時閃爍對應的次數(shù),然后保持LED1和LED2常亮,LED3和LED4熄滅;K1連續(xù)按下奇數(shù)次時,四個燈按0.5秒(定時器中斷實

    2024年02月12日
    瀏覽(19)
  • 嵌入式USB轉(zhuǎn)RS232九針串口線驅(qū)動,及串口軟件secureCRT的使用

    嵌入式USB轉(zhuǎn)RS232九針串口線驅(qū)動,及串口軟件secureCRT的使用

    一般而言,嵌入式開發(fā)板使用串口來就監(jiān)控后臺??梢允褂么诰€連接開發(fā)板和電腦,對于沒有串口的電腦來說就需要一根USB轉(zhuǎn)串口線。 (有條件的這里個人推薦 綠聯(lián) 的 比較穩(wěn)定 ,當然其他的也可以,根據(jù)自身條件選擇) ? ? ? ? ? ? ? ? 它的芯片:PL2303 ? ? ? ? ? ?

    2024年02月07日
    瀏覽(32)
  • 驅(qū)動開發(fā)——嵌入式(驅(qū)動)軟開基礎(十)

    1. 64位的計算機有哪些優(yōu)點? (1)可以進行更大范圍的整數(shù)計算。 (2)可以支持更大的內(nèi)存,虛擬內(nèi)存空間大小一般為2^48(256TB)。64位的Linux一般使用48位表示虛擬內(nèi)存空間地址,40位表示物理內(nèi)存地址。 2. 中斷分為哪兩種? (1) 異步中斷 :也叫 外部中斷 ,由CPU外設產(chǎn)

    2024年02月06日
    瀏覽(25)
  • 驅(qū)動開發(fā)——嵌入式(驅(qū)動)軟開基礎(七)

    1 Linux驅(qū)動程序的功能是什么? (1)對設備初始化和釋放。 (2)進行內(nèi)核與硬件的數(shù)據(jù)交互。 (3)檢測和處理設備出現(xiàn)的錯誤。 2. 內(nèi)核程序中申請內(nèi)存使用什么函數(shù)? 答案:kmalloc()、kzalloc()、vmalloc()。 解讀: (1)void *kmalloc(size_t size, gfp_t flags); ①申請連續(xù)的物理內(nèi)存,

    2024年02月06日
    瀏覽(22)
  • 嵌入式系統(tǒng)項目設計——基于LED、按鍵、蜂鳴器的打地鼠游戲(完整代碼)

    嵌入式系統(tǒng)項目設計——基于LED、按鍵、蜂鳴器的打地鼠游戲(完整代碼)

    內(nèi)容摘自上學期嵌入式系統(tǒng)課程設計最終的實驗報告,因為CSDN不支持上傳word資料,所以我就摘錄下來寫進文章里了,希望可以幫助到你 1.1選題背景 打地鼠游戲是一種非常受小孩子歡迎的游戲,擁有數(shù)量極其廣大的受眾,所以它的市場前景非常廣闊。當今社會雖然存在各種各

    2024年02月09日
    瀏覽(99)
  • 嵌入式內(nèi)核及驅(qū)動開發(fā)高級

    嵌入式內(nèi)核及驅(qū)動開發(fā)高級

    僅devfs,導致開發(fā)不方便以及一些功能難以支持: 熱插拔 不支持一些針對所有設備的統(tǒng)一操作(如電源管理) 不能自動mknod 用戶查看不了設備信息 設備信息硬編碼,導致驅(qū)動代碼通用性差,即沒有分離設備和驅(qū)動 uevent機制:sysfs + uevent + udevd(上層app) sysfs用途:(類似于

    2024年02月16日
    瀏覽(36)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包