打印
[APM32F4]

【极海APM32F4xx Tiny】学习笔记03-按键输入+自定义按键框架

[复制链接]
700|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
chejia12|  楼主 | 2023-7-21 09:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 chejia12 于 2023-5-29 22:10 编辑 3.按键输入+自定义按键框架按键框架使用条件:1.已经初始化了gpio位输入状态或提供了初始化按键为输入的函数 2.注册按键事件 需要提供按键按下的有效电平 需要提供按键按下的事件处理函数 3.循环调用按键 key_lib_buttons_process 函数,一般1ms调用一次 BUTTON_DEBOUNCE_TIME_MS 一般设置为200 ,也就是200ms

按键实例教程:
  •         提供了按键处理框架文件bsp_key_lib.c/h
  •         提供了按键gpio设置为输入模式的函数bsp_key.c/h
  •         提供了按键处理按键实例,及如何使用按键框架的bsp_button_instance.c/h


bsp_key_lib.c[url=]复制[/url]
  • #include "../key/bsp_key_lib.h"
  • #include "stdio.h"
  • #include "string.h"
  • static button *btuuon_head = NULL;
  • //核心检测代码
  • void button_cheeck(button *btn)
  • {
  •     volatile uint8_t current_level = 0;
  •     if(btn->fn_read_button_level)
  •         current_level = (uint8_t)btn->fn_read_button_level(btn->read_button_param); //获取当前按键电平
  •     if ((current_level != btn->last_level)                                                  //检测电平变化
  •             && (++(btn->debounce_time) >= BUTTON_DEBOUNCE_TIME_MS)) //按键电平发生变化,消抖
  •     {
  •         btn->last_level = current_level;                //更新当前按键电平
  •         btn->debounce_time = 0;                 //确定了是按下
  •         if (btn->triger_level == current_level)
  •         {
  •             btn->envent = BUTTON_DOWM; //按键状态
  •         }
  •         //释放按键
  •         else
  •         {
  •             btn->envent = BUTTON_UP;
  •         }
  •     }
  •     //处理按键事件
  •     if(btn->envent != BUTTON_NULL && btn->button_handles[(uint8_t)btn->envent])
  •     {
  •         btn->button_handles[(uint8_t)btn->envent](btn->id);
  •         btn->envent = BUTTON_NULL;
  •     }
  • }
  • void key_lib_register_button(button *btn, uint8_t id, uint8_t valid_level, read_button_level fn_read_button_level, button_event_type type, fn_button_handle handel,uint8_t param)
  • {
  •     btn->triger_level = valid_level;
  •     btn->fn_read_button_level = fn_read_button_level;
  •     btn->button_handles[(uint8_t)type] = handel;
  •     btn->id = id;
  •         btn->read_button_param =param;
  •     btn->envent = BUTTON_NULL;
  •     btn->debounce_time = 0;
  •         btn->last_level = fn_read_button_level(param);
  •     //形成一个链表结构
  •     if(!btuuon_head)
  •     {
  •         btuuon_head = btn;
  •     }
  •     else
  •     {
  •         button *pbtn = btuuon_head;
  •         //同一个按键注册多个时间处理
  •         for(; pbtn; pbtn = pbtn->next)
  •         {
  •             if(pbtn == btn)
  •             {
  •                 return;
  •             }
  •         }
  •         //一个新的button注册事件
  •         pbtn = btuuon_head;
  •         for(; pbtn->next; pbtn = pbtn->next)
  •         {
  •         }
  •         pbtn->next = btn;
  •     }
  • }
  • void key_lib_register_button_ex(button *btn)
  • {
  •     btn->last_level=btn->fn_read_button_level(btn->read_button_param);
  •     btn->debounce_time=0;
  •     btn->envent = BUTTON_NULL;
  •         //形成一个链表结构
  •     if(!btuuon_head)
  •     {
  •         btuuon_head = btn;
  •     }
  •     else
  •     {
  •         button *pbtn = btuuon_head;
  •         //同一个按键注册多个时间处理
  •         for(; pbtn; pbtn = pbtn->next)
  •         {
  •             if(pbtn == btn)
  •             {
  •                 return;
  •             }
  •         }
  •         //一个新的button注册事件
  •         pbtn = btuuon_head;
  •         for(; pbtn->next; pbtn = pbtn->next)
  •         {
  •         }
  •         pbtn->next = btn;
  •     }
  • }
  • /*定时器每1ms调用一次*/
  • void key_lib_buttons_process()
  • {
  •     button *pbtn = btuuon_head;
  •     for(; pbtn; pbtn = pbtn->next)
  •     {
  •         button_cheeck(pbtn);
  •     }
  • }



bsp_key_lib.h[url=]复制[/url]
  • #ifndef _BUTTON_H_
  • #define _BUTTON_H_
  • #include "stdint.h"
  • /*
  •     按键框架使用条件:
  •     1.已经初始化了gpio位输入状态或提供了初始化按键为输入的函数
  •     2.注册按键事件
  •         需要提供按键按下的有效电平
  •         需要提供按键按下的事件处理函数
  •     3.循环调用按键 key_lib_buttons_process 函数,一般1ms调用一次  BUTTON_DEBOUNCE_TIME_MS 一般设置为200 ,也就是200ms
  • */
  • //按键消抖时间ms,一般是200ms,key_lib_buttons_process 函数的周期调用时间决定了这个地方的值
  • #define BUTTON_DEBOUNCE_TIME_MS 2  
  • #define INTERVAL 10
  • typedef enum
  • {
  •     BUTTON_DOWM=0,//按键按下
  •     BUTTON_UP, //按键释放
  •         BUTTON_NULL//未知时间
  • }button_event_type;
  • /*************************旋钮宏定义**********************************/
  • /*
  •     按键状态
  • */
  • typedef void (*fn_button_handle)(uint8_t btn_id);               //按键事件回调函数
  • typedef uint8_t  (*read_button_level)(uint8_t param);       //读取按键的回调函数
  • typedef struct button_
  • {
  •         uint8_t id;//id
  •         read_button_level fn_read_button_level;//电平去读函数
  •     uint8_t triger_level;                       //按键触发的有效电平
  •         uint8_t read_button_param;
  •     fn_button_handle button_handles[BUTTON_NULL];//时间处理函数
  •       uint16_t debounce_time;                   //双击时间
  •         button_event_type envent;               //按键事件
  •         struct button_ *next;                       //下一个按键
  •         uint8_t last_level;                         //最后一次按键跳变的电平
  • } button;
  • /*
  •     每ms调用一次
  • */
  • void key_lib_buttons_process(void);
  • /*
  •     注册按键检测事件
  • */
  • void key_lib_register_button(button *btn,uint8_t id,uint8_t valid_level, read_button_level fn_read_button_level ,button_event_type type,fn_button_handle handel,uint8_t param);
  • void key_lib_register_button_ex(button *btn);
  • #endif


bsp_key.c[url=]复制[/url]
  • /* Includes */
  • #include "../key/bsp_key.h"
  • //按键port
  • GPIO_T* BUTTON_PORT[BUTTONn] = {KEY1_BUTTON_GPIO_PORT, KEY2_BUTTON_GPIO_PORT};
  • //按键pin
  • const uint16_t BUTTON_PIN[BUTTONn] = {KEY1_BUTTON_PIN, KEY2_BUTTON_PIN};
  • //按键port
  • const uint32_t BUTTON_CLK[BUTTONn] = {KEY1_BUTTON_GPIO_CLK, KEY2_BUTTON_GPIO_CLK};
  • //外部中断先名
  • const EINT_LINE_T BUTTON_EINT_LINE[BUTTONn] = {KEY1_BUTTON_EINT_LINE, KEY2_BUTTON_EINT_LINE};
  • //外部中断源分组
  • const SYSCFG_PORT_T BUTTON_PORT_SOURCE[BUTTONn] = {KEY1_BUTTON_EINT_PORT_SOURCE, KEY2_BUTTON_EINT_PORT_SOURCE};
  • //外部中断源pin
  • const SYSCFG_PIN_T BUTTON_PIN_SOURCE[BUTTONn] = {KEY1_BUTTON_EINT_PIN_SOURCE, KEY2_BUTTON_EINT_PIN_SOURCE};
  • ////外部中断源中断处理函数
  • const IRQn_Type BUTTON_IRQn[BUTTONn] = {KEY1_BUTTON_EINT_IRQn, KEY2_BUTTON_EINT_IRQn};
  • /*
  •     按键名称
  •     按键输入模式 0普通输入 ;1:中断输入
  • */
  • void bsp_key_init(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode)
  • {
  •     GPIO_Config_T     GPIO_configStruct;
  •     EINT_Config_T     EINT_configStruct;
  •     /** 使能按键时钟*/
  •     RCM_EnableAHB1PeriphClock(BUTTON_CLK[Button]);
  •     /** 配置gpio位输入模式,上拉 */
  •     GPIO_ConfigStructInit(&GPIO_configStruct);
  •     GPIO_configStruct.mode = GPIO_MODE_IN;//输入
  •     GPIO_configStruct.pin = BUTTON_PIN[Button];//PIN
  •     GPIO_configStruct.pupd  = GPIO_PUPD_UP;//上拉
  •     GPIO_Config(BUTTON_PORT[Button], &GPIO_configStruct);
  •     if (Button_Mode == BUTTON_MODE_EINT)//中断模式
  •     {
  •         /** Enable the SYSCFG Clock 使能系统时钟 */
  •         RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
  •         /** Connect Button EINT Line to Button GPIO Pin 配置中断源 那个线*/
  •         SYSCFG_ConfigEINTLine(BUTTON_PORT_SOURCE[Button], BUTTON_PIN_SOURCE[Button]);
  •         /** Configure Button EINT line  中断使能*/
  •         EINT_configStruct.line = BUTTON_EINT_LINE[Button];
  •         EINT_configStruct.mode = EINT_MODE_INTERRUPT;
  •         EINT_configStruct.trigger = EINT_TRIGGER_FALLING;
  •         EINT_configStruct.lineCmd = ENABLE;
  •         EINT_Config(&EINT_configStruct);
  •         /** Enable and set Button EINT Interrupt to the lowest priority 配置中断优先级*/
  •         NVIC_EnableIRQRequest(BUTTON_IRQn[Button], 0x0f, 0x0f);
  •     }
  • }
  • /*
  •     读取按键状态
  • */
  • uint8_t bsp_get_key(uint8_t Button)
  • {
  •     return GPIO_ReadInputBit(BUTTON_PORT[Button], BUTTON_PIN[Button]);
  • }
  • //uint8_t Key_Scan(uint8_t mode)
  • //{
  • //    /** The flag of button is release */
  • //    static uint8_t s_key_release = 1;
  • //    if(mode == KEY_MODE_CONTINUOUS)
  • //    {
  • //        s_key_release = 1;
  • //    }
  • //    if(s_key_release && (KEY1 == 0 || KEY2 == 0))
  • //    {
  • //        Delay_ms(10);
  • //        s_key_release = 0;
  • //        if(KEY1 == 0)
  • //        {
  • //            return KEY1_PRESSED;
  • //        }
  • //        else if(KEY2 == 0)
  • //        {
  • //            return KEY2_PRESSED;
  • //        }
  • //    }
  • //    else if(KEY1 == 1 && KEY2 == 1)
  • //    {
  • //        s_key_release = 1;
  • //    }
  • //    return KEY_ALL_REALEASED;
  • //}



bsp_key.h[url=]复制[/url]
  • /*!
  • * @file        bsp_key.h
  • *
  • * @brief       Header for bsp_key.c module
  • *
  • * @version     V1.0.0
  • *
  • * @date        2023-03-01
  • *
  • * @attention
  • *
  • *  Copyright (C) 2021-2023 Geehy Semiconductor
  • *
  • *  You may not use this file except in compliance with the
  • *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
  • *
  • *  The program is only for reference, which is distributed in the hope
  • *  that it will be useful and instructional for customers to develop
  • *  their software. Unless required by applicable law or agreed to in
  • *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
  • *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
  • *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
  • *  and limitations under the License.
  • */
  • /* Define to prevent recursive inclusion */
  • #ifndef __BSP_KEY_H
  • #define __BSP_KEY_H
  • #ifdef __cplusplus
  •   extern "C" {
  • #endif
  • /* Includes */
  • //#include "Board.h"
  • #include "bsp_delay.h"
  • #include "apm32f4xx.h"
  • #include "apm32f4xx_gpio.h"
  • #include "apm32f4xx_eint.h"
  • #include "apm32f4xx_rcm.h"
  • #include "apm32f4xx_syscfg.h"
  • #include "apm32f4xx_misc.h"
  • typedef enum
  • {
  •     BUTTON_KEY1 = 0,
  •     BUTTON_KEY2 = 1,
  •         BUTTONn
  • } Button_TypeDef;
  • typedef enum
  • {
  •     BUTTON_MODE_GPIO = 0,
  •     BUTTON_MODE_EINT = 1
  • } ButtonMode_TypeDef;
  • /**
  • * @brief 按键1
  • */
  • #define KEY1_BUTTON_PIN                   GPIO_PIN_10
  • #define KEY1_BUTTON_GPIO_PORT             GPIOC
  • #define KEY1_BUTTON_GPIO_CLK              RCM_AHB1_PERIPH_GPIOC
  • #define KEY1_BUTTON_EINT_LINE             EINT_LINE_10
  • #define KEY1_BUTTON_EINT_PORT_SOURCE      SYSCFG_PORT_GPIOC
  • #define KEY1_BUTTON_EINT_PIN_SOURCE       SYSCFG_PIN_10
  • #define KEY1_BUTTON_EINT_IRQn             EINT15_10_IRQn
  • /**
  • * @brief 按键2
  • */
  • #define KEY2_BUTTON_PIN                   GPIO_PIN_11
  • #define KEY2_BUTTON_GPIO_PORT             GPIOC
  • #define KEY2_BUTTON_GPIO_CLK              RCM_AHB1_PERIPH_GPIOC
  • #define KEY2_BUTTON_EINT_LINE             EINT_LINE_11
  • #define KEY2_BUTTON_EINT_PORT_SOURCE      SYSCFG_PORT_GPIOC
  • #define KEY2_BUTTON_EINT_PIN_SOURCE       SYSCFG_PIN_11
  • #define KEY2_BUTTON_EINT_IRQn             EINT15_10_IRQn
  • /*
  •     按键名称
  •     按键输入模式 0普通输入 ;1:中断输入
  • */
  • void bsp_key_init(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode);
  • /*
  •     读取按键状态
  • */
  • uint8_t bsp_get_key(uint8_t Button);
  • //#define KEY1                GPIO_ReadInputBit(KEY1_BUTTON_GPIO_PORT,KEY1_BUTTON_PIN)
  • //#define KEY2                GPIO_ReadInputBit(KEY2_BUTTON_GPIO_PORT,KEY2_BUTTON_PIN)
  • ///**
  • //  * @}
  • //  */
  • ///** @defgroup APM32F407_TINY_Enumerations
  • //  @{
  • //  */
  • ///*!
  • // * @brief    Key value
  • // */
  • //typedef enum
  • //{
  • //    KEY_ALL_REALEASED,      /*!< All key is realeased */
  • //    KEY1_PRESSED,           /*!< KEY1 is pressed */
  • //    KEY2_PRESSED,           /*!< KEY2 is pressed */
  • //} KEY_VALUE_T;
  • ///*!
  • // * @brief    Key mode
  • // */
  • //typedef enum
  • //{
  • //    KEY_MODE_SINGLE,            /*!< Single detect mode */
  • //    KEY_MODE_CONTINUOUS,        /*!< Continuous detect mode */
  • //} KEY_MODE_T;
  • ///**
  • //  * @}
  • //  */
  • ///** @defgroup APM32F407_TINY_Functions
  • //  @{
  • //  */
  • ///** function declaration*/
  • //uint8_t Key_Scan(uint8_t mode);
  • #ifdef __cplusplus
  • }
  • #endif
  • #endif
  • /**@} end of group APM32F407_TINY_Functions */
  • /**@} end of group Board_APM32F407_TINY */
  • /**@} end of group Board */



bsp_button_instance.c[url=]复制[/url]
  • #include "string.h"
  • #include <stdio.h>
  • #include "../key/bsp_button_instance.h"
  • #include "../key/bsp_key.h"
  • //-------------------实际使用-------------------------------
  • //static button btn0,btn1;
  • static void btn_gpio_init(void)
  • {
  •     bsp_key_init(BUTTON_KEY1,BUTTON_MODE_GPIO);
  •     bsp_key_init(BUTTON_KEY2,BUTTON_MODE_GPIO);
  • }
  • void button_down_handles(uint8_t btn_id);
  • void button_up_handles(uint8_t btn_id);
  • button btnx= {
  •     0,//id
  •     bsp_get_key,//get_level
  •     BUTTON_DOWM,
  •     BUTTON_KEY1,
  •     {button_down_handles,0},
  • };
  • button btny= {
  •     1,//id
  •     bsp_get_key,//按键读取函数
  •     BUTTON_DOWM,//有效电平
  •     BUTTON_KEY2,//按键读取函数参数
  •     {button_down_handles,0},//处理函数可以填写2个处理函数
  • };
  • void init_key_btn(void)
  • {
  •     btn_gpio_init();
  •     //按下按键注册
  •     //key_lib_register_button(&btn0, 0, RESET, bsp_get_key, BUTTON_DOWM, button_down_handles,BUTTON_KEY1);
  •     //key_lib_register_button(&btn1, 1, RESET, bsp_get_key, BUTTON_DOWM, button_down_handles,BUTTON_KEY2);
  •     key_lib_register_button_ex(&btnx);
  •     key_lib_register_button_ex(&btny);
  • }
  • void button_up_handles(uint8_t btn_id)
  • {
  • #if BUTTON_DEBUG >0
  •     printf("%s %s %d btn_id = %d \r\n", __FILE__, __FUNCTION__, __LINE__, btn_id);
  • #endif
  • }
  • void button_down_handles(uint8_t btn_id)
  • {
  • #if BUTTON_DEBUG >0
  •     printf("%s %s %d btn_id = %d \r\n", __FILE__, __FUNCTION__, __LINE__, btn_id);
  • #endif
  • }
  • //void button_handles(uint8_t btn_id)
  • //{
  • //    #if BUTTON_DEBUG >0
  • //    #endif
  • //    //处理摇杆数据
  • //
  • //}



bsp_button_instance.h[url=]复制[/url]
  • #ifndef _BUTTON_INSTANCEH_
  • #include "stdint.h"
  • #include "../key/bsp_key_lib.h"
  • #define DEBUG 1
  • #if DEBUG >0
  • #define BUTTON_DEBUG 1
  • #endif
  • void init_key_btn(void);
  • void button_handles(uint8_t btn_id);
  • #endif



main.c 调用[url=]复制[/url]
  • int main(void)
  • {
  •     led_init(LED0);
  •     led_init(LED1);
  •         bsp_uart1_init(115200);
  •         printf("hello apm32\r\n");
  •     //按键初始化
  •     init_key_btn();
  •     while (1)
  •     {
  •         Delay(0x2FFFFF);
  •         led_toggle(LED0);
  •         led_toggle(LED1);
  •         //按键事件循环调用
  •         key_lib_buttons_process();
  •     }
  • }

main.c 调用





使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

12

主题

32

帖子

1

粉丝