MultiButton多功能模块

开源按键库MultiButton

点击此连接下载

按钮结构体

/* 声明一个按键结构体类型(链表) */
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  button_id;           //按键ID 
	uint8_t  (*hal_button_Level)(uint8_t button_id_);    //获取按键电平的函数指针
	BtnCallback  cb[number_of_event];                    //按键回调函数指针数组(事件)
	struct Button* next;                                 //按键使用链表存储
}Button;

按钮事件驱动枚举

/* 声明一个按键事件的枚举类型,包括了所有的按键操作类型 */
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;

第一步:按键初始化函数

/**
  * @brief  初始化按键结构体变量handle
  * @param  handle: 按键结构体变量
  * @param  pin_level: 读取按键电平的函数(这里需要定义一个指定类型的函数来获取按键电平)
  * @param  active_level: 按键按下时的电平
  * @param  button_id: 自定义的按键ID
  * @retval None
  */
//按键结构体初始化,赋予按键获取电平的函数指针,并读出当前电平
void button_init(struct Button* handle, uint8_t(*pin_level)(uint8_t), uint8_t active_level, uint8_t button_id)
{
	//结构体初始化为全0
	memset(handle, 0, sizeof(struct Button)); 
	//初始化为没有按键事件
	handle->event = (uint8_t)NONE_PRESS;
	//读取按键电平状态函数指针
	handle->hal_button_Level = pin_level;
	//读取按键电平
	handle->button_level = !active_level;
	//按下有效电平
	handle->active_level = active_level;
	//按键号
	handle->button_id = button_id;
}

第二步:将当前按键与按键事件相关联

/**
  * @brief  Attach the button event callback function.
  * @param  handle: 定义的按键结构体
  * @param  event: 按键事件,想要一个按键触发多个事件时,可以多次调用该函数
  * @param  cb: 回调函数(需要人为定义)
  * @retval None
  */
//按键注册(赋予特定的按键事件以回调函数)
void button_attach(struct Button* handle, PressEvent event, BtnCallback cb)
{
	handle->cb[event] = cb;
}

第三步:该按键已经初始化完成,下面需要将该按键加入到按键链表之中

/**
  * @brief  将(Button*)handle 添加到链表头部
  * @param  handle: target handle struct.
  * @retval 0: succeed. -1: already exist.
  */
 /*启动一个按键,即新增一个按键结构体链表节点*/
int button_start(struct Button* handle)
{
	struct Button* target = head_handle;
	while(target) {	//如果当前结构体已经在链表中存在,返回-1
		if(target == handle) return -1;	//already exist.
		target = target->next;
	}
	handle->next = head_handle;
	head_handle = handle;
	return 0;
}

定时扫描链表

/**
  * @brief  background ticks, timer repeat invoking interval 5ms.
  *     按键扫描,扫描时长由用户实现
  * @param  None.
  * @retval None
  */
/*按键节拍,每一次节拍事件遍历按键列表中所有按键,调用驱动函数*/
void button_ticks(void)
{
	struct Button* target;
	for(target=head_handle; target; target=target->next) {
		button_handler(target);	//核心逻辑实现,按键回调事件在该函数中调用(满足条件)
		
	}
}

代码调用:

#include "multi_button.h"

enum Button_IDs {
	btn1_id,
	btn2_id,
};

struct Button btn1;
struct Button btn2;

uint8_t read_button_GPIO(uint8_t button_id)
{
	// you can share the GPIO read function with multiple Buttons
	switch(button_id)
	{
		case btn1_id:
			return HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin);
		case btn2_id:
			return HAL_GPIO_ReadPin(B2_GPIO_Port, B2_Pin);
		default:
			return 0;
	}
}

int main()
{
	button_init(&btn1, read_button_GPIO, 0, btn1_id);
	button_init(&btn2, read_button_GPIO, 0, btn2_id);

	button_attach(&btn1, PRESS_DOWN,       BTN1_PRESS_DOWN_Handler);
	button_attach(&btn1, PRESS_UP,         BTN1_PRESS_UP_Handler);
	button_attach(&btn1, PRESS_REPEAT,     BTN1_PRESS_REPEAT_Handler);
	button_attach(&btn1, SINGLE_CLICK,     BTN1_SINGLE_Click_Handler);
	button_attach(&btn1, DOUBLE_CLICK,     BTN1_DOUBLE_Click_Handler);
	button_attach(&btn1, LONG_PRESS_START, BTN1_LONG_PRESS_START_Handler);
	button_attach(&btn1, LONG_PRESS_HOLD,  BTN1_LONG_PRESS_HOLD_Handler);

	button_attach(&btn2, PRESS_DOWN,       BTN2_PRESS_DOWN_Handler);
	button_attach(&btn2, PRESS_UP,         BTN2_PRESS_UP_Handler);
	button_attach(&btn2, PRESS_REPEAT,     BTN2_PRESS_REPEAT_Handler);
	button_attach(&btn2, SINGLE_CLICK,     BTN2_SINGLE_Click_Handler);
	button_attach(&btn2, DOUBLE_CLICK,     BTN2_DOUBLE_Click_Handler);
	button_attach(&btn2, LONG_PRESS_START, BTN2_LONG_PRESS_START_Handler);
	button_attach(&btn2, LONG_PRESS_HOLD,  BTN2_LONG_PRESS_HOLD_Handler);

	button_start(&btn1);
	button_start(&btn2);

	//make the timer invoking the button_ticks() interval 5ms.
	//This function is implemented by yourself.
	__timer_start(button_ticks, 0, 5);

	while(1)
	{}
}

void BTN1_PRESS_DOWN_Handler(void* btn)
{
	//do something...
}

void BTN1_PRESS_UP_Handler(void* btn)
{
	//do something...
}

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值