分享一个很好用的按键组件

简介: 分享一个很好用的按键组件

在嵌入式系统或单片机程序开发过程中,经常会遇到各种按键的需求,比如按键短按、按键长按、按键双击,这些功能虽然不难,但想要完全写好这些功能并不简单。网上已经有大神实现了这样的组件,该组件的特性如下:

  • 使用时系统不阻塞
  • 低耦合性
  • 同一个按键可实现单击、双击、长按
  • 可根据按键线序更改,比如高电平触发或低电平触发

按键检测组件函数接口如下:

一、初始化按键

/**
  * @name   Init_Key_Struct
  * @brief  初始化按键
  * @param  Update_Key_CallBack:更新按键状态
  * @param  Debug_CallBack:打印按键调试信息
  * @retval 0:成功;
  *         1:Update_Key_CallBack == NULL;
  */
char Init_Key_Struct(void (*Update_Key_CallBack)(void), void (*Debug_CallBack)(unsigned char *debug_mess));
  • 参数Update_Key_CallBack用于更新按键状态,即按下或者释放,是一个函数指针,该值一定不能为NULL。
  • 参数Debug_CallBack用于打印按键组件的异常信息,也是一个函数指针,如果不需要时候可以将该参数写NULL。

二、注册按键

/**
  * @name   Reg_Key
  * @brief  添加注册按键(注:如果按键已经注册过,那么再次注册会覆盖之前注册过的相同的按键)
  * @param  key_s:按键状态
  * @param  count:按键计数
  * @param  Trig_Mode_E:按键触发模式
  * @param  Key_Mode_E:按键模式
  * @param  Key_Click_CallBack:按键触发回调
  * @retval 0:成功;
  *         1:Key_Click_CallBack == NULL;
  *         2:Key.Reg_Key_Num > Key_Num_Max;
  */
char Reg_Key(unsigned char *key_s, const unsigned short count,
             Trig_Mode_TypeDef Trig_Mode_E, Key_Mode_TypeDef  Key_Mode_E, void (*Key_Click_CallBack)(void));
  • 参数key_s为按键状态,即是按键按下或者释放,可以与"一"中的Update_Key_CallBack回调函数关联起来。
  • 参数count为按键计数,意思是当按键按下多少次后出发对应的回调,这个回调就是参数Key_Click_CallBack
  • 参数Trig_Mode_E,指的是按键的出发方式,该组件用一个枚举来进行描述:
/**
  * @brief 按键触发模式状态枚举
  */
typedef enum
{
  N_Trig = 0,                                         /*!< 0 空 */   
  L_Trig ,                                            /*!< 1 低电平触发 */     
  H_Trig,                                             /*!< 2 高电平触发 */
}Trig_Mode_TypeDef;
  • 参数Key_Mode_E为按键模式,有单击,双击,长按三种,该组件也是用一个枚举来进行描述:
/**
  * @brief 按键模式状态枚举
  */
typedef enum
{
  N_Click = 0,                                        /*!< 0 空 */ 
  S_Click ,                                           /*!< 1 单击 */      
  D_Click,                                            /*!< 2 双击 */
  L_Press,                                            /*!< 3 长按 */
}Key_Mode_TypeDef;
  • 参数Key_Click_CallBack,也就是相应模式下出发的回调函数了,这是一个函数指针。

三、按键检测

/**
  * @name   Key_Detect
  * @brief  按键检测
  * @param  无
  * @retval 0:成功;
  *         1:Key.Update_Key_CallBack == NULL;
  */
char Key_Detect(void);

该接口是用来检测按键状态的,使用该函数时,需要周期性的进行调用,当函数返回0时,表示函数一直在运行,如果返回1,则表示更新按键电平状态的回调函数Update_Key_CallBack为空。

四、打印组件版本信息

/**
  * @name   Get_Version_Mess
  * @brief  打印Key_Detect组件版本信息
  * @param  无
  * @retval 返Key_Detect组件版本信息
  */
char *Get_Version_Mess(void)

其中一、二、三是就是我们使用这个按键组件的核心函数,我们来看看这个组件的使用方法,以下是我使用野火霸道F103开发板实现的例程,代码只贴出一部分核心的:

五、部分例程实现与讲解

//按键单击时发出时的事件值
#define KEY_SIGNAL 0
//按键长按时发出时的事件值
#define KEY_LONG   1
//按键没有发出时的事件值
#define KEY_NULL   -1
/*按键状态==>按下or释放*/
uint8_t Key_Status = 0 ;
/*按键事件==>对应单击、双击、长按*/
int Key_Event = KEY_NULL;
/*按键发生单击时回调*/
void key_S_CallBack(void) 
{
  Key_Event = KEY_SIGNAL ;
}
/*按键发生长按时回调*/
void key_L_CallBack(void) 
{
  Key_Event = KEY_LONG ;
}
/*获取按键状态*/
void Get_Key_Status(void)
{
   Key_Status = HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
}
/*打印调试信息*/
void Print_Debug_mess(unsigned char *debug_Mess)
{
    printf("%s\n",debug_Mess);
}
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  uint8_t Register_Status = 1 ;
  int Count = 0 ;
  /* USER CODE END 1 */
  /* MCU Configuration--------------------------------------------------------*/
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
  /* USER CODE BEGIN Init */
  /* USER CODE END Init */
  /* Configure the system clock */
  SystemClock_Config();
  /* USER CODE BEGIN SysInit */
  /* USER CODE END SysInit */
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  printf("按键组件demo初始化\n");
  //HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
  /*显示绿灯*/
  HAL_GPIO_WritePin(GPIOB, LED_R_Pin, GPIO_PIN_RESET);
  /*初始化结构体*/
  Register_Status = Init_Key_Struct(Get_Key_Status, Print_Debug_mess);
  if(Register_Status)
  {
    printf("初始化按键失败\n");
    return -1 ;
  }
  /*注册事件发生回调*/
  Reg_Key(&Key_Status, 10,  H_Trig, S_Click, key_S_CallBack);//单击
  Reg_Key(&Key_Status, 200,  H_Trig, L_Press, key_L_CallBack);//长按
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  Key_Detect();
  if(KEY_SIGNAL == Key_Event)
  {
    HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB, LED_G_Pin, GPIO_PIN_RESET);
  }
  if(KEY_LONG == Key_Event)
  {
    HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB, LED_B_Pin, GPIO_PIN_RESET);
  }
  HAL_Delay(5);
  }
  /* USER CODE END 3 */
}

该例程的实现非常简单,即当没有发生任何按键的时候,显示红灯,当发生单击时,显示绿灯,当发生长按时,显示蓝灯。

640.jpg

640.jpg

640.jpg

六、例程及组件文档分享

链接:https://pan.baidu.com/s/1jV2dCE_wGGZSPBIUhMfUgQ

提取码:89zf

链接:https://pan.baidu.com/s/1Wg2jBfihFn-SKh0JmytIZA

提取码:o61v

往期精彩分享

让C语言的调试更加高大上

分享一个好用的C语言.ini文件的解析库

分享一个非常有用且简单C语言测试框架

分享一个自己量产项目上的集成测试软件MTTEST

目录
相关文章
vbs鼠标方法——模拟鼠标按键
'*********************************************************************** ' 代码开始 '*********************************************************************** Set mouse=New SetMouse mouse.
4896 0
|
6月前
|
人工智能 运维 监控
领先AI企业经验谈:探究AI分布式推理网络架构实践
当前,AI行业正处于快速发展的关键时期。继DeepSeek大放异彩之后,又一款备受瞩目的AI智能体产品Manus横空出世。Manus具备独立思考、规划和执行复杂任务的能力,其多智能体架构能够自主调用工具。在GAIA基准测试中,Manus的性能超越了OpenAI同层次的大模型,展现出卓越的技术实力。
|
8月前
|
开发者 ice
实时云渲染中的NAT转发服务支持个人电脑秒变云渲染服务器
实时云渲染技术广泛应用于XR领域,助力数千客户完成云端部署。平行云推出的转发服务解决了家庭网络动态IP问题,使个人电脑成为实时云渲染服务器,按实际使用分钟数计费,无用户访问不收费。通过配置LarkXR的代理转发Server和ICE Server,开发者可轻松实现互联网访问内网XR应用,极大提升了开发、测试和演示的便利性。
130 11
|
机器学习/深度学习 算法 Ubuntu
dlib
【6月更文挑战第13天】
202 4
|
10月前
|
安全 网络协议 算法
HTTPS为什么可以穿越NAT端口映射设备
HTTPS能穿越NAT端口映射设备的原因在于,NAT设备仅在IP和端口层面进行地址转换,不对应用层协议(如TLS)的内容进行解析或干预。因此,HTTPS的加密通信可在客户端与服务器间直接建立,NAT设备充当透明中介,确保数据包正确路由,而不涉及加密或认证过程。这样即使没有在NAT设备上配置证书,HTTPS连接也能顺利建立并保持安全。
248 6
|
10月前
|
负载均衡 安全 网络安全
|
10月前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
1104 2
|
10月前
|
域名解析 弹性计算 网络安全
CEN+私网NAT实现跨地域访问云服务需求-CEN企业版
本文介绍了如何通过企业版云企业网和私网NAT配置,实现ECS内网跨地域访问OSS资源的方法。该方法避免了跨地域配置云服务网段时可能出现的管控异常问题,适用于其他云服务如MQ等。
|
11月前
|
网络协议 安全 网络架构
NAT穿透技术、穿透原理和方法
【10月更文挑战第19天】 NAT穿透技术、穿透原理和方法
793 7
|
10月前
|
运维 负载均衡 安全