【极海APM32F4xx Tiny】学习笔记03-按键输入+自定义按键框架
本帖最后由 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复制
[*]
[*]#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复制
[*]#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;//时间处理函数
[*]
[*] 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复制
[*]
[*]
[*]/* Includes */
[*] #include "../key/bsp_key.h"
[*]
[*]//按键port
[*]GPIO_T* BUTTON_PORT = {KEY1_BUTTON_GPIO_PORT, KEY2_BUTTON_GPIO_PORT};
[*]//按键pin
[*]const uint16_t BUTTON_PIN = {KEY1_BUTTON_PIN, KEY2_BUTTON_PIN};
[*]//按键port
[*]const uint32_t BUTTON_CLK = {KEY1_BUTTON_GPIO_CLK, KEY2_BUTTON_GPIO_CLK};
[*]//外部中断先名
[*]const EINT_LINE_T BUTTON_EINT_LINE = {KEY1_BUTTON_EINT_LINE, KEY2_BUTTON_EINT_LINE};
[*]//外部中断源分组
[*]const SYSCFG_PORT_T BUTTON_PORT_SOURCE = {KEY1_BUTTON_EINT_PORT_SOURCE, KEY2_BUTTON_EINT_PORT_SOURCE};
[*]//外部中断源pin
[*]const SYSCFG_PIN_T BUTTON_PIN_SOURCE = {KEY1_BUTTON_EINT_PIN_SOURCE, KEY2_BUTTON_EINT_PIN_SOURCE};
[*]////外部中断源中断处理函数
[*]const IRQn_Type BUTTON_IRQn = {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);
[*]
[*] /** 配置gpio位输入模式,上拉 */
[*] GPIO_ConfigStructInit(&GPIO_configStruct);
[*] GPIO_configStruct.mode = GPIO_MODE_IN;//输入
[*] GPIO_configStruct.pin = BUTTON_PIN;//PIN
[*] GPIO_configStruct.pupd= GPIO_PUPD_UP;//上拉
[*] GPIO_Config(BUTTON_PORT, &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_PIN_SOURCE);
[*]
[*] /** Configure Button EINT line中断使能*/
[*] EINT_configStruct.line = BUTTON_EINT_LINE;
[*] 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, 0x0f, 0x0f);
[*] }
[*]}
[*]
[*]/*
[*] 读取按键状态
[*]*/
[*]uint8_t bsp_get_key(uint8_t Button)
[*]{
[*] return GPIO_ReadInputBit(BUTTON_PORT, BUTTON_PIN);
[*]}
[*]
[*]
[*]//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复制
[*]/*!
[*] * @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复制
[*]
[*]#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复制
[*]#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 调用复制
[*]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 调用http://bbs.**/data/attachment/forum/202305/29/220824juhliywix1usyzhz.png.thumb.jpg
页:
[1]