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

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

文章分类
文章存档

2020年(1)

2018年(1)

2017年(56)

2016年(72)

2015年(151)

分类: 嵌入式

2015-10-23 11:40:25

目标:
1. 能实现非阻塞按键读取。
2. 能保存4次按键的值,如果按键太快了,超过4次按键,则后面的按键值会丢失。当然这个4次,可以自己定义。
3. 能够检测短按,长按状态,并保存键值。

贴代码了。

App_LongShortKey.c

点击(此处)折叠或打开

  1. #include "App_LongShortKey.h"


  2. #define KEY0_INPUT KEY0

  3. static char key0_Status = 0;
  4. static unsigned int key0_TimeS, key0_TimeL;


  5. /**
  6.  * \brief: 与FIFO相关的变量定义。
  7.  */
  8. //#define KEYBUFFSIZE 4
  9. char keyBuff[KEYBUFFSIZE];
  10. char key_indexW = 0;
  11. char key_indexR = 0;
  12. char key_count = 0;

  13. #define ENA_INT() __enable_irq()
  14. #define DIS_INT() __disable_irq()
  15. //#define ENA_INT()
  16. //#define DIS_INT()

  17. /**
  18.  * \brief: 初始化
  19.  */
  20.  
  21. void key_paraInit(void)
  22. {
  23.     char i = 0;
  24.     
  25.     for(i =0; i< KEYBUFFSIZE; i++)
  26.         keyBuff[i] = 0;
  27.     
  28.     key_indexW = 0;
  29.     key_indexR = 0;
  30.     key_count = 0;
  31. }
  32.  
  33. void key_inBuff(char keyValue)
  34. {
  35.     if(key_count >= KEYBUFFSIZE)
  36.         return;
  37.     
  38.     DIS_INT();
  39.     
  40.     key_count ++;
  41.     
  42.     keyBuff[key_indexW] = keyValue;
  43.     
  44.     if(++ key_indexW == KEYBUFFSIZE)
  45.         key_indexW = 0;
  46.     
  47.     ENA_INT();
  48. }

  49. char key_readBuff(void)
  50. {
  51.     char key = 0;

  52.     if(key_count == 0)
  53.         return 0;
  54.     
  55.     DIS_INT();
  56.     
  57.     key_count --;
  58.     
  59.     key = keyBuff[key_indexR];
  60.     if( ++key_indexR == KEYBUFFSIZE)
  61.         key_indexR = 0;
  62.     
  63.     ENA_INT();
  64.     return key;
  65. }

  66. /**
  67.  * \brief: 重要函数: 在10ms中断中调用的函数。检测按键的状态,并保存到buffer中。
  68.  */
  69. void keyScan(void)
  70. {
  71.     if(key0_Status == KEY_SHORT_PRESS)
  72.         key0_TimeS ++;
  73.     else
  74.         key0_TimeS = 0;
  75.     
  76.     if(key0_Status == KEY_LONG_PRESS)
  77.         key0_TimeL ++;
  78.     else
  79.         key0_TimeL = 0;
  80.     
  81.     switch(key0_Status)
  82.     {
  83.         case KEY_NO_PRESS:
  84.             if(KEY0_INPUT == 0)                   // 表示按键被按下
  85.                 key0_Status = KEY_SHORT_PRESS;
  86.         break;
  87.             
  88.         case KEY_SHORT_PRESS:
  89.             
  90.             if(KEY0_INPUT != 0)                    // 表示按键松开了。
  91.             {
  92.                 // 松开了,表示完成了一次短按键,保存键值
  93.                 key_inBuff(KEY_SHORT_CODE + KEY0_CODE);
  94.                 
  95.                 // 回到按键未按下的状态。
  96.                 key0_Status = KEY_NO_PRESS;
  97.             }
  98.             else
  99.             {
  100.                 if(key0_TimeS >= 2000/10)      // 如果按键还没有松开,一直按键到2s中,则触发长按键事件,将键值压入Buffer中。
  101.                 {
  102.                     key_inBuff(KEY_FIRST_LONG_CODE + KEY0_CODE);
  103.                     key0_Status = KEY_LONG_PRESS;                 // 进入长按键状态
  104.                 }
  105.             }
  106.         break;
  107.             
  108.         case KEY_LONG_PRESS:
  109.             
  110.             if(KEY0_INPUT != 0) // 按键释放
  111.             {
  112.                 // 回到按键未按下状态。
  113.                 key0_Status = KEY_NO_PRESS;
  114.             }
  115.             else   // 长按键触发了一次,仍然处于按下状态
  116.             {
  117.                 if(key0_TimeL >= 250/10) // 则没隔250ms,触发一次长按键事件,保存键值到buffer中。
  118.                 {
  119.                     key_inBuff(KEY_AFTER_LONG_CODE + KEY0_CODE);
  120.                     key0_TimeL = 0;
  121.                 }
  122.             }
  123.         break;
  124.     }
  125. }
App_LongShortKey.h

点击(此处)折叠或打开

  1. #ifndef _APP_LONGSHORT_KEY_H_
  2. #define _APP_LONGSHORT_KEY_H_

  3. #include "key.h"


  4. #define KEY_NO_PRESS 0
  5. #define KEY_SHORT_PRESS 1
  6. #define KEY_LONG_PRESS 2

  7. #define KEY0_CODE (char)0x01


  8. #define KEY_SHORT_CODE (char)0x10
  9. #define KEY_FIRST_LONG_CODE (char)0x80
  10. #define KEY_AFTER_LONG_CODE (char)0xc0

  11. #define KEYBUFFSIZE 4

  12. void key_paraInit(void);
  13. void keyScan(void);
  14. char key_readBuff(void);

  15. #endif



应用程序:
平台是STM32。

点击(此处)折叠或打开

  1. #include "led.h"
  2. #include "delay.h"
  3. #include "sys.h"
  4. #include "usart.h"
  5. #include "App_LongShortKey.h"

  6. uint8_t flag = 0;

  7. void SysTick_Init(void)
  8. {
  9.     if(SysTick_Config( SystemCoreClock / 100)) // 10ms
  10.     {
  11.         while(1);
  12.     }
  13.     
  14.     SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  15. }



  16. void SysTick_Handler(void)
  17. {
  18.     flag = 1;
  19. }



  20.  int main(void)
  21.  {    
  22.     char key = 0;
  23.     LED_Init();           
  24.     KEY_Init();
  25.     SysTick_Init();
  26.     uart_init(9600);
  27.     NVIC_Configuration();

  28.     __enable_irq();
  29.      
  30.     key_paraInit();
  31.      
  32.     while(1)
  33.     {
  34.         if(flag) // 10ms timer interrupt.
  35.         {
  36.             flag =0;
  37.             keyScan();
  38.         }

  39.         key = key_readBuff();
  40.         if(key != 0x00)
  41.         {
  42.             switch(key)
  43.             {
  44.                 case (KEY0_CODE+KEY_SHORT_CODE):
  45.                     printf("short key pressed \r\n");
  46.                 break;
  47.                 
  48.                 case (KEY0_CODE+KEY_FIRST_LONG_CODE):
  49.                     printf("long first pressed \r\n");
  50.                 break;
  51.                 
  52.                 case (KEY0_CODE+KEY_AFTER_LONG_CODE):
  53.                     printf("long after pressed \r\n");
  54.                 break;
  55.             }
  56.         }

  57.     }
  58.  }


实现方法:
状态机的实现,参看App_LongShortKey.c中的注释。


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