STM32使用HAL库实现按键的单击、双击、长按

STM32使用HAL库实现按键的单击、双击、长按

目录

  • STM32使用HAL库实现按键的单击、双击、长按
    • 前言
    • 具体思路
    • 工程配置
    • 代码实现
    • 实验效果

前言

编程开发环境:STM32CubeIDE

具体思路 ---- * 初始化一个全局标记 * 按键中断事件发生后置位标记 * while死循环中一直检测这个标记,如果被置位那么进行消抖,然后再次检测连接KEYIO是否处于按下状态,如是则认为本次按键有效 * 第一次按键事件有效后,启动定时器定时300ms,在此定时期间内如果有二次按下那么就是双击,如果没有按下,等到300ms定时时间到后读取IO电平,如果处于松开状态那么本次就是单击事件,如果还是按下状态那么就再次启动700定时器,700ms过后再次读取IO电平是否处于按下状态,如是那么就是长按。 * * * 工程配置 ---- 我是使用STM32CUBEMX配置生成的工程,配置按键: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200919164941415.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxMTUzNDcxNTAz,size_16,color_FFFFFF,t_70#pic_center) STM32的定时器有向上、向下计数模式,向上计数就是从0计数到N然后触发中断,向下计数模式就是倒计时到0,由于我们需要二次启动定时器来检测长按,所以再次配置为向下计数模式,分频为7199,计数3000就是定时300ms: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200919165238384.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxMTUzNDcxNTAz,size_16,color_FFFFFF,t_70#pic_center) 中断配置: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200919165306462.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxMTUzNDcxNTAz,size_16,color_FFFFFF,t_70#pic_center) 代码实现 ---- /* * key_state位说明: * * bit[15]:按键事件完成标志位 * bit[14]:按键中断触发标志位 * bit[13]:长按事件触发需要启动第二次定时器标志位 * bit[12~0]: 按键计数,=1:单击 =2:双击 =3:长按 */ __IO uint16_t key_state = 0; int __io_putchar(int ch) { HAL_UART_Transmit(&huart1, (uint8_t*) &ch, 1, 100); return ch; } void TIM4_Stop(void) { HAL_TIM_Base_Stop_IT(&htim4); } void TIM4_Start(uint16_t timeout) { __HAL_TIM_SET_COUNTER(&htim4, timeout); HAL_TIM_Base_Start_IT(&htim4); } void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == htim4.Instance) { TIM4_Stop(); if(key_state & 0X2000) // 如果是700ms的超时 { // 再次检测按键如果是按下状态,那么就是长按事件,否则事件无效 if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET) { key_state = 0X8003; }else { key_state = 0X8000; } } else // 如果是300ms的超时 { // 300ms时间到再次检测按键状态如果仍处于按下状态,那么就启动700ms的超时, // 700ms时间到后再次检测按键如果是按下状态,那么就是长按事件了。 if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET) // 按键处于按下状态 { key_state |= 0X2000; // 标记启动了700ms的超时定时 TIM4_Start(7000); // 启动700ms超时 } else // 按键处于松开状态 { if((key_state & 0X1FFF) == 1) // 按键按下计数=1,是单击事件 { key_state = 0X8001; }else if((key_state & 0X1FFF) >= 2) // 按键按下计数>=2,是双击事件 { key_state = 0X8002; }else // 按键按下计数为其他值,本次按键事件无效 { key_state = 0; } } } } } void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { switch(GPIO_Pin) { case KEY_Pin: if((key_state & 0X8000) == 0) { key_state |= 0X4000; // 标记按键中断触发,在while死循环中进行消抖和的启动定时器 } break; default:break; } } int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_TIM4_Init(); __HAL_TIM_CLEAR_IT(&htim4, TIM_IT_UPDATE); // STM32的定时器初始化完毕之后如果不清理中断标记为会有直接进入中断的问题 while (1) { if(key_state & 0X4000) // 按键中断触发 { key_state &= ~0x4000; // 清除事件 HAL_Delay(60); // 消抖延时 // 消抖完毕之后再次检测按键是否为按下状态,如是则本次按键有效,否则视为无效并清除标识。 if(HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin) == GPIO_PIN_RESET) { if((key_state & 0X1FFF) == 0) // 首次按下时启动300ms超时定时器 { TIM4_Start(3000); } key_state++; // 按键按下计数增加 } } if(key_state & 0X8000) // 按键事件发成了 { switch(key_state) { case 0X8001: printf("single\r\n"); break; case 0X8002: printf("double\r\n"); break; case 0X8003: printf("hold\r\n"); break; default:break; } key_state = 0; // 清除事件 } } } * * * 实验效果 ---- 按键单击、双击、长按实验效果如下: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200919165532374.gif#pic_center)
点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

UIWebView长按保存图片和识别图片二维码的实现方案(使用缓存)

0x00需求:长按识别UIWebView中的二维码,如下图长按识别二维码0x01方案1:给UIWebView增加一个长按手势,激活长按手势时获取当前UIWebView的截图,分析是否包含二维码。核心代码:略优点:流程简单,可以快速实现。不足:无法实现保存UIWebView中图片,如果当前We

STM32使用HAL库DMA+空闲中断实现串口不定长数据接收

STM32使用HAL库DMA空闲中断实现串口不定长数据接收环境:STM32CubeIDESTM32F103RBWIN10HAL库V1.8首先配置串口:!在这里插入图片描述(https://img

stm32 库函数(按键控制led灯闪烁)最简单易懂的使用方法

STM32使用库函数(按键控制led不同的闪烁效果)下面是main.cinclude"stm32f10x.h"include"led.h"include"key.h"intmain(void){while(1){