- button_init(&button1, read_button_pin, 0, 0);
3.注册按键事件
- button_attach(&button1, SINGLE_CLICK, Callback_SINGLE_CLICK_Handler);
- button_attach(&button1, DOUBLE_CLICK, Callback_DOUBLE_Click_Handler);
- ...
4.启动按键
5.设置一个5ms间隔的定时器循环调用后台处理函数
- while(1) {
- ...
- if(timer_ticks == 5) {
- timer_ticks = 0;
- button_ticks();
- }
- }
二. MultiButton的特性与事件我们看完使用方法,可以发现它是每个按键对象单独用一份数据结构管理
- 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;
- uint8_t (*hal_button_Level)(uint8_t button_id_);
- BtnCallback cb[number_of_event];
- struct Button* next;
- };
好处是这样每个按键使用单向链表相连,依次进入 button_handler(struct Button* handle) 状态机处理,所以每个按键的状态彼此独立。
标题我们一直强调MultiButton是一个事件驱动型按键驱动,那么它都支持哪些事件呢?
如下图,这是Multibutton支持的按键事件:
三. 移植MultiButton到CH32V103
1.新建工程与文件拷贝
mounriver新建工程真的很方便,大家可以参考:http://www.mounriver.com/help
文件拷贝的话,只要把multi_button.c和multi_button.h拷贝到工程目录即可,key.c和key.h是初始化ch32v103的gpio的。
2.实验平台
实验平台是我们自己设计的一款usb hid评估板,如下图:
板载8颗轻触开关,另外有一颗在摇杆电位器上,共9个按键。
原理图如下:
3.软件设计:
首先是9颗按键的初始化,主要在Key.c和key.h
因为SW1是摇杆电位器自带的,这里对应PA0,按下是高电平,这里需要下拉,其他按键是低电平按键都上拉。
- void KEY_INIT(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
- GPIO_Init(GPIOA, &GPIO_InitStructure);
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6
- |GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- }
这些是SW1~SW9对应的端口定义,
- #define B1_GPIO_PORT GPIOA
- #define B1_PIN GPIO_Pin_0
- #define B2_GPIO_PORT GPIOB
- #define B2_PIN GPIO_Pin_9
- #define B3_GPIO_PORT GPIOB
- #define B3_PIN GPIO_Pin_8
- #define B4_GPIO_PORT GPIOB
- #define B4_PIN GPIO_Pin_7
- #define B5_GPIO_PORT GPIOB
- #define B5_PIN GPIO_Pin_6
- #define B6_GPIO_PORT GPIOA
- #define B6_PIN GPIO_Pin_15
- #define B7_GPIO_PORT GPIOB
- #define B7_PIN GPIO_Pin_3
- #define B8_GPIO_PORT GPIOB
- #define B8_PIN GPIO_Pin_4
- #define B9_GPIO_PORT GPIOB
- #define B9_PIN GPIO_Pin_5
按键已经初始化完成,接着是multibutton的使用了
第一步先定义按键号与句柄
- enum Button_IDs {
- btn1_id,
- btn2_id,
- btn3_id,
- btn4_id,
- btn5_id,
- btn6_id,
- btn7_id,
- btn8_id,
- btn9_id,
- };
- struct Button btn1;
- struct Button btn2;
- struct Button btn3;
- struct Button btn4;
- struct Button btn5;
- struct Button btn6;
- struct Button btn7;
- struct Button btn8;
- struct Button btn9;
第二步是.初始化按键对象,绑定按键的GPIO电平读取接口read_button_pin() ,后一个参数设置有效触发电平- 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 GPIO_ReadInputDataBit(B1_GPIO_PORT, B1_PIN);
- case btn2_id:
- return GPIO_ReadInputDataBit(B2_GPIO_PORT, B2_PIN);
- case btn3_id:
- return GPIO_ReadInputDataBit(B3_GPIO_PORT, B3_PIN);
- case btn4_id:
- return GPIO_ReadInputDataBit(B4_GPIO_PORT, B4_PIN);
- case btn5_id:
- return GPIO_ReadInputDataBit(B5_GPIO_PORT, B5_PIN);
- case btn6_id:
- return GPIO_ReadInputDataBit(B6_GPIO_PORT, B6_PIN);
- case btn7_id:
- return GPIO_ReadInputDataBit(B7_GPIO_PORT, B7_PIN);
- case btn8_id:
- return GPIO_ReadInputDataBit(B8_GPIO_PORT, B8_PIN);
- case btn9_id:
- return GPIO_ReadInputDataBit(B9_GPIO_PORT, B9_PIN);
- default:
- return 0;
- }
- }
- button_init(&btn1, read_button_GPIO, 1, btn1_id);
- button_init(&btn2, read_button_GPIO, 0, btn2_id);
- button_init(&btn3, read_button_GPIO, 0, btn3_id);
- button_init(&btn4, read_button_GPIO, 0, btn4_id);
- button_init(&btn5, read_button_GPIO, 0, btn5_id);
- button_init(&btn6, read_button_GPIO, 0, btn6_id);
- button_init(&btn7, read_button_GPIO, 0, btn7_id);
- button_init(&btn8, read_button_GPIO, 0, btn8_id);
- button_init(&btn9, read_button_GPIO, 0, btn9_id);
第三步注册按键事件并启动,- button_attach(&btn1, PRESS_DOWN, BTN1_PRESS_DOWN_Handler);
- button_attach(&btn1, PRESS_UP, BTN1_PRESS_UP_Handler);
- button_attach(&btn2, PRESS_DOWN, BTN2_PRESS_DOWN_Handler);
- button_attach(&btn2, PRESS_UP, BTN2_PRESS_UP_Handler);
- button_attach(&btn3, PRESS_DOWN, BTN3_PRESS_DOWN_Handler);
- button_attach(&btn3, PRESS_UP, BTN3_PRESS_UP_Handler);
- button_attach(&btn4, PRESS_DOWN, BTN4_PRESS_DOWN_Handler);
- button_attach(&btn4, PRESS_UP, BTN4_PRESS_UP_Handler);
- button_attach(&btn5, PRESS_DOWN, BTN5_PRESS_DOWN_Handler);
- button_attach(&btn5, PRESS_UP, BTN5_PRESS_UP_Handler);
- button_attach(&btn6, PRESS_DOWN, BTN6_PRESS_DOWN_Handler);
- button_attach(&btn6, PRESS_UP, BTN6_PRESS_UP_Handler);
- button_attach(&btn7, PRESS_DOWN, BTN7_PRESS_DOWN_Handler);
- button_attach(&btn7, PRESS_UP, BTN7_PRESS_UP_Handler);
- button_attach(&btn8, PRESS_DOWN, BTN8_PRESS_DOWN_Handler);
- button_attach(&btn8, PRESS_UP, BTN8_PRESS_UP_Handler);
- button_attach(&btn9, PRESS_DOWN, BTN9_PRESS_DOWN_Handler);
- button_attach(&btn9, PRESS_UP, BTN9_PRESS_UP_Handler);
- button_start(&btn1);
- button_start(&btn2);
- button_start(&btn3);
- button_start(&btn4);
- button_start(&btn5);
- button_start(&btn6);
- button_start(&btn7);
- button_start(&btn8);
- button_start(&btn9);
最后设置一个5ms间隔的定时器循环调用后台处理函数,这里贴出main.c代码:
- #include "debug.h"
- #include "multi_button.h"
- #include "key.h"
- /* Global typedef */
- enum Button_IDs {
- btn1_id,
- btn2_id,
- btn3_id,
- btn4_id,
- btn5_id,
- btn6_id,
- btn7_id,
- btn8_id,
- btn9_id,
- };
- struct Button btn1;
- struct Button btn2;
- struct Button btn3;
- struct Button btn4;
- struct Button btn5;
- struct Button btn6;
- struct Button btn7;
- struct Button btn8;
- struct Button btn9;
- /* Global define */
- /* Global Variable */
- 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 GPIO_ReadInputDataBit(B1_GPIO_PORT, B1_PIN);
- case btn2_id:
- return GPIO_ReadInputDataBit(B2_GPIO_PORT, B2_PIN);
- case btn3_id:
- return GPIO_ReadInputDataBit(B3_GPIO_PORT, B3_PIN);
- case btn4_id:
- return GPIO_ReadInputDataBit(B4_GPIO_PORT, B4_PIN);
- case btn5_id:
- return GPIO_ReadInputDataBit(B5_GPIO_PORT, B5_PIN);
- case btn6_id:
- return GPIO_ReadInputDataBit(B6_GPIO_PORT, B6_PIN);
- case btn7_id:
- return GPIO_ReadInputDataBit(B7_GPIO_PORT, B7_PIN);
- case btn8_id:
- return GPIO_ReadInputDataBit(B8_GPIO_PORT, B8_PIN);
- case btn9_id:
- return GPIO_ReadInputDataBit(B9_GPIO_PORT, B9_PIN);
- default:
- return 0;
- }
- }
- void BTN1_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN1_PRESS_DOWN\r\n");
- }
- void BTN1_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN1_PRESS_UP\r\n");
- }
- void BTN2_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN2_PRESS_DOWN\r\n");
- }
- void BTN2_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN2_PRESS_UP\r\n");
- }
- void BTN3_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN3_PRESS_DOWN\r\n");
- }
- void BTN3_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN3_PRESS_UP\r\n");
- }
- void BTN4_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN4_PRESS_DOWN\r\n");
- }
- void BTN4_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN4_PRESS_UP\r\n");
- }
- void BTN5_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN5_PRESS_DOWN\r\n");
- }
- void BTN5_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN5_PRESS_UP\r\n");
- }
- void BTN6_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN6_PRESS_DOWN\r\n");
- }
- void BTN6_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN6_PRESS_UP\r\n");
- }
- void BTN7_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN7_PRESS_DOWN\r\n");
- }
- void BTN7_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN7_PRESS_UP\r\n");
- }
- void BTN8_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN8_PRESS_DOWN\r\n");
- }
- void BTN8_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN8_PRESS_UP\r\n");
- }
- void BTN9_PRESS_DOWN_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN9_PRESS_DOWN\r\n");
- }
- void BTN9_PRESS_UP_Handler(void* btn)
- {
- //do something...
- printf("\r\nBTN9_PRESS_UP\r\n");
- }
- /*********************************************************************
- * @fn main
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] Main program.
- *
- * [url=home.php?mod=space&uid=266161]@return[/url] none
- */
- int main(void)
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
- Delay_Init();
- USART_Printf_Init(115200);
- printf("SystemClk:%d\r\n", SystemCoreClock);
- printf("This is printf example\r\n");
- KEY_INIT();
- button_init(&btn1, read_button_GPIO, 1, btn1_id);
- button_init(&btn2, read_button_GPIO, 0, btn2_id);
- button_init(&btn3, read_button_GPIO, 0, btn3_id);
- button_init(&btn4, read_button_GPIO, 0, btn4_id);
- button_init(&btn5, read_button_GPIO, 0, btn5_id);
- button_init(&btn6, read_button_GPIO, 0, btn6_id);
- button_init(&btn7, read_button_GPIO, 0, btn7_id);
- button_init(&btn8, read_button_GPIO, 0, btn8_id);
- button_init(&btn9, read_button_GPIO, 0, btn9_id);
- button_attach(&btn1, PRESS_DOWN, BTN1_PRESS_DOWN_Handler);
- button_attach(&btn1, PRESS_UP, BTN1_PRESS_UP_Handler);
- button_attach(&btn2, PRESS_DOWN, BTN2_PRESS_DOWN_Handler);
- button_attach(&btn2, PRESS_UP, BTN2_PRESS_UP_Handler);
- button_attach(&btn3, PRESS_DOWN, BTN3_PRESS_DOWN_Handler);
- button_attach(&btn3, PRESS_UP, BTN3_PRESS_UP_Handler);
- button_attach(&btn4, PRESS_DOWN, BTN4_PRESS_DOWN_Handler);
- button_attach(&btn4, PRESS_UP, BTN4_PRESS_UP_Handler);
- button_attach(&btn5, PRESS_DOWN, BTN5_PRESS_DOWN_Handler);
- button_attach(&btn5, PRESS_UP, BTN5_PRESS_UP_Handler);
- button_attach(&btn6, PRESS_DOWN, BTN6_PRESS_DOWN_Handler);
- button_attach(&btn6, PRESS_UP, BTN6_PRESS_UP_Handler);
- button_attach(&btn7, PRESS_DOWN, BTN7_PRESS_DOWN_Handler);
- button_attach(&btn7, PRESS_UP, BTN7_PRESS_UP_Handler);
- button_attach(&btn8, PRESS_DOWN, BTN8_PRESS_DOWN_Handler);
- button_attach(&btn8, PRESS_UP, BTN8_PRESS_UP_Handler);
- button_attach(&btn9, PRESS_DOWN, BTN9_PRESS_DOWN_Handler);
- button_attach(&btn9, PRESS_UP, BTN9_PRESS_UP_Handler);
- button_start(&btn1);
- button_start(&btn2);
- button_start(&btn3);
- button_start(&btn4);
- button_start(&btn5);
- button_start(&btn6);
- button_start(&btn7);
- button_start(&btn8);
- button_start(&btn9);
- while(1)
- {
- button_ticks();
- Delay_Ms(5);
- }
- }
4.下载验证:
按下对应的按键,会有按下和松开事件的回调,特别适用于我们做usb hid的按键扫描!!