单片机按键处理框架
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了单片机按键处理框架,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7986字,纯文字阅读大概需要12分钟。
内容图文
写过一段时间单片机程序,也看了一些单片机程序,书上的,网上的,基本都是非常原始的读取按键,延时判断,这些按键相关代码穿插于整个程序,着实不够美观,最重要的是不能复用,so俺就想做个按键框架,只需提供按键处理代码即可,言归正传,先简介一下几个文件,ringfifo.c提供了一个简单的环形缓冲队列,用以通知按键消息,key.c 实现的按键的框架处理(读取按键,调用按键处理函数),key_port.c 需提供底层硬件接口及用户的按键处理函数,目前支持的按键消息类型有4类:keyDown,keyRelease,longPress, double click.
key.h中提供了4个函数:InitKey()为初始化, KeyProc() 须在主循环中调用,KeyScan()须定时(10-20ms)调用,SetKeyHandler()用来设置按键处理函数
1 #ifndef __KEY_H__ 2 #define __KEY_H__ 3 4#define NULL 0 5 6 typedef enum{ 7 KEY_EVENT_DOWN = 0, 8 KEY_EVENT_UP, 9 KEY_EVENT_LONGPRESS, 10 KEY_EVENT_DOUBLECLICK, 11 KEY_EVENT_COMBO_KEYDOWN, 12}KeyEventType; 1314 typedef void (*pKeyEventCB)(void *para); 1516 typedef struct _tagKeyInfo 17{ 18 unsigned char keyCode; 19 unsigned char keyStatus; 20 unsigned char comboKeyFlag; 21 unsigned int keyDbClickTime; 22 unsigned int keyDownTime; 23 unsigned int keyRepeatTime; 24 pKeyEventCB FuncCB[5]; 25void * para[5]; 26}KeyInfo; 2728 typedef struct _tagMessageInfo 29{ 30 unsigned int keyEvent; 31 unsigned int keyCode; 32 KeyInfo* pContext; 33}MessageInfo; 34353637void InitKey(void); //3839void KeyProc(void);// call this func in main loop4041void KeyScan(void); // call it in timer service, 20ms4243 pKeyEventCB SetKeyHandler(unsigned char key,KeyEventType event,pKeyEventCB pFunc,void *para); 4445#endif
1 #include "key_port.h" 2 #include "key.h" 3 #include "ringfifo.h" 4 #include <string.h> 5 6#define KEY_STATE_UP 0X0 7#define KEY_STATE_DOWN 0X3 8#define KEY_STATE_LONGRESS 0XF 9#define KEY_STATE_RELEASE 0XC 10 11static KeyInfo kInfo[KEY_AMOUNT]; 12static RingFifo MsgQ; 13 14 15void PostMessage(MessageInfo* pMsg) 16{ 17 PushFifo(&MsgQ,pMsg); 18} 19 20 unsigned char GetMessage(MessageInfo*pMsg) 21{ 22return PopFifo(&MsgQ,pMsg); 23} 24 25// call it in timer service 26void KeyScan(void) 27{ 28int i = 0; 29 unsigned char c = 0; 30 KeyInfo * pInfo = kInfo; 31 MessageInfo Msg; 32for(i=0;i<KEY_AMOUNT;++i) 33 { 34 Msg.pContext = pInfo; 35 Msg.keyCode = pInfo->keyCode; 36 c = ReadKeyStatus(Msg.keyCode); // 37 pInfo->keyStatus |= c; 38 pInfo->keyStatus &= 0xF; 39switch(pInfo->keyStatus) 40 { 41case KEY_STATE_UP: 42 pInfo->keyDownTime = 0; 43break; 44case KEY_STATE_DOWN: 45 Msg.keyEvent = KEY_EVENT_DOWN; 46 PostMessage(&Msg); // post event 47break; 48case KEY_STATE_LONGRESS: 49if(pInfo->keyDownTime < KEY_LONGPRESS_TIME /POLLING_INTERVAL) 50 { 51 pInfo->keyDownTime++; 52 } 53else 54 { 55if(pInfo->keyRepeatTime < KEY_LONGPRESS_REPEAT_INTERVAL/POLLING_INTERVAL) 56 { 57 ++pInfo->keyRepeatTime; 58 } 59else 60 { 61 pInfo->keyRepeatTime = 0; 62 Msg.keyEvent = KEY_EVENT_LONGPRESS; 63 PostMessage(&Msg); // post event 64 } 65 } 66break; 67case KEY_STATE_RELEASE: 68 Msg.keyEvent = KEY_EVENT_UP; 69 PostMessage(&Msg); // post event 70if(pInfo->keyDbClickTime) //double click 71 { 72 Msg.keyEvent = KEY_EVENT_DOUBLECLICK; 73 PostMessage(&Msg); // post event 74 } 75 pInfo->keyDbClickTime = KEY_DBCLICK_TIME /POLLING_INTERVAL; 76break; 77 } 78if(pInfo->keyDbClickTime)pInfo->keyDbClickTime--; 79 pInfo->keyStatus <<= 1; 80 ++pInfo; 81 } 82 83} 84 85 86 87// call this func in main() 88void KeyProc(void) 89{ 90 KeyInfo * pInfo = 0; 91int k = 10; 92 MessageInfo msg; 93while(GetMessage(&msg) &&(k--)) 94 { 95 pInfo = msg.pContext; 96if(pInfo->FuncCB[msg.keyEvent]) 97 { 98 pInfo->FuncCB[msg.keyEvent](pInfo->para[msg.keyEvent]); 99 } 100 } 101} 102103 pKeyEventCB SetKeyHandler(unsigned char key,KeyEventType event,pKeyEventCB pFunc,void *para) 104{ 105 pKeyEventCB pf = NULL; 106int i = 0; 107for(i = 0;i<KEY_AMOUNT;++i) 108 { 109if(key == kInfo[i].keyCode) 110 { 111 pf = kInfo[i].FuncCB[event]; 112 kInfo[i].FuncCB[event] = pFunc; 113 kInfo[i].para[event] = para; 114break; 115 } 116 } 117return pf; 118} 119120void InitKey(void) 121{ 122int i = 0; 123 InitFifo(&MsgQ); 124 memset(kInfo,0,sizeof(kInfo)); 125for(i = 0;i<KEY_AMOUNT;++i) 126 { 127 kInfo[i].keyCode = KeyCodeTable[i]; 128 } 129130 RegisterKeyHandler(); 131 }
1 #ifndef __RINGFIFO_H__ 2 #define __RINGFIFO_H__ 3 4 #include "key.h" 5 6#define FIFO_SIZE 10 7 8typedef MessageInfo ElemDataType; 910 typedef struct _tagFifo 11{ 12 ElemDataType data[FIFO_SIZE]; // message 13 unsigned char read; // 14 unsigned char write; // 15}RingFifo; 1617void InitFifo(RingFifo * pFifo); 18 unsigned char PopFifo(RingFifo * pFifo,ElemDataType * pMsg); 19 unsigned char PushFifo(RingFifo * pFifo,ElemDataType * pMsg); 20 unsigned char PeekFifo(RingFifo * pFifo,ElemDataType * pMsg); 2122#endif
1 #include "RingFifo.h" 2 #include <string.h> 3//#include <assert.h> 4 5#define assert(x) 6 7void InitFifo(RingFifo * pFifo) 8{ 9 assert(pFifo); 10 memset(pFifo,0,sizeof(RingFifo)); 11} 1213 unsigned char PopFifo(RingFifo * pFifo,ElemDataType * pMsg) 14{ 15 assert(pFifo&&pMsg); 16if(pFifo->read == pFifo->write) 17 { 18return0; 19 } 20else21 { 22 memcpy(pMsg,pFifo->data+pFifo->read,sizeof(ElemDataType)); 23 pFifo->read = (pFifo->read+1)%FIFO_SIZE; 24return1; 25 } 2627} 2829 unsigned char PushFifo(RingFifo * pFifo,ElemDataType * pMsg) 30{ 31 assert(pFifo&&pMsg); 32 memcpy(pFifo->data+pFifo->write,pMsg,sizeof(ElemDataType)); 33 pFifo->write = (pFifo->write + 1) % FIFO_SIZE; 34return1; 35} 3637 unsigned char PeekFifo(RingFifo * pFifo,ElemDataType * pMsg) 38{ 39 assert(pFifo&&pMsg); 40if(pFifo->read == pFifo->write) 41 { 42return0; 43 } 44else45 { 46 memcpy(pMsg,&pFifo->data[pFifo->read],sizeof(ElemDataType)); 47return1; 48 } 49 }
key_port.h中, KEY_AMOUNT代表能识别的按键个数, 用户需实现ReadKeyStatus(),RegisterKeyHandler()这2个函数,其中
ReadKeyStatus()用来读取硬件按键状态,具体可参见key_port.c示例
RegisterKeyHandler()用来设置按键处理函数。
1 #ifndef __KEY_PORT_H__ 2 #define __KEY_PORT_H__ 3 4#define KEY_AMOUNT 6 5 6#define KEY_LONGPRESS_TIME 3000 // 3S 7#define KEY_DBCLICK_TIME 500 8#define POLLING_INTERVAL 20 //timer interval 9#define KEY_LONGPRESS_REPEAT_INTERVAL 500 10extern unsigned char KeyCodeTable[KEY_AMOUNT]; 11 unsigned char ReadKeyStatus(unsigned char key); 12void RegisterKeyHandler(void); 1314#endif
1 #include "key_port.h" 2 #include "key.h" 3 #include "stm32f10x.h" 4 #include "timer.h" 5 #include "stepper.h" 6 7#define KEY_1 1 8#define KEY_2 2 9#define KEY_3 3 10#define KEY_4 4 11#define KEY_5 5 12#define KEY_6 6 13 14 unsigned char KeyCodeTable[KEY_AMOUNT]= 15{ 16 KEY_1, 17 KEY_2, 18 KEY_3, 19 KEY_4, 20 KEY_5, 21 KEY_6 22}; 23 24void startStateMachine(void); 25void key1handler(void *p) // 26{ 27 startStateMachine(); 28} 29 30void key2handler(void *p) //reset 31{ 32 33} 34 35 36void key3handler(void *p) // reserve 37{ 38 39 40} 41 42void key3handler_up(void *p) // 43{ 44 45} 46 47void key4handler(void *p) 48{ 49 50} 51 52void key5handler(void *p) 53{ 54 55} 56 57void key6handler(void *p) 58{ 59 60} 61 62// get key status,return 1 if key down , 63 unsigned char ReadKeyStatus(unsigned char key) 64{ 65 unsigned char c = 0; 66switch(key) 67 { 68case KEY_1: 69 c = !GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5); 70break; 71case KEY_2: 72 c = !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15); 73break; 74case KEY_3: 75 c = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4); 76break; 77case KEY_4: 78 79 c = 0; 80break; 81case KEY_5: 82 83 c= 0; 84break; 85case KEY_6: 86 c= 0; 87break; 88 } 89return c; 90} 91 92void RegisterKeyHandler(void) 93{ 94// Add you key event func here 95 SetKeyHandler(KEY_1,KEY_EVENT_DOWN,key1handler ,0); 96 SetKeyHandler(KEY_2,KEY_EVENT_DOWN,key2handler ,0); 97 SetKeyHandler(KEY_3,KEY_EVENT_DOWN,key3handler ,0); 98 SetKeyHandler(KEY_3,KEY_EVENT_UP,key3handler_up ,0); 99 SetKeyHandler(KEY_4,KEY_EVENT_DOWN,key4handler ,0); 100 SetKeyHandler(KEY_5,KEY_EVENT_DOWN,key5handler ,0); 101 SetKeyHandler(KEY_6,KEY_EVENT_UP,key6handler ,0); 102 }
在key_port.c中,提供了一个示例,分别设置了3个按键key_1,key_2,key_3的keydown处理函数,同时设置了key_3的keyUp处理函数。
原文:http://www.cnblogs.com/mayitbe/p/3914743.html
内容总结
以上是互联网集市为您收集整理的单片机按键处理框架全部内容,希望文章能够帮你解决单片机按键处理框架所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。