STM32基于MultiButton驱动按键
简介:STM32F103C8T6基于MultiButton驱动按键源码介绍。
开发平台:KEIL ARM
MCU型号:STM32F103C8T6
传感器型号:MultiButton
特别提示:驱动内可能使用了某些其他组件,比如delay等,在文末外设模板下载地址内有。
1积分源码下载地址在文末!!!
使用举例:
#include <stdio.h>
#include "BUTTON.h"int main()
{KEYClass.Init(); // 初始化while(1) {}
}
// 将扫描函数加入MultiButton.h文件内TICKS_INTERVAL宏定义的周期的定时器内进行扫描
void TIM_5msIRQHandle()
{KEYClass.Scan();
}
驱动源码:
BUTTON.c
#include "main.h"
#include "MultiButton.h"static void KEY_GPIO_Config(void);
static uint8_t read_key1_pin(void);
static uint8_t read_key2_pin(void);
static void key1_shortPress_handle(void *btn);
static void key2_shortPress_handle(void *btn);
static void key1_longPress_handle(void *btn);
static void key2_longPress_handle(void *btn);static void KEY_Init(void);
static void KEY_Scan(void);KEYClassStruct KEYClass = {.Init = KEY_Init,.Scan = KEY_Scan,.Read_key1 = read_key1_pin,.Read_key2 = read_key2_pin
};// 按键结构体
struct Button key1;
struct Button key2;#define KEY1_PORT_CLK (RCC_APB2Periph_GPIOB)
#define KEY1_PORT GPIOB
#define KEY1_PIN GPIO_Pin_6
#define KEY2_PORT_CLK (RCC_APB2Periph_GPIOB)
#define KEY2_PORT GPIOB
#define KEY2_PIN GPIO_Pin_7static void KEY_GPIO_Config(void)
{GPIO_InitTypeDef GPIO_InitStructure;/*开启按键GPIO口的时钟*/RCC_APB2PeriphClockCmd(KEY1_PORT_CLK | KEY2_PORT_CLK,ENABLE);/*初始化GPIO*/GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = KEY1_PIN;GPIO_Init(KEY1_PORT,&GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = KEY2_PIN;GPIO_Init(KEY2_PORT,&GPIO_InitStructure);
}static uint8_t read_key1_pin(void)
{return GPIO_ReadInputDataBit(KEY1_PORT, KEY1_PIN);
}
static uint8_t read_key2_pin(void)
{return GPIO_ReadInputDataBit(KEY2_PORT, KEY2_PIN);
}
// key1短按切换页面
static void key1_shortPress_handle(void *btn)
{#ifdef DEBUG_printfprintf("key1 short press\\n");#endif
}
// key2短按切换选项 ·················
static void key2_shortPress_handle(void *btn)
{#ifdef DEBUG_printfprintf("key2 short press\\n");#endif
}
// key1长按
static void key1_longPress_handle(void *btn)
{#ifdef DEBUG_printfprintf("key1 long press\\n");#endif
}
// key2长按
static void key2_longPress_handle(void *btn)
{#ifdef DEBUG_printfprintf("key2 long press\\n");#endif
}static void KEY_Init(void)
{KEY_GPIO_Config();button_init(&key1, read_key1_pin, 0);button_init(&key2, read_key2_pin, 0);button_attach(&key1, SINGLE_CLICK, key1_shortPress_handle);button_attach(&key2, SINGLE_CLICK, key2_shortPress_handle);button_attach(&key1, LONG_PRESS_START, key1_longPress_handle);button_attach(&key2, LONG_PRESS_START, key2_longPress_handle);button_start(&key1);button_start(&key2);
}static void KEY_Scan(void)
{button_ticks();
}
BUTTON.h
#ifndef __BUTTON_AS_H
#define __BUTTON_AS_H #include "main.h" typedef struct {void (* Init)(void);void (* Scan)(void);uint8_t (* Read_key1)(void);uint8_t (* Read_key2)(void);
} KEYClassStruct;extern KEYClassStruct KEYClass;#endif
MultiButton.c
/ Copyright (c) 2016 Zibin Zheng <znbin@qq.com>* All rights reserved*/#include "MultiButton.h"#define EVENT_CB(ev) if(handle->cb[ev])handle->cb[ev]((Button*)handle)//button handle list head.
static struct Button* head_handle = NULL;/* @brief Initializes the button struct handle.* @param handle: the button handle strcut.* @param pin_level: read the HAL GPIO of the connet button level.* @param active_level: pressed GPIO level.* @retval None*/
void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level)
{memset(handle, 0, sizeof(struct Button));handle->event = (uint8_t)NONE_PRESS;handle->hal_button_Level = pin_level;handle->button_level = handle->hal_button_Level();handle->active_level = active_level;
}/* @brief Attach the button event callback function.* @param handle: the button handle strcut.* @param event: trigger event type.* @param cb: callback function.* @retval None*/
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb)
{handle->cb[event] = cb;
}/* @brief Inquire the button event happen.* @param handle: the button handle strcut.* @retval button event.*/
PressEvent get_button_event(struct Button* handle)
{return (PressEvent)(handle->event);
}/* @brief Button driver core function, driver state machine.* @param handle: the button handle strcut.* @retval None*/
void button_handler(struct Button* handle)
{uint8_t read_gpio_level = handle->hal_button_Level();//ticks counter working..if((handle->state) > 0) handle->ticks++;/*------------button debounce handle---------------*/if(read_gpio_level != handle->button_level) { //not equal to prev one//continue read 3 times same new level changeif(++(handle->debounce_cnt) >= DEBOUNCE_TICKS) {handle->button_level = read_gpio_level;handle->debounce_cnt = 0;}} else { //leved not change ,counter reset.handle->debounce_cnt = 0;}/*-----------------State machine-------------------*/switch (handle->state) {case 0:if(handle->button_level == handle->active_level) { //start press downhandle->event = (uint8_t)PRESS_DOWN;EVENT_CB(PRESS_DOWN);handle->ticks = 0;handle->repeat = 1;handle->state = 1;} else {handle->event = (uint8_t)NONE_PRESS;}break;case 1:if(handle->button_level != handle->active_level) { //released press uphandle->event = (uint8_t)PRESS_UP;EVENT_CB(PRESS_UP);handle->ticks = 0;handle->state = 2;} else if(handle->ticks > LONG_TICKS) {handle->event = (uint8_t)LONG_PRESS_START;EVENT_CB(LONG_PRESS_START);handle->state = 5;}break;case 2:if(handle->button_level == handle->active_level) { //press down againhandle->event = (uint8_t)PRESS_DOWN;EVENT_CB(PRESS_DOWN);handle->repeat++;EVENT_CB(PRESS_REPEAT); // repeat hithandle->ticks = 0;handle->state = 3;} else if(handle->ticks > SHORT_TICKS) { //released timeoutif(handle->repeat == 1) {handle->event = (uint8_t)SINGLE_CLICK;EVENT_CB(SINGLE_CLICK);} else if(handle->repeat == 2) {handle->event = (uint8_t)DOUBLE_CLICK;EVENT_CB(DOUBLE_CLICK); // repeat hit}handle->state = 0;}break;case 3:if(handle->button_level != handle->active_level) { //released press uphandle->event = (uint8_t)PRESS_UP;EVENT_CB(PRESS_UP);if(handle->ticks < SHORT_TICKS) {handle->ticks = 0;handle->state = 2; //repeat press} else {handle->state = 0;}}else if(handle->ticks > SHORT_TICKS){ // long press uphandle->state = 0;}break;case 5:if(handle->button_level == handle->active_level) {//continue hold triggerhandle->event = (uint8_t)LONG_PRESS_HOLD;EVENT_CB(LONG_PRESS_HOLD);} else { //releasdhandle->event = (uint8_t)PRESS_UP;EVENT_CB(PRESS_UP);handle->state = 0; //reset}break;}
}/* @brief Start the button work, add the handle into work list.* @param handle: target handle strcut.* @retval 0: succeed. -1: already exist.*/
int button_start(struct Button* handle)
{struct Button* target = head_handle;while(target) {if(target == handle) return -1; //already exist.target = target->next;}handle->next = head_handle;head_handle = handle;return 0;
}/* @brief Stop the button work, remove the handle off work list.* @param handle: target handle strcut.* @retval None*/
void button_stop(struct Button* handle)
{struct Button curr;for(curr = &head_handle; *curr; ) {struct Button* entry = *curr;if (entry == handle) {*curr = entry->next;
// free(entry);return;//glacier add 2021-8-18} elsecurr = &entry->next;}
}/* @brief background ticks, timer repeat invoking interval 5ms.* @param None.* @retval None*/
void button_ticks()
{struct Button* target;for(target=head_handle; target; target=target->next) {button_handler(target);}
}
MultiButton.h
/ Copyright (c) 2016 Zibin Zheng <znbin@qq.com>* All rights reserved*/#ifndef _MULTI_BUTTON_H_
#define _MULTI_BUTTON_H_#include "stdint.h"
#include "string.h"//According to your need to modify the constants.
#define TICKS_INTERVAL 5 //ms
#define DEBOUNCE_TICKS 3 //MAX 8
#define SHORT_TICKS (300 /TICKS_INTERVAL)
#define LONG_TICKS (1000 /TICKS_INTERVAL)typedef void (*BtnCallback)(void*);typedef enum {PRESS_DOWN = 0,PRESS_UP,PRESS_REPEAT,SINGLE_CLICK,DOUBLE_CLICK,LONG_PRESS_START,LONG_PRESS_HOLD,number_of_event,NONE_PRESS
}PressEvent;typedef struct Button {uint16_t ticks;uint8_t repeat : 4;uint8_t event : 4;uint8_t state : 3;uint8_t debounce_cnt : 3;uint8_t active_level : 1;uint8_t button_level : 1;uint8_t (*hal_button_Level)(void);BtnCallback cb[number_of_event];struct Button* next;
}Button;#ifdef __cplusplus
extern "C" {
#endifvoid button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level);
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb);
PressEvent get_button_event(struct Button* handle);
int button_start(struct Button* handle);
void button_stop(struct Button* handle);
void button_ticks(void);#ifdef __cplusplus
}
#endif#endif
驱动下载地址:
https://download.csdn.net/download/m0_50669075/87672800
STM32工程模板、外设模板、模块模板下载地址:
stm32_template: STM32F103工程模板,外设模板,模块模板。模块模板包括:DHT11温湿度传感器,OLED屏幕,DS18B20温度传感器,DS1302时钟模块,红外测温模块,RFID模块,SIM900A短信模块,OneNET入网,ADXL345三轴传感器,离线语音识别模块,语音播报模块,甲醛传感器,PM2.5模块,SG90舵机,健康检测模块,消息队列示例,链表示例,分时调度系统示例等。