|
发表于 2013-6-17 10:34:05
|
显示全部楼层
本帖最后由 sqmm 于 2013-6-17 10:50 编辑
我老早实现过单个按键实现导航的程序
能够单击双击,3击....9击...N击
能够识别长按,单击后长按,双击后长按....N击后长按
直接用button_get()返回不同键码.
可以很方便实现导航.
用一个定时器,主循环保证150ms内有查询就OK
- #include<avr/interrupt.h>
- #include<cpu/cpu.h>
- #include"avrbutton.h"
- static dwordVal_t tsKeyDown;
- static dwordVal_t tsKeyUp;
- static dwordVal_t* ptsKeyLast = &tsKeyDown; // 最近按键动作计时
- static u8 ButtonAction; // 为主循环提供按钮事件信号
- static u8 KeyIsMulti; // 连击标识,1:有可能连击
- static u8 KeyCount; // 连击次数
- #define MULTI_CLIK 150
- #define LONG_PRESS 1000
- #define KEY_REPEAT 300
- u16 ms_diff(dwordVal_t* more, dwordVal_t* less)
- {
- u16 ret = more->Val - less->Val;
- return ( ret & 0x8000 )?0xFFFF:ret;
- }
- SIGNAL ( MutiFunction_ISR )
- {
- if( !ms_passed(ptsKeyLast,21) )// 消抖
- return;
- u8 state = PIN_H(MutiFunction_KEY);
- if(!state)
- {//按键弹起
- if(ButtonAction>=3)//重复后驱动复位
- {
- KeyCount = 0;
- ButtonAction = 0;
- KeyIsMulti = 0;
- return;
- }
- ButtonAction = 2;
- tsKeyUp.Val = SysClock.Val;
- ptsKeyLast = &tsKeyUp;
- if(KeyIsMulti)
- {
- KeyCount ++;
- }
- }
- else
- {//按键按下
- ButtonAction = 1;
- tsKeyDown.Val = SysClock.Val;
- ptsKeyLast = &tsKeyDown;
- if( ms_diff(&tsKeyDown, &tsKeyUp)<MULTI_CLIK )// 有可能是连击
- {
- KeyIsMulti = 1;
- if(KeyCount==0)
- KeyCount = 1;
- }
- }
- }
- u8 button_get(void)
- {
- u8 ret = 0;
- if(ButtonAction==0)
- {
- return ret;
- }
- else if(ButtonAction==2)
- {
- if( ms_passed(ptsKeyLast, MULTI_CLIK) )
- {
- if(KeyIsMulti)
- {
- ret = KeyCount;
- }
- else// 要么单击要么长按
- {
- ret = 1;// 单击
- }
- KeyCount = 0;
- ButtonAction = 0;
- KeyIsMulti = 0;
- }
- }
- else if(ButtonAction==1)
- {// 很可能产生连击事件.
- if( ms_passed(ptsKeyLast, LONG_PRESS) )
- {
- ButtonAction = 3;
- ret = KeyCount?KeyCount:0xFF;
- }
-
- }
- else if(ButtonAction==3)
- {
- if( ms_passed(ptsKeyLast, KEY_REPEAT) )
- {
- if( PIN_L(MutiFunction_KEY) )//按键弹起确认
- {
- KeyCount = 0;
- ButtonAction = 0;
- KeyIsMulti = 0;
- return ret;
- }
- //ptsKeyLast->Val = SysClock.Val;
- //ret = KeyCount?KeyCount:0xFF;
- }
- }
- return ret;
- }
- // 初始化按钮端口,打开按钮电平跳变中断
- void button_init(u8 id)
- {
- DRIVER(MutiFunction_KEY, IN);
- CLR( MutiFunction_KEY );
- MASK_1(EIMSK, MutiFunction_INT);
- MASK(EICRB, 0x1/*0b01*/<<((MutiFunction_INT-4)<<1));
- ButtonAction = 0;
- }
复制代码 |
|