言归正传,先简介一下几个文件,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;
13
14 typedef void (*pKeyEventCB)(void *para);
15
16 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];
25 void * para[5];
26 }KeyInfo;
27
28 typedef struct _tagMessageInfo
29 {
30 unsigned int keyEvent;
31 unsigned int keyCode;
32 KeyInfo* pContext;
33 }MessageInfo;
34
35
36
37 void InitKey(void); //
38
39 void KeyProc(void);// call this func in main loop
40
41 void KeyScan(void); // call it in timer service, 20ms
42
43 pKeyEventCB SetKeyHandler(unsigned char key,KeyEventType event,pKeyEventCB pFunc,void *para);
44
45 #endif


1 #include "key_port.h"
2 #include "key.h"
3 #include "ringfifo.h"
4 #include
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
11 static KeyInfo kInfo[KEY_AMOUNT];
12 static RingFifo MsgQ;
13
14
15 void PostMessage(MessageInfo* pMsg)
16 {
17 PushFifo(&MsgQ,pMsg);
18 }
19
20 unsigned char GetMessage(MessageInfo*pMsg)
21 {
22 return PopFifo(&MsgQ,pMsg);
23 }
24
25 // call it in timer service
26 void KeyScan(void)
27 {
28 int i = 0;
29 unsigned char c = 0;
30 KeyInfo * pInfo = kInfo;
31 MessageInfo Msg;
32 for(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;
39 switch(pInfo->keyStatus)
40 {
41 case KEY_STATE_UP:
42 pInfo->keyDownTime = 0;
43 break;
44 case KEY_STATE_DOWN:
45 Msg.keyEvent = KEY_EVENT_DOWN;
46 PostMessage(&Msg); // post event
47 break;
48 case KEY_STATE_LONGRESS:
49 if(pInfo->keyDownTime < KEY_LONGPRESS_TIME /POLLING_INTERVAL)
50 {
51 pInfo->keyDownTime++;
52 }
53 else
54 {
55 if(pInfo->keyRepeatTime < KEY_LONGPRESS_REPEAT_INTERVAL/POLLING_INTERVAL)
56 {
57 ++pInfo->keyRepeatTime;
58 }
59 else
60 {
61 pInfo->keyRepeatTime = 0;
62 Msg.keyEvent = KEY_EVENT_LONGPRESS;
63 PostMessage(&Msg); // post event
64 }
65 }
66 break;
67 case KEY_STATE_RELEASE:
68 Msg.keyEvent = KEY_EVENT_UP;
69 PostMessage(&Msg); // post event
70 if(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;
76 break;
77 }
78 if(pInfo->keyDbClickTime)pInfo->keyDbClickTime--;
79 pInfo->keyStatus <<= 1;
80 ++pInfo;
81 }
82
83 }
84
85
86
87 // call this func in main()
88 void KeyProc(void)
89 {
90 KeyInfo * pInfo = 0;
91 int k = 10;
92 MessageInfo msg;
93 while(GetMessage(&msg) &&(k--))
94 {
95 pInfo = msg.pContext;
96 if(pInfo->FuncCB[msg.keyEvent])
97 {
98 pInfo->FuncCB[msg.keyEvent](pInfo->para[msg.keyEvent]);
99 }
100 }
101 }
102
103 pKeyEventCB SetKeyHandler(unsigned char key,KeyEventType event,pKeyEventCB pFunc,void *para)
104 {
105 pKeyEventCB pf = NULL;
106 int i = 0;
107 for(i = 0;i<KEY_AMOUNT;++i)
108 {
109 if(key == kInfo[i].keyCode)
110 {
111 pf = kInfo[i].FuncCB[event];
112 kInfo[i].FuncCB[event] = pFunc;
113 kInfo[i].para[event] = para;
114 break;
115 }
116 }
117 return pf;
118 }
119
120 void InitKey(void)
121 {
122 int i = 0;
123 InitFifo(&MsgQ);
124 memset(kInfo,0,sizeof(kInfo));
125 for(i = 0;i<KEY_AMOUNT;++i)
126 {
127 kInfo[i].keyCode = KeyCodeTable[i];
128 }
129
130 RegisterKeyHandler();
131 }


1 #ifndef __RINGFIFO_H__
2 #define __RINGFIFO_H__
3
4 #include "key.h"
5
6 #define FIFO_SIZE 10
7
8 typedef MessageInfo ElemDataType;
9
10 typedef struct _tagFifo
11 {
12 ElemDataType data[FIFO_SIZE]; // message
13 unsigned char read; //
14 unsigned char write; //
15 }RingFifo;
16
17 void 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);
21
22 #endif


1 #include "RingFifo.h"
2 #include
3 //#include
4
5 #define assert(x)
6
7 void InitFifo(RingFifo * pFifo)
8 {
9 assert(pFifo);
10 memset(pFifo,0,sizeof(RingFifo));
11 }
12
13 unsigned char PopFifo(RingFifo * pFifo,ElemDataType * pMsg)
14 {
15 assert(pFifo&&pMsg);
16 if(pFifo->read == pFifo->write)
17 {
18 return 0;
19 }
20 else
21 {
22 memcpy(pMsg,pFifo->data+pFifo->read,sizeof(ElemDataType));
23 pFifo->read = (pFifo->read+1)%FIFO_SIZE;
24 return 1;
25 }
26
27 }
28
29 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;
34 return 1;
35 }
36
37 unsigned char PeekFifo(RingFifo * pFifo,ElemDataType * pMsg)
38 {
39 assert(pFifo&&pMsg);
40 if(pFifo->read == pFifo->write)
41 {
42 return 0;
43 }
44 else
45 {
46 memcpy(pMsg,&pFifo->data[pFifo->read],sizeof(ElemDataType));
47 return 1;
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 10 extern unsigned char KeyCodeTable[KEY_AMOUNT]; 11 unsigned char ReadKeyStatus(unsigned char key); 12 void RegisterKeyHandler(void); 13 14 #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
24 void startStateMachine(void);
25 void key1handler(void *p) //
26 {
27 startStateMachine();
28 }
29
30 void key2handler(void *p) //reset
31 {
32
33 }
34
35
36 void key3handler(void *p) // reserve
37 {
38
39
40 }
41
42 void key3handler_up(void *p) //
43 {
44
45 }
46
47 void key4handler(void *p)
48 {
49
50 }
51
52 void key5handler(void *p)
53 {
54
55 }
56
57 void 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;
66 switch(key)
67 {
68 case KEY_1:
69 c = !GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5);
70 break;
71 case KEY_2:
72 c = !GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15);
73 break;
74 case KEY_3:
75 c = GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4);
76 break;
77 case KEY_4:
78
79 c = 0;
80 break;
81 case KEY_5:
82
83 c= 0;
84 break;
85 case KEY_6:
86 c= 0;
87 break;
88 }
89 return c;
90 }
91
92 void 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处理函数。
畅学电子







