【FreeRTOS】按键单双击检测

前言

FreeRTOS是一个功能强大的实时操作系统,广泛应用于嵌入式系统开发中。在硬件资源有限的情况下,如何利用有限的按键实现更多的功能是一个重要问题。本文将介绍在FreeRTOS上实现按键单击和双击检测的方法,帮助开发者在有限的按键上实现更多的操作,提升用户体验。

文字思路

基本思路就是,检测200毫秒内,用户按下相邻的两次健值,来判断是否触发了双击,假如只检测到一次,那毫无疑问只是单击。

所需结构:

  • 定义健值结构
  • 创建定时器,及该定时器的回调事件。
  • 创建按键检测任务,创建一个存储健值的队列。

运行流程:

当按键检测任务,检测到用户第一次按下按键时,则记录健值,同时开启定时器。当定时器到时间后,会检查被相邻健值数组里的数据,在根据结构,把触发了的单双击提交到健值队列中。

逻辑框图:

该框图名称与下面代码函数名称不一定对的上,仅供大家参考理解,但是流程逻辑一致。

在这里插入图片描述

代码步骤

下述为纯FreeRTOS版本,还有像一些基本通用的函数就不粘贴出来了,比如像扫描按键函数之类的。

  • 定义健值结构,方便管理。

    struct{
    	uint8_t Status;				// 当前状态  0:静止模式  1:运行模式	2:结算模式
    	uint8_t PutValue;			// 输入健值
    	uint8_t RecordTwoValue[2];	// 记录相邻两次的健值
    	uint16_t DoubleClickWait;	// 双击等待间隔
    }KeyObject;
    
  • 声明健值队列

    QueueHandle_t KeyValueHandle;
    
  • 定时回调事件

    下述在提交健值时,还没有对单双击的健值进行区分,但是已经能辨别出触发源了,可执行修改即可。

    // 定时回调事件
    void vTimerCallback(void *argument)
    {
    	// 按键检测的定时回调事件
    	// 达到间隔,进行键位结算
    	uint8_t KeyValue0 = KeyObject.RecordTwoValue[0];
    	uint8_t KeyValue1 = KeyObject.RecordTwoValue[1];
    	// 健值判断
    	if(KeyValue0 == 0 || KeyValue1 == 0)	// 单击
    	{
    		KeyObject.PutValue = KeyValue0 + KeyValue1;
    		printf("触发单击,健值:%d\r\n",KeyObject.PutValue);
    	}
    	else if(KeyValue0 == KeyValue1)				// 双击
    	{
    		KeyObject.PutValue = KeyValue0;
    		printf("触发双击,健值:%d\r\n",KeyObject.PutValue);
    	}
    	else	// 大概率是双击时前后不匹配,取最后一次单击
    	{
    		KeyObject.PutValue = KeyValue1;
    		printf("触发不匹配单击,健值:%d\r\n",KeyObject.PutValue);
    	}
    	// 输入健值
    	osMessageQueuePut(KeyValueHandle, &(KeyObject.PutValue), 0, 0);
    	// 重置状态
    	KeyObject.Status = 0;
    	// 重置记录值
    	KeyObject.RecordTwoValue[0] = 0;
    	KeyObject.RecordTwoValue[1] = 0;
    }
    
    
    
  • 按键检测任务+软件定时器

    // 按键获取检测
    static void TaskKeyGet(void *arg)
    {
        char KeyValue = 0;
        // 初始化Key对象
    	KeyObject.Status = 0;
    	KeyObject.PutValue = 0;
    	KeyObject.RecordTwoValue[0] = 0;
    	KeyObject.RecordTwoValue[1] = 0;
    	KeyObject.DoubleClickWait = 200;
        KeyValueHandle = xQueueCreate(1, sizeof(char));   //动态方式创建队列
        // 创建一个周期性定时器,周期为500ms
        xMyTimer = xTimerCreate(
            "MyTimer",             		// 定时器的名字,用于调试信息
            KeyObject.DoubleClickWait,	// 定时器的周期
            pdFALSE,               		// 是否为周期性定时器(pdTRUE表示是,pdFALSE表示一次性定时器)
            (void*)0,              		// 回调函数的传递给定时器的参数(可以为NULL)
            vTimerCallback         		// 定时器超时后要调用的回调函数
        );
        for ( ; ; )
        {
            KeyValue = KEY_Scan();
    		if(KeyValue != 0)
    		{
                // 判断为是否为首次进入
    			if(KeyObject.Status == 0)
    			{
                    // 触发定时器
    				xTimerStart(xMyTimer,KeyObject.DoubleClickWait);
    				KeyObject.Status = 1;
    			}
    
    			// 记录两次健值以及健值的新旧交替
    			KeyObject.RecordTwoValue[0] = KeyObject.RecordTwoValue[1];
    			KeyObject.RecordTwoValue[1] = KeyValue;
    
    		}
            vTaskDelay(10);
        }
    }
    

上述内容详细阐述了按键检测的代码全部流程。这段代码是从STM32CubeMX生成的FreeRTOS+STM32工程中提取的,由于STM32CubeMX对FreeRTOS的API进行了二次封装,因此在实际应用中可能存在一些细微的差异。如果各位在阅读或使用过程中发现任何错误或不足之处,敬请不吝指正

  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值