继
上一篇添加了一个小屏幕之后,这次计划把按键系统增加进去,毕竟作为最重要的输入交互部分,按键是整个系统必不可少的重要部分。
我的是第二批的LPC54100板子,板子上带了一个五位按键,一个复位按键,和两个功能键,一共8个,其中复位键我们不用处理,所以就是7个按键要处理。
我打算实现按键的长短按和连按的检测,所以需要建立一个按键处理状态机,首先进行初始化
- #include "key_fun.h"
- #include "bsp_key.h"
- #define KEY_COUNT 7
- #define KEY0 0x0001
- #define KEY1 0x0002
- #define KEY2 0x0004
- #define KEY3 0x0008
- #define KEY4 0x0010
- #define KEY5 0x0020
- #define KEY6 0x0040
- // 需要修改部分
- #define button0 KEY0_IN
- #define button1 (KEY1_IN)
- #define button2 KEY2_IN
- #define button3 KEY3_IN
- #define button4 (KEY4_IN)
- #define button5 KEY5_IN
- #define button6 KEY6_IN
- #define GetKey0 (button0?0:KEY0)
- #define GetKey1 (button1?0:KEY1)
- #define GetKey2 (button2?0:KEY2)
- #define GetKey3 (button3?0:KEY3)
- #define GetKey4 (button4?0:KEY4)
- #define GetKey5 (button5?0:KEY5)
- #define GetKey6 (button6?0:KEY6)
- // 控制按键时长
- #define LONG_PRESS_MAX 250 // 20ms*250=5s,长按最大
- #define LONG_PRESS 100 // 20ms*100=2s,长按
- #define SHORT_PRESS 5 // 20ms*5=100ms,短按
- #define MID_PRESS 50 // 20ms*50=1s,连按 第一次开始时间
- #define REPEAT_PRESS 25 // 20ms*25=500ms,连按灵敏参数 ,半秒钟触发一次
- #define FALSE false
- #define TRUE true
- //私有变量
- unsigned char key_time[KEY_COUNT];
- unsigned long io_last,io_now;
- //全局变量
- unsigned short key_status; // Long[15...8]/Short[7...0]
- // 初始化
- void key_fun_init(void)
- { unsigned char i;
- //初始化按键I/O口属性
- KEY_Initialize();
- //初始化变量
- io_last=0;
- io_now=0;
- key_status=0;
- for(i=0;i<KEY_COUNT;i++) key_time[i]=0;
- }
按键长按,短按和连按的时间在宏定义里面可以修改
接着是按键扫描程序
- // 按键处理
- void key_scan(void)
- {
- //按键端口上拉了,默认是高电平,有按键时变低。这里取反,有按键时变高。
- io_now=0;
- io_now=GetKey0|GetKey1|GetKey2|GetKey3|GetKey4|GetKey5|GetKey6;
- key_status=0;
- // set键只分长按和短按,没有连按
- if ((io_now&KEY0) & (io_last&KEY0))
- {
- key_time[0]++;
- if (key_time[0]==LONG_PRESS) {key_status|= KEY_SET_LONG;}
- if (key_time[0]>LONG_PRESS) key_time[0] = LONG_PRESS+1; //只触发一次
- }
- else
- { //按键释放
- if(key_time[0]>SHORT_PRESS)
- {
- if ((key_time[0]<LONG_PRESS)) key_status |= KEY_SET_SHORT; //短按只在按键释放时响应,且只触发一次,
- }
- key_time[0] = 0;
- }
- // up和down键有连按和短按,没有长按
- if ((io_now&KEY1) & (io_last&KEY1))
- {
- key_time[1]++;
- if (key_time[1]>MID_PRESS) //持续按住过程中当时间大于MID_PRESS定义时触发一次短按
- {
- key_status |= KEY_UP_SHORT;
- key_time[1] = key_time[1] - REPEAT_PRESS; //设定出发周期,继续等待下一次触发
- }
- }
- else
- {
- if (key_time[1]>SHORT_PRESS)
- {
- key_status |= KEY_UP_SHORT; //释放时根据时间触发一次短按
- }
- key_time[1] = 0; //只要释放,都要重新计时
- }
- // up和down键有连按和短按,没有长按
- if ((io_now&KEY2) & (io_last&KEY2))
- {
- key_time[2]++;
- if (key_time[2]>MID_PRESS)
- {
- key_status |= KEY_DOWN_SHORT;
- key_time[2] = key_time[2] - REPEAT_PRESS;
- }
- }
- else
- {
- if (key_time[2]>SHORT_PRESS)
- {
- key_status |= KEY_DOWN_SHORT;
- }
- key_time[2] = 0;
- }
-
- // up和down键有连按和短按,没有长按
- if ((io_now&KEY3) & (io_last&KEY3))
- {
- key_time[3]++;
- if (key_time[3]>MID_PRESS)
- {
- key_status |= KEY_LEFT_SHORT;
- key_time[3] = key_time[3] - REPEAT_PRESS;
- }
- }
- else
- {
- if (key_time[3]>SHORT_PRESS)
- {
- key_status |= KEY_LEFT_SHORT;
- }
- key_time[3] = 0;
- }
-
- // up和down键有连按和短按,没有长按
- if ((io_now&KEY4) & (io_last&KEY4))
- {
- key_time[4]++;
- if (key_time[4]>MID_PRESS)
- {
- key_status |= KEY_RIGHT_SHORT;
- key_time[4] = key_time[4] - REPEAT_PRESS;
- }
- }
- else
- {
- if (key_time[4]>SHORT_PRESS)
- {
- key_status |= KEY_RIGHT_SHORT;
- }
- key_time[4] = 0;
- }
- // KEY1键只分长按和短按,没有连按
- if ((io_now&KEY5) & (io_last&KEY5))
- {
- key_time[5]++;
- if (key_time[5]==LONG_PRESS) {key_status|= KEY_KEY1_LONG;}
- if (key_time[5]>LONG_PRESS) key_time[5] = LONG_PRESS+1; //只触发一次
- }
- else
- { //按键释放
- if(key_time[5]>SHORT_PRESS)
- {
- if ((key_time[5]<LONG_PRESS)) key_status |= KEY_KEY1_SHORT; //短按只在按键释放时响应,且只触发一次,
- }
- key_time[5] = 0;
- }
- // KEY2键只分长按和短按,没有连按
- if ((io_now&KEY6) & (io_last&KEY6))
- {
- key_time[6]++;
- if (key_time[6]==LONG_PRESS) {key_status|= KEY_KEY2_LONG;}
- if (key_time[6]>LONG_PRESS) key_time[6] = LONG_PRESS+1; //只触发一次
- }
- else
- { //按键释放
- if(key_time[6]>SHORT_PRESS)
- {
- if ((key_time[6]<LONG_PRESS)) key_status |= KEY_KEY2_SHORT; //短按只在按键释放时响应,且只触发一次,
- }
- key_time[6] = 0;
- }
-
-
-
- // 添加自己对于set_long,set_short,up_short,down_short的处理代码
- // 处理完了不要忘记把相应的值置为FALSE
- io_last = io_now;
- }
在主循环里周期性调用按键扫描函数即可,之后就可以通过判断key_status即可知道是那个或那些按键按下了。
- /* 处理完毕,清除标志位 */
- void key_flag_clr(void)
- {
- key_status=0;
- }
之后需要清掉key_status。
主循环
- Lcd7585_write_string(0,7,(char *)"LPC541x Board");
- Lcd7585_write_string(0,6,(char *)" --by Shower.xu");
- while(1)
- {
- delay_xms(15);
- key_scan();
- if(key_status)
- {
- if(key_status&KEY_SET_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(12,3,(char *)"o");
- if(key_status&KEY_UP_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(12,4,(char *)"^");
- if(key_status&KEY_DOWN_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(12,2,(char *)"v");
- if(key_status&KEY_LEFT_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(2,3,(char *)"<");
- if(key_status&KEY_RIGHT_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(22,3,(char *)">");
- if(key_status&KEY_KEY1_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(42,4,(char *)" KEY1 ");
- if(key_status&KEY_KEY2_SHORT) Lcd7585_SetDisplay(DISP_NEGATIVE);else Lcd7585_SetDisplay(DISP_POSITIVE);
- Lcd7585_write_string(42,2,(char *)" KEY2 ");
- key_flag_clr();
- }
- }
这样就可以在lcd上显示出来按键状态了。
其中向左的按键因为和swd调试接口复用,所以.....,真是奇怪的设计
图片在这里
代码在这里
4-Key2.rar
(47.06 KB)
(下载次数: 28, 2015-4-5 10:04 上传)
视频在这里
[media]http://www.tudou.com/v/rMYC7T6B7gc/&rpid=100900070&resourceId=100900070_04_05_99/v.swf[/media]