前言
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("触发单击,健值:%drn",KeyObject.PutValue); } else if(KeyValue0 == KeyValue1) // 双击 { KeyObject.PutValue = KeyValue0; printf("触发双击,健值:%drn",KeyObject.PutValue); } else // 大概率是双击时前后不匹配,取最后一次单击 { KeyObject.PutValue = KeyValue1; printf("触发不匹配单击,健值:%drn",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进行了二次封装,因此在实际应用中可能存在一些细微的差异。如果各位在阅读或使用过程中发现任何错误或不足之处,敬请不吝指正
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net