Chinaunix首页 | 论坛 | 博客
  • 博客访问: 804750
  • 博文数量: 281
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2770
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-02 19:45
个人简介

邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-12-11 11:17:44

在上一章节【嵌入式设计编程:事件及事件队列_3(对按键进行读取)】中,实现了利用事件队列的方式来实现按键状态的读取。
对于按键的抖动,利用10ms中断连续读取消抖,这里也可以利用前面讲的软件定时器来实现同样的功能,非常的方便。

想想,软件定时器如何实现?
(1)设定扫描时间,是否为周期性事件: #define KEY_SCAN_PERIOD_MS     10
(2)静态定义一个软件定时器,并初始化: static softtimer_t  keyScanTask_timer = TIMER_INIT;
(3)定义一个时间到的真正的处理函数: void keyScan(void *data)
(4)启动软件定时器: Timer_StartPeriodic(&keyScanTask_timer,  KEY_SCAN_PERIOD_MS,  keyScan);





列代码

点击(此处)折叠或打开

  1. #include "App_LongShortKey.h"
  2. #include <stdio.h>
  3. #include "Timer.h"


  4. #define KEY_EVENT_QUEUE_DEBUG

  5. #ifdef KEY_EVENT_QUEUE_DEBUG
  6. #include "eventQueue.h"

  7. static void keyScanEvent(void *data);
  8. static event_t keyPressEvent = EVENT_INIT(keyScanEvent);
  9. #endif


  10. #define KEY0_INPUT KEY1

  11. static char key0_Status = 0;
  12. static unsigned int key0_TimeS, key0_TimeL;


  13. /**
  14.  * \brief: 与FIFO相关的变量定义
  15.  */
  16. //#define KEYBUFFSIZE 4
  17. char keyBuff[KEYBUFFSIZE];
  18. char key_indexW = 0;
  19. char key_indexR = 0;
  20. char key_count = 0;

  21. #define ENA_INT() __enable_irq()
  22. #define DIS_INT() __disable_irq()
  23. //#define ENA_INT()
  24. //#define DIS_INT()

  25. /**
  26.  * \brief: 与FIFO相关操作的函数的定义
  27.  */
  28.  
  29. void key_paraInit(void)
  30. {
  31.     char i = 0;
  32.     
  33.     for(i =0; i< KEYBUFFSIZE; i++)
  34.         keyBuff[i] = 0;
  35.     
  36.     key_indexW = 0;
  37.     key_indexR = 0;
  38.     key_count = 0;
  39. }
  40.  
  41. void key_inBuff(char keyValue)
  42. {
  43.     if(key_count >= KEYBUFFSIZE)
  44.         return;
  45.     
  46.     DIS_INT();
  47.     
  48.     key_count ++;
  49.     
  50.     keyBuff[key_indexW] = keyValue;
  51.     
  52.     if(++ key_indexW == KEYBUFFSIZE)
  53.         key_indexW = 0;
  54.     
  55.     ENA_INT();
  56. }

  57. char key_readBuff(void)
  58. {
  59.     char key = 0;

  60.     if(key_count == 0)
  61.         return 0;
  62.     
  63.     DIS_INT();
  64.     
  65.     key_count --;
  66.     
  67.     key = keyBuff[key_indexR];
  68.     if( ++key_indexR == KEYBUFFSIZE)
  69.         key_indexR = 0;
  70.     
  71.     ENA_INT();
  72.     return key;
  73. }

  74. /**
  75.  * \brief:
  76.  */
  77. uint8_t keyCodeBuff[1];

  78. void keyScan(void *data)
  79. {

  80.     
  81.     if(key0_Status == KEY_SHORT_PRESS)
  82.         key0_TimeS ++;
  83.     else
  84.         key0_TimeS = 0;
  85.     
  86.     if(key0_Status == KEY_LONG_PRESS)
  87.         key0_TimeL ++;
  88.     else
  89.         key0_TimeL = 0;
  90.     
  91.     switch(key0_Status)
  92.     {
  93.         case KEY_NO_PRESS:
  94.             if(KEY0_INPUT == 0)
  95.                 key0_Status = KEY_SHORT_PRESS;
  96.         break;
  97.             
  98.         case KEY_SHORT_PRESS:
  99.             
  100.             if(KEY0_INPUT != 0) // 表示按键松开了
  101.             {
  102.                 // 保存按键
  103.                 //key_inBuff(KEY_SHORT_CODE + KEY0_CODE);
  104.                 
  105. #ifdef KEY_EVENT_QUEUE_DEBUG

  106.                 keyCodeBuff[0] = KEY_SHORT_CODE + KEY0_CODE;
  107.                 EventQueue_EnqueueWithData(&keyPressEvent, keyCodeBuff);
  108. #endif
  109.                 
  110.                 // 返回到按键未按下模式
  111.                 key0_Status = KEY_NO_PRESS;
  112.             }
  113.             else
  114.             {
  115.                 if(key0_TimeS >= 2000/10) // 2s detect
  116.                 {
  117.                     //key_inBuff(KEY_FIRST_LONG_CODE + KEY0_CODE);
  118. #ifdef KEY_EVENT_QUEUE_DEBUG
  119.                     
  120.                    keyCodeBuff[0] = KEY_FIRST_LONG_CODE + KEY0_CODE;
  121.                    EventQueue_EnqueueWithData(&keyPressEvent, keyCodeBuff);
  122. #endif

  123.                     
  124.                     key0_Status = KEY_LONG_PRESS;
  125.                 }
  126.             }
  127.         break;
  128.             
  129.         case KEY_LONG_PRESS:
  130.             
  131.             if(KEY0_INPUT != 0) // 表示按键松开了
  132.             {
  133.                 // 返回到按键未按下模式
  134.                 key0_Status = KEY_NO_PRESS;
  135.             }
  136.             else
  137.             {
  138.                 if(key0_TimeL >= 100/10) // 250ms
  139.                 {
  140.                     //key_inBuff(KEY_AFTER_LONG_CODE + KEY0_CODE);
  141. #ifdef KEY_EVENT_QUEUE_DEBUG
  142.                                         
  143.                     keyCodeBuff[0] = KEY_AFTER_LONG_CODE + KEY0_CODE;
  144.                     EventQueue_EnqueueWithData(&keyPressEvent, keyCodeBuff);
  145. #endif

  146.                     key0_TimeL = 0;
  147.                 }
  148.             }
  149.         break;
  150.     }
  151. }


  152. void keyScanEvent(void *data)
  153. {
  154.     uint8_t *keyCode = (uint8_t *)data;
  155.     uint8_t key = *keyCode;
  156.     
  157.     switch(key){
  158.         
  159.         case (KEY0_CODE + KEY_SHORT_CODE):
  160.             printf("key1 short press \r\n");
  161.         break;
  162.         
  163.         case (KEY0_CODE + KEY_FIRST_LONG_CODE):
  164.             printf("key1 long press \r\n");
  165.         break;
  166.         
  167.         case (KEY0_CODE + KEY_AFTER_LONG_CODE):
  168.             printf("key1 after long press \r\n");
  169.         break;
  170.         
  171.         default:
  172.             break;
  173.         
  174.     }
  175. }


  176. // 软件定时器相关的设置
  177. #define KEY_SCAN_PERIOD_MS 10
  178. static softtimer_t keyScanTask_timer = TIMER_INIT;


  179. void keyScanTask_init(void)
  180. {
  181.     /* 添加循环打印任务到 Software_timer 链表中 */
  182.     // timer时间到的时候,通知事件发生。
  183.     Timer_StartPeriodic(&keyScanTask_timer, KEY_SCAN_PERIOD_MS, keyScan);
  184.     printf("software time initialize \n");
  185. }

主函数里面

点击(此处)折叠或打开

  1. int main(void)
  2. {    
  3.     //static int cnt = 0;
  4.     volatile static event_t* event;
  5.     board_init();
  6.     keyScanTask_init(); // 启动软件定时器
  7.     
  8.     while(1)
  9.     {
  10.         event = EventQueue_GetPendingEvent();
  11.         if (event)
  12.         {
  13.             event->execute(event->data);
  14.         }
  15.         
  16. // if(flag) // 10ms中断内,查询按键状态,用来消除按键抖动。
  17. // {
  18. // flag =0;
  19. // keyScan();
  20. // }
  21.     }
  22.  }

同样实现检测效果。是不是很方便啊


阅读(1285) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~