本帖最后由 netlhx 于 2015-5-3 21:51 编辑
最近学习FREERTOS,研究了一下按键处理的方式,提出来供讨论。
该方法有如下特色:
1. 基于信号量方式,比查询方式效率更高
2. 可灵活调整按键时长,可实现常规按键、任意时长按键
3. 结合信号量还可实现组合按键。
下面是代码部分,比较简单,就不解释了
- osSemaphoreId key0PressedBinSemHandle;
- /* Create the semaphores(s) */
- /* definition and creation of key0PressedBinSem */
- osSemaphoreDef(key0PressedBinSem);
- key0PressedBinSemHandle = osSemaphoreCreate(osSemaphore(key0PressedBinSem), 1);
- /* StartCheckKeyPressedTask function */
- void StartCheckKeyPressedTask(void const * argument)
- {
- /* USER CODE BEGIN StartCheckKeyPressedTask */
- //static uint8_t key0Pressed = 0;
- static uint16_t count = 0;
-
- /* Infinite loop */
- for(;;)
- {
- if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_4) == GPIO_PIN_RESET)
- {
- //key0Pressed = 1;
- count ++;
-
- }
- else
- {
- //key0Pressed = 0;
- count = 0;
- }
- if(count > 40)
- {
- count = 0;
- osSemaphoreRelease(key0PressedBinSemHandle);
- }
- osDelay(50);
- }
- /* USER CODE END StartCheckKeyPressedTask */
- }
- /* StartKey0PressedTask function */
- void StartKey0PressedTask(void const * argument)
- {
- /* USER CODE BEGIN StartKey0PressedTask */
- osSemaphoreWait(key0PressedBinSemHandle, 0);
- /* Infinite loop */
- for(;;)
- {
- osSemaphoreWait(key0PressedBinSemHandle, osWaitForever);
- HAL_GPIO_TogglePin(GPIOF, GPIO_PIN_9);
- osDelay(1);
- }
- /* USER CODE END StartKey0PressedTask */
- }
复制代码
注意调整count值的比较量,就可以实现不同按键时长的选择,代码中实现的是2秒的延时。 |
是状态机+定时器的做法。
不建议用任务延时代替定时器,因为任务延时会额外占用一个任务描述符。但是在操作系统环境下,用一个专门的任务监控状态机并且分发按键消息是非常有必要的。
方法很多,基于队列也很好。不过基于队列同时相应两个按键连击好像处理就麻烦点了。
下面是我开一个按键扫描任务里面发送标志到标志组,其他任务检查标志组就可以。
这还有一个方法就是,用OS的软件定时器,对于还有误触发情况我们可以用STM32硬件按键滤波方法
---》STM32的定时器输入通道都有一个滤波单元,分别位于每个输入通路上(下图中的黄色框)和外部触发输入通路上(下图中的兰色框),它们的作用是滤除输入信号上的高频干扰。
http://www.eeworld.com.cn/mndz/2013/0922/article_19360.html
这个是香水城分享的
用队列是否更好呢?
快速按键用队列应该会好一些
实际上我们需要的按键需要快速识别,但又可以有选择地响应连击事件或是单纯的按下事件。
可有良策?
不好意思,这半年比较忙,好久没有逛论坛了。
我写过一个专门做按键识别的组件,可以识别按键的各种动作的,包括短按按下、短按弹起、长按、长按弹起、连击、连击弹起等动作。可以提供的信息是,设计的核心思想是状态机。在设计完成后发现比最开始想得稍微复杂一点。