在学习过程中,遇到了要使用很多个按键的情况,(没有同时按下的处理,没有用矩阵键盘)。一增加一个新按键,需要改动的地方太多,在网上看了一篇博客
https://blog.csdn.net/jiejiemcu/article/details/83097992
觉得它使用的方法不错,就进行学习研究,移植到stm32单片机上。这种编程思想值得学习,做个小总结。
typedef struct button
{
/* 下面是一个函数指针,指向判断按键手否按下的函数 */
uint8_t (*Read_Button_Level)(void); /* 读取按键电平函数,需要用户实现 */
char Name[BTN_NAME_MAX];
uint8_t Button_State : 4; /* 按键当前状态(按下还是弹起) */
uint8_t Button_Last_State : 4; /* 上一次的按键状态,用于判断双击 */
uint8_t Button_Trigger_Level: 2; /* 按键触发电平 */
uint8_t Button_Last_Level: 2; /* 按键当前电平 */
uint8_t Button_Trigger_Event; /* 按键触发事件,单击,双击,长按等 */
Button_CallBack CallBack_Function[number_of_event];
uint8_t Button_Cycle; /* 连续按键周期 */
uint8_t Timer_Count; /* 计时 */
uint8_t Debounce_Time; /* 消抖时间 */
uint8_t Long_Time_Record; /* 有长按记录 */
uint8_t Long_Time; /* 按键按下持续时间 */
struct button *Next;
}Button_t
uint8_t (*Read_Button_Level)(void); /* 读取按键电平函数,需要用户实现 */
这段代码是一个函数指针形式,指向函数的指针,可以用来塞用户的函数
函数指针的定义:如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。
关于函数指针的详解:
https://blog.csdn.net/luoyayun361/article/details/80428882
Button_CallBack CallBack_Function[number_of_event]; 这是一个回调函数的数组,
#define TRIGGER_CB(event) if(btn->CallBack_Function[event]) btn->CallBack_Function[event]((Button_t*)btn)
这个是关于回调的解析:
https://blog.csdn.net/booirror/article/details/20007009
通过jlink_rttview 进行打印,按键的信息
按键1按下,短按,双击,长按,长按释放
这里是20ms轮询一下相应的按键状态查询函数
按键的创建程序,相应的回调函数,事件和stm32的低层函数进行连接
/************************************************************
* @brief 按键创建
* @param name : 按键名称
* @param btn : 按键结构体
* @param read_btn_level : 按键电平读取函数,需要用户自己实现返回uint8_t类型的电平
* @param btn_trigger_level : 按键触发电平
* @note NULL
***********************************************************/
void Button_Create(const char *name,
Button_t *btn,
uint8_t(*read_btn_level)(void),
uint8_t btn_trigger_level)
{
if(btn == NULL)
{
SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_BRIGHT_RED"struct button is null!"RTT_CTRL_RESET"n");
}
memset(btn,0,sizeof(*btn));
StrnCopy(btn->Name,name,BTN_NAME_MAX);
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = NONE_TRIGGER;
btn->Button_Trigger_Event = NONE_TRIGGER;
btn->Read_Button_Level = read_btn_level;
btn->Button_Trigger_Level = btn_trigger_level;
btn->Button_Last_Level = btn->Read_Button_Level();
btn->Debounce_Time = 0;
btn->Long_Time_Record = 0;
SEGGER_RTT_printf(0,"button create success n");
Add_Button(btn);
Print_Btn_Info(btn);
}
相应的回调函数,用户可以将要处理的事件放在这段函数里
/************************************************************
* @brief 相应的回调事件
* @param btn:处理的按键
* @return NULL
* @note 用户可在这里添加自己的事件处理函数
***********************************************************/
void Btn1_Down_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_Down_CallBackn");
}
void Btn1_Double_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_Double_CallBackn");
}
void Btn1_Long_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_Long_CallBackn");
}
void Btn1_LongFree_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_LongFree_CallBackn");
}
这是修改后,并应用的工程,希望从网络中学习到更多的东西
在学习过程中,遇到了要使用很多个按键的情况,(没有同时按下的处理,没有用矩阵键盘)。一增加一个新按键,需要改动的地方太多,在网上看了一篇博客
https://blog.csdn.net/jiejiemcu/article/details/83097992
觉得它使用的方法不错,就进行学习研究,移植到stm32单片机上。这种编程思想值得学习,做个小总结。
typedef struct button
{
/* 下面是一个函数指针,指向判断按键手否按下的函数 */
uint8_t (*Read_Button_Level)(void); /* 读取按键电平函数,需要用户实现 */
char Name[BTN_NAME_MAX];
uint8_t Button_State : 4; /* 按键当前状态(按下还是弹起) */
uint8_t Button_Last_State : 4; /* 上一次的按键状态,用于判断双击 */
uint8_t Button_Trigger_Level: 2; /* 按键触发电平 */
uint8_t Button_Last_Level: 2; /* 按键当前电平 */
uint8_t Button_Trigger_Event; /* 按键触发事件,单击,双击,长按等 */
Button_CallBack CallBack_Function[number_of_event];
uint8_t Button_Cycle; /* 连续按键周期 */
uint8_t Timer_Count; /* 计时 */
uint8_t Debounce_Time; /* 消抖时间 */
uint8_t Long_Time_Record; /* 有长按记录 */
uint8_t Long_Time; /* 按键按下持续时间 */
struct button *Next;
}Button_t
uint8_t (*Read_Button_Level)(void); /* 读取按键电平函数,需要用户实现 */
这段代码是一个函数指针形式,指向函数的指针,可以用来塞用户的函数
函数指针的定义:如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址。既然是地址我们就可以定义一个指针变量来存放,这个指针变量就叫作函数指针变量,简称函数指针。
关于函数指针的详解:
https://blog.csdn.net/luoyayun361/article/details/80428882
Button_CallBack CallBack_Function[number_of_event]; 这是一个回调函数的数组,
#define TRIGGER_CB(event) if(btn->CallBack_Function[event]) btn->CallBack_Function[event]((Button_t*)btn)
这个是关于回调的解析:
https://blog.csdn.net/booirror/article/details/20007009
通过jlink_rttview 进行打印,按键的信息
按键1按下,短按,双击,长按,长按释放
这里是20ms轮询一下相应的按键状态查询函数
按键的创建程序,相应的回调函数,事件和stm32的低层函数进行连接
/************************************************************
* @brief 按键创建
* @param name : 按键名称
* @param btn : 按键结构体
* @param read_btn_level : 按键电平读取函数,需要用户自己实现返回uint8_t类型的电平
* @param btn_trigger_level : 按键触发电平
* @note NULL
***********************************************************/
void Button_Create(const char *name,
Button_t *btn,
uint8_t(*read_btn_level)(void),
uint8_t btn_trigger_level)
{
if(btn == NULL)
{
SEGGER_RTT_WriteString(0, RTT_CTRL_TEXT_BRIGHT_RED"struct button is null!"RTT_CTRL_RESET"n");
}
memset(btn,0,sizeof(*btn));
StrnCopy(btn->Name,name,BTN_NAME_MAX);
btn->Button_State = NONE_TRIGGER;
btn->Button_Last_State = NONE_TRIGGER;
btn->Button_Trigger_Event = NONE_TRIGGER;
btn->Read_Button_Level = read_btn_level;
btn->Button_Trigger_Level = btn_trigger_level;
btn->Button_Last_Level = btn->Read_Button_Level();
btn->Debounce_Time = 0;
btn->Long_Time_Record = 0;
SEGGER_RTT_printf(0,"button create success n");
Add_Button(btn);
Print_Btn_Info(btn);
}
相应的回调函数,用户可以将要处理的事件放在这段函数里
/************************************************************
* @brief 相应的回调事件
* @param btn:处理的按键
* @return NULL
* @note 用户可在这里添加自己的事件处理函数
***********************************************************/
void Btn1_Down_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_Down_CallBackn");
}
void Btn1_Double_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_Double_CallBackn");
}
void Btn1_Long_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_Long_CallBackn");
}
void Btn1_LongFree_CallBack(void *btn)
{
SEGGER_RTT_printf(0,"Btn1_LongFree_CallBackn");
}
这是修改后,并应用的工程,希望从网络中学习到更多的东西
举报