打印
[AT32F423]

【AT-START-F423测评】移植一个优秀的按键程序

[复制链接]
1868|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lulugl|  楼主 | 2023-10-25 09:32 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 lulugl 于 2023-10-25 09:34 编辑

#申请原创# #有奖活动#@21ic小跑堂
【按键驱动】
单片机在输入设备中,按键是最简单经济可靠的设备之一。单按键可以直接由GPIO来驱动,采集他的高低电平来实现按键状态的功能,但是在实际中,按键的状态获取,要考虑到消抖情况,如果单一按键要通过单击、双击、连击、长按等来实现结合功能,那就实现起来就非常复杂,效果也不是非常好。
在github中我找到了一个开源的按键驱动,Button_drive是一个小巧的按键驱动,支持单击、双击、长按、连续触发等(后续可以在按键控制块中添加触发事件),理论上可无限量扩展Button,Button_drive采用按键触发事件回调方式处理业务逻辑,支持在RTOS中使用,我目前仅在 HYPERLINK "https://github.com/RT-Thread/rt-thread" 上测试过。 写按键驱动的目的是想要将用户按键逻辑与按键处理事件分离,用户无需处理复杂麻烦的逻辑事件。https://github.com/jiejieTop/ButtonDrive
【实现方式】
下载github源码
复制一份示例的printf工程到一个新的文件夹中,重命名为printf_button。

解压源码后复制button.c/h到工程文件的middlewares下的button文件夹中。

在工程文件中新增button组,把button.c加入button组中。

添加头文件的引用。

在button.c中添加at32f423_board.h头文件的引用。

在button.c中实现按键电平的获取自定义函数,在模版工程中,官方在at32f423_board.c中实现的按键的初始化,我们直接引用就可以实现按键状态的获取:
/* 获取按键电平 */

uint8_t Read_KEY1_Level(void)

{

return at32_button_state();

}

在main.c中,我们实现用户的单击、双击、长按释放的功能回调函数,代码如下:
Button_t Button1;

void Btn1_Dowm_CallBack(void *btn)

{

printf("Button1 单击!\r\n");

}

void Btn1_Double_CallBack(void *btn)

{

printf("Button1 双击!\r\n");

}

void Btn1_Long_CallBack(void *btn)

{

printf("Button1 长按!\r\n");

}

void Btn1_ContinuosFree_CallBack(void *btn)

{

printf("Button1 连按释放!\r\n");

}

在主函中,我们注册需要实现的功能函数,我这里添加单击、双击、长按、长按释放,代码如下:
Button_Attach(&Button1,BUTTON_DOWM,Btn1_Dowm_CallBack); //单击

Button_Attach(&Button1,BUTTON_DOUBLE,Btn1_Double_CallBack); //双击

Button_Attach(&Button1,BUTTON_LONG,Btn1_Long_CallBack); //长按BUTTON_LONG_FREE,

Button_Attach(&Button1,BUTTON_LONG_FREE,Btn1_ContinuosFree_CallBack);

在while中添加按键检测函数:
Button_Process(); //需要周期调用按键处理函数

到此,移植结束,下载到开发板上可以实现相应的功能,按下开发板的按键,就在串口打印出相应的状态:

button.c完整程序如下:
/************************************************************
  * [url=home.php?mod=space&uid=247401]@brief[/url]   按键驱动
        * @param   NULL
  * [url=home.php?mod=space&uid=266161]@return[/url]  NULL
  * [url=home.php?mod=space&uid=187600]@author[/url]  jiejie
  * [url=home.php?mod=space&uid=2757600]@Github[/url]  https://github.com/jiejieTop
  * [url=home.php?mod=space&uid=212281]@date[/url]    2018-xx-xx
  * [url=home.php?mod=space&uid=895143]@version[/url] v1.0
  * [url=home.php?mod=space&uid=536309]@NOTE[/url]    button.c
  ***********************************************************/
#include "button.h"
#include "at32f423_board.h"
#include "stdio.h"
#include "string.h"
/*******************************************************************
*                          变量声明                              
*******************************************************************/

static struct button* Head_Button = NULL;


/*******************************************************************
*                         函数声明     
*******************************************************************/
static char *StrnCopy(char *dst, const char *src, uint32_t n);
static void Print_Btn_Info(Button_t* btn);
static void Add_Button(Button_t* btn);


/************************************************************
  * [url=home.php?mod=space&uid=247401]@brief[/url]   按键创建
        * @param   name : 按键名称
        * @param   btn : 按键结构体
  * @param   read_btn_level : 按键电平读取函数,需要用户自己实现返回uint8_t类型的电平
  * @param   btn_trigger_level : 按键触发电平
  * [url=home.php?mod=space&uid=266161]@return[/url]  NULL
  * [url=home.php?mod=space&uid=187600]@author[/url]  jiejie
  * [url=home.php?mod=space&uid=2757600]@Github[/url]  https://github.com/jiejieTop
  * [url=home.php?mod=space&uid=212281]@date[/url]    2018-xx-xx
  * [url=home.php?mod=space&uid=895143]@version[/url] v1.0
  * [url=home.php?mod=space&uid=536309]@NOTE[/url]    NULL
  ***********************************************************/
void Button_Create(const char *name,
                  Button_t *btn,
                  uint8_t(*read_btn_level)(void),
                  uint8_t btn_trigger_level)
{
  if( btn == NULL)
  {
    printf("struct button is null!");
    //ASSERT(ASSERT_ERR);
  }
  
  memset(btn, 0, sizeof(struct button));  //清除结构体信息,建议用户在之前清除

  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;
  
  printf("button create success!");
  
  Add_Button(btn);          //创建的时候添加到单链表中
  
  Print_Btn_Info(btn);     //打印信息

}

/************************************************************
  * @brief   按键触发事件与回调函数映射链接起来
        * @param   btn : 按键结构体
        * @param   btn_event : 按键触发事件
  * @param   btn_callback : 按键触发之后的回调处理函数。需要用户实现
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  ***********************************************************/
void Button_Attach(Button_t *btn,Button_Event btn_event,Button_CallBack btn_callback)
{
        uint8_t i;
  if( btn == NULL)
  {
    printf("struct button is null!");
    //ASSERT(ASSERT_ERR);       //断言
  }
  
  if(BUTTON_ALL_RIGGER == btn_event)
  {
    for(i = 0 ; i < number_of_event-1 ; i++)
      btn->CallBack_Function[i] = btn_callback; //按键事件触发的回调函数,用于处理按键事件
  }
  else
  {
    btn->CallBack_Function[btn_event] = btn_callback; //按键事件触发的回调函数,用于处理按键事件
  }
}

/************************************************************
  * @brief   删除一个已经创建的按键
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    NULL
  ***********************************************************/
void Button_Delete(Button_t *btn)
{
  struct button** curr;
  for(curr = &Head_Button; *curr;)
  {
    struct button* entry = *curr;
    if (entry == btn)
    {
      *curr = entry->Next;
    }
    else
    {
      curr = &entry->Next;
    }
  }
}

/************************************************************
  * @brief   获取按键触发的事件
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  ***********************************************************/
void Get_Button_EventInfo(Button_t *btn)
{
        uint8_t i;
  //按键事件触发的回调函数,用于处理按键事件
  for(i = 0 ; i < number_of_event-1 ; i++)
  {
    if(btn->CallBack_Function[i] != 0)
    {
      printf("Button_Event:%d",i);
    }      
  }
}

uint8_t Get_Button_Event(Button_t *btn)
{
  return (uint8_t)(btn->Button_Trigger_Event);
}

/************************************************************
  * @brief   获取按键触发的事件
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  ***********************************************************/
uint8_t Get_Button_State(Button_t *btn)
{
  return (uint8_t)(btn->Button_State);
}

/************************************************************
  * @brief   按键周期处理函数
  * @param   btn:处理的按键
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    必须以一定周期调用此函数,建议周期为20~50ms
  ***********************************************************/
void Button_Cycle_Process(Button_t *btn)
{
  uint8_t current_level = (uint8_t)btn->Read_Button_Level();//获取当前按键电平
  
  if((current_level != btn->Button_Last_Level)&&(++(btn->Debounce_Time) >= BUTTON_DEBOUNCE_TIME)) //按键电平发生变化,消抖
  {
      btn->Button_Last_Level = current_level; //更新当前按键电平
      btn->Debounce_Time = 0;                 //确定了是按下
      
      //如果按键是没被按下的,改变按键状态为按下(首次按下/双击按下)
      if((btn->Button_State == NONE_TRIGGER)||(btn->Button_State == BUTTON_DOUBLE))
      {
        btn->Button_State = BUTTON_DOWM;
      }
      //释放按键
      else if(btn->Button_State == BUTTON_DOWM)
      {
        btn->Button_State = BUTTON_UP;
        TRIGGER_CB(BUTTON_UP);    // 触发释放
//        printf("释放了按键");
      }
  }
  
  switch(btn->Button_State)
  {
    case BUTTON_DOWM :            // 按下状态
    {
      if(btn->Button_Last_Level == btn->Button_Trigger_Level) //按键按下
      {
        #if CONTINUOS_TRIGGER     //支持连续触发

        if(++(btn->Button_Cycle) >= BUTTON_CONTINUOS_CYCLE)
        {
          btn->Button_Cycle = 0;
          btn->Button_Trigger_Event = BUTTON_CONTINUOS;
          TRIGGER_CB(BUTTON_CONTINUOS);    //连按
          printf("连按");
        }
        
        #else
        
        btn->Button_Trigger_Event = BUTTON_DOWM;
      
        if(++(btn->Long_Time) >= BUTTON_LONG_TIME)  //释放按键前更新触发事件为长按
        {
          #if LONG_FREE_TRIGGER
         
          btn->Button_Trigger_Event = BUTTON_LONG;
         
          #else
         
          if(++(btn->Button_Cycle) >= BUTTON_LONG_CYCLE)    //连续触发长按的周期
          {
            btn->Button_Cycle = 0;
            btn->Button_Trigger_Event = BUTTON_LONG;
            TRIGGER_CB(BUTTON_LONG);    //长按
          }
          #endif
         
          if(btn->Long_Time == 0xFF)  //更新时间溢出
          {
            btn->Long_Time = BUTTON_LONG_TIME;
          }
//          printf("长按");
        }
         
        #endif
      }

      break;
    }
   
    case BUTTON_UP :        // 弹起状态
    {
      if(btn->Button_Trigger_Event == BUTTON_DOWM)  //触发单击
      {
        if((btn->Timer_Count <= BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State == BUTTON_DOUBLE)) // 双击
        {
          btn->Button_Trigger_Event = BUTTON_DOUBLE;
          TRIGGER_CB(BUTTON_DOUBLE);   
//          printf("双击");
          btn->Button_State = NONE_TRIGGER;
          btn->Button_Last_State = NONE_TRIGGER;
        }
        else
        {
            btn->Timer_Count=0;
            btn->Long_Time = 0;   //检测长按失败,清0
         
          #if (SINGLE_AND_DOUBLE_TRIGGER == 0)
            TRIGGER_CB(BUTTON_DOWM);    //单击
          #endif
            btn->Button_State = BUTTON_DOUBLE;
            btn->Button_Last_State = BUTTON_DOUBLE;
         
        }
      }
      
      else if(btn->Button_Trigger_Event == BUTTON_LONG)
      {
        #if LONG_FREE_TRIGGER
          TRIGGER_CB(BUTTON_LONG);    //长按
        #else
          TRIGGER_CB(BUTTON_LONG_FREE);    //长按释放
        #endif
        btn->Long_Time = 0;
        btn->Button_State = NONE_TRIGGER;
        btn->Button_Last_State = BUTTON_LONG;
      }
      
      #if CONTINUOS_TRIGGER
        else if(btn->Button_Trigger_Event == BUTTON_CONTINUOS)  //连按
        {
          btn->Long_Time = 0;
          TRIGGER_CB(BUTTON_CONTINUOS_FREE);    //连发释放
          btn->Button_State = NONE_TRIGGER;
          btn->Button_Last_State = BUTTON_CONTINUOS;
        }
      #endif
      
      break;
    }
   
    case BUTTON_DOUBLE :
    {
      btn->Timer_Count++;     //时间记录
      if(btn->Timer_Count>=BUTTON_DOUBLE_TIME)
      {
        btn->Button_State = NONE_TRIGGER;
        btn->Button_Last_State = NONE_TRIGGER;
      }
      #if SINGLE_AND_DOUBLE_TRIGGER
      
        if((btn->Timer_Count>=BUTTON_DOUBLE_TIME)&&(btn->Button_Last_State != BUTTON_DOWM))
        {
          btn->Timer_Count=0;
          TRIGGER_CB(BUTTON_DOWM);    //单击
          btn->Button_State = NONE_TRIGGER;
          btn->Button_Last_State = BUTTON_DOWM;
        }
        
      #endif

      break;
    }

    default :
      break;
  }
  
}

/************************************************************
  * @brief   遍历的方式扫描按键,不会丢失每个按键
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    此函数要周期调用,建议20-50ms调用一次
  ***********************************************************/
void Button_Process(void)
{
  struct button* pass_btn;
  for(pass_btn = Head_Button; pass_btn != NULL; pass_btn = pass_btn->Next)
  {
      Button_Cycle_Process(pass_btn);
  }
}

/************************************************************
  * @brief   遍历按键
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    NULL
  ***********************************************************/
void Search_Button(void)
{
  struct button* pass_btn;
  for(pass_btn = Head_Button; pass_btn != NULL; pass_btn = pass_btn->Next)
  {
    printf("button node have %s",pass_btn->Name);
  }
}

/************************************************************
  * @brief   处理所有按键回调函数
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    暂不实现
  ***********************************************************/
void Button_Process_CallBack(void *btn)
{
  uint8_t btn_event = Get_Button_Event(btn);

  switch(btn_event)
  {
    case BUTTON_DOWM:
    {
      printf("添加你的按下触发的处理逻辑");
      break;
    }
   
    case BUTTON_UP:
    {
      printf("添加你的释放触发的处理逻辑");
      break;
    }
   
    case BUTTON_DOUBLE:
    {
      printf("添加你的双击触发的处理逻辑");
      break;
    }
   
    case BUTTON_LONG:
    {
      printf("添加你的长按触发的处理逻辑");
      break;
    }
   
    case BUTTON_LONG_FREE:
    {
      printf("添加你的长按释放触发的处理逻辑");
      break;
    }
   
    case BUTTON_CONTINUOS:
    {
      printf("添加你的连续触发的处理逻辑");
      break;
    }
   
    case BUTTON_CONTINUOS_FREE:
    {
      printf("添加你的连续触发释放的处理逻辑");
      break;
    }
      
  }
}


/**************************** 以下是内部调用函数 ********************/

/************************************************************
  * @brief   拷贝指定长度字符串
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    NULL
  ***********************************************************/
static char *StrnCopy(char *dst, const char *src, uint32_t n)
{
  if (n != 0)
  {
    char *d = dst;
    const char *s = src;
    do
    {
        if ((*d++ = *s++) == 0)
        {
            while (--n != 0)
                *d++ = 0;
            break;
        }
    } while (--n != 0);
  }
  return (dst);
}

/************************************************************
  * @brief   打印按键相关信息
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    NULL
  ***********************************************************/
static void Print_Btn_Info(Button_t* btn)
{
  
  printf("button struct information:\n\
              btn->Name:%s \n\
              btn->Button_State:%d \n\
              btn->Button_Trigger_Event:%d \n\
              btn->Button_Trigger_Level:%d \n\
              btn->Button_Last_Level:%d \n\
              ",
              btn->Name,
              btn->Button_State,
              btn->Button_Trigger_Event,
              btn->Button_Trigger_Level,
              btn->Button_Last_Level);
  Search_Button();
}
/************************************************************
  * @brief   使用单链表将按键连接起来
        * @param   NULL
  * @return  NULL
  * @author  jiejie
  * @github  https://github.com/jiejieTop
  * @date    2018-xx-xx
  * @version v1.0
  * @note    NULL
  ***********************************************************/
static void Add_Button(Button_t* btn)
{
  btn->Next = Head_Button;
  Head_Button = btn;
}

/* 获取按键电平 */
uint8_t Read_KEY1_Level(void)
{
        return at32_button_state();
}



button.h完整代码:
#ifndef BUTTON_H
#define BUTTON_H

#include "at32f423_conf.h"

#define NULL          0
#define BTN_NAME_MAX  32     //名字最大为32字节

/* 按键消抖时间40ms, 建议调用周期为20ms
只有连续检测到40ms状态不变才认为有效,包括弹起和按下两种事件
*/

#define CONTINUOS_TRIGGER             0  //是否支持连续触发,连发的话就不要检测单双击与长按了        

/* 是否支持单击&双击同时存在触发,如果选择开启宏定义的话,单双击都回调,只不过单击会延迟响应,
   因为必须判断单击之后是否触发了双击否则,延迟时间是双击间隔时间 BUTTON_DOUBLE_TIME。
   而如果不开启这个宏定义,建议工程中只存在单击/双击中的一个,否则,在双击响应的时候会触发一次单击,
   因为双击必须是有一次按下并且释放之后才产生的 */
#define SINGLE_AND_DOUBLE_TRIGGER     1

/* 是否支持长按释放才触发,如果打开这个宏定义,那么长按释放之后才触发单次长按,
   否则在长按指定时间就一直触发长按,触发周期由 BUTTON_LONG_CYCLE 决定 */
#define LONG_FREE_TRIGGER             0

#define BUTTON_DEBOUNCE_TIME           2   //消抖时间      (n-1)*调用周期
#define BUTTON_CONTINUOS_CYCLE  1          //连按触发周期时间  (n-1)*调用周期  
#define BUTTON_LONG_CYCLE       1          //长按触发周期时间  (n-1)*调用周期
#define BUTTON_DOUBLE_TIME      15         //双击间隔时间  (n-1)*调用周期  建议在200-600ms
#define BUTTON_LONG_TIME               50                /* 持续n秒((n-1)*调用周期 ms),认为长按事件 */

#define TRIGGER_CB(event)   \
        if(btn->CallBack_Function[event]) \
          btn->CallBack_Function[event]((Button_t*)btn)

typedef void (*Button_CallBack)(void*);   /* 按键触发回调函数,需要用户实现 */



typedef enum {
  BUTTON_DOWM = 0,
  BUTTON_UP,
  BUTTON_DOUBLE,
  BUTTON_LONG,
  BUTTON_LONG_FREE,
  BUTTON_CONTINUOS,
  BUTTON_CONTINUOS_FREE,
  BUTTON_ALL_RIGGER,
  number_of_event, /* 触发回调的事件 */
  NONE_TRIGGER
}Button_Event;

/*
        每个按键对应1个全局的结构体变量。
        其成员变量是实现滤波和多种按键状态所必须的
*/
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;                  /* 按键按下持续时间 */
  
  struct button *Next;
  
}Button_t;




/* 供外部调用的函数声明 */

void Button_Create(const char *name,
                  Button_t *btn,
                  uint8_t(*read_btn_level)(void),
                  uint8_t btn_trigger_level);
                  
void Button_Attach(Button_t *btn,Button_Event btn_event,Button_CallBack btn_callback);   
                  
void Button_Cycle_Process(Button_t *btn);   
                  
void Button_Process(void);
                  
void Button_Delete(Button_t *btn);   
  
void Search_Button(void);     
                  
void Get_Button_EventInfo(Button_t *btn);
uint8_t Get_Button_Event(Button_t *btn);
uint8_t Get_Button_State(Button_t *btn);
void Button_Process_CallBack(void *btn);
uint8_t Read_KEY1_Level(void);                  
#endif
main.c完整代码:
/**
  **************************************************************************
  * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  * @brief    main program
  **************************************************************************
  *                       Copyright notice & Disclaimer
  *
  * The software Board Support Package (BSP) that is made available to
  * download from Artery official website is the copyrighted work of Artery.
  * Artery authorizes customers to use, copy, and distribute the BSP
  * software and its related documentation for the purpose of design and
  * development in conjunction with Artery microcontrollers. Use of the
  * software is governed by this copyright notice and the following disclaimer.
  *
  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
  *
  **************************************************************************
  */

#include "at32f423_board.h"
#include "at32f423_clock.h"
#include "button.h"

/** @addtogroup AT32F423_periph_examples
  * @{
  */

/** @addtogroup 423_USART_printf USART_printf
  * @{
  */

__IO uint32_t time_cnt = 0;
Button_t Button1;


void Btn1_Dowm_CallBack(void *btn)
{
  printf("Button1 单击!\r\n");
}

void Btn1_Double_CallBack(void *btn)
{
  printf("Button1 双击!\r\n");
}

void Btn1_Long_CallBack(void *btn)
{
  printf("Button1 长按!\r\n");
}
void Btn1_ContinuosFree_CallBack(void *btn)
{
  printf("Button1 连按释放!\r\n");
}

/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
  system_clock_config();
  at32_board_init();
  uart_print_init(115200);
         Button_Create("Button1",
              &Button1,
              Read_KEY1_Level,
              1);
  Button_Attach(&Button1,BUTTON_DOWM,Btn1_Dowm_CallBack);                       //单击
  Button_Attach(&Button1,BUTTON_DOUBLE,Btn1_Double_CallBack);                   //双击  
  Button_Attach(&Button1,BUTTON_LONG,Btn1_Long_CallBack);                       //长按BUTTON_LONG_FREE,
        Button_Attach(&Button1,BUTTON_LONG_FREE,Btn1_ContinuosFree_CallBack);
  /* output a message on hyperterminal using printf function */
  printf("usart printf example: retarget the c library printf function to the usart\r\n");
        Get_Button_Event(&Button1);
  while(1)
  {
                Button_Process();     //需要周期调用按键处理函数
//    printf("usart printf counter: %u\r\n",time_cnt++);
//    delay_sec(1);
                delay_ms(20);
  }
}

/**
  * @}
  */

/**
  * @}
  */

【试用心得】
1、此次是我第一次使用按键的驱动代码,实现了很多单按键的功能,这在我们以后面的编程工作中会有很大的帮助。
2、能够顺利的移植,也得益于雅特力的官方示例给了开发板的常规驱动,比如Uart\printf重定向、按键驱动、LED灯驱动都写好了,我们只要调用board.c中的就可以了。
3、在github上有很多优秀的开源软件,能向大佬们学习,也是提高自身技术水平的重要方式之一,这里要感觉这些无私奉献的大佬。

使用特权

评论回复
沙发
184592967| | 2023-10-25 15:32 | 只看该作者
谢谢分享,搞来试试

使用特权

评论回复
板凳
Aeddg| | 2023-10-25 16:32 | 只看该作者
谢谢分享!

使用特权

评论回复
地板
lulugl|  楼主 | 2023-10-25 18:23 | 只看该作者
184592967 发表于 2023-10-25 15:32
谢谢分享,搞来试试

挺好用的一个开源库,你值得拥有!

使用特权

评论回复
5
trucyw| | 2023-10-26 08:23 | 只看该作者
谢谢分享,搞来试试

使用特权

评论回复
6
jobszheng| | 2023-10-26 09:26 | 只看该作者
这个按键代码优秀在哪里了啊?

使用特权

评论回复
7
lulugl|  楼主 | 2023-10-26 10:40 | 只看该作者
jobszheng 发表于 2023-10-26 09:26
这个按键代码优秀在哪里了啊?

不只是我说他优秀,其他的人也认为他优秀,而且这个驱动,移植方便,只要实现一下IO的驱动,电平状态的获取后就可以实现单击、双击、连击等等的。这样的不优秀,还有什么可以说他优秀?

使用特权

评论回复
8
ssy123321| | 2024-12-13 17:42 | 只看该作者
mark

使用特权

评论回复
9
呐咯密密| | 2024-12-13 20:06 | 只看该作者
这些开源的按键驱动真的好用

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

156

主题

744

帖子

10

粉丝