STM32
直播中

李骏鹏

7年用户 1212经验值
私信 关注
[问答]

stm32按键的长按/短按怎么实现?

STM32按键的长按/短按怎么实现?

回帖(1)

娄莉莉

2021-12-2 13:51:53

在学习过程中,遇到了要使用很多个按键的情况,(没有同时按下的处理,没有用矩阵键盘)。一增加一个新按键,需要改动的地方太多,在网上看了一篇博客


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");
}
这是修改后,并应用的工程,希望从网络中学习到更多的东西
举报

更多回帖

发帖
×
20
完善资料,
赚取积分