本帖最后由 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 调用
|
|