打印
[匠人手记]

程序匠人及各位高手,看看这个按键思路怎么样。

[复制链接]
2942|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
vincent0319|  楼主 | 2012-2-23 13:20 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
TI, CAN, AN, ST, ic
优化一个4*4的按键程序,要返回长按键和短按键,大体思路如下:
1、功能函数key_scan 放while(1)里跑,不让系统有任何等待
2、通过状态机的方式实现
3、判断三次状态,有按键,消抖确定有按键,短按键或者长按键

看了很多种按键代码,消抖基本都用等待方式实现,效率不高,所以写了个这样的代码,全当练习。具体思路可以体现,但#define的不全。望高手指点二三。


type enum{
KEY_SCAN_FIRST;
KEY_SCAN_SECOND;
KEY_SCAN_THIRD;
}KEY_SCAN_STATE;

typedef unsigned long long TICK_TYPE;

TICK_TYPE systick=0;
void Systick(void) //系统定时器中断 ,1ms 间隔
{
systick++;
}

TICK_TYPE GET_currentTimetick() //获得当前TICK
{
return systick;
}

struct KEY_BODY{
unsigned char keynum;//哪个按键
unsigned char keytype;//按键状态
KEY_SCAN_STATE scan_status;//扫描状态
TICK_TYPE scan_starttime; //扫描开始tick
int keyshake_delay;//消抖tick
}key;



//KEYtype defines
#define KEY_DOWN_L 1
#define KEY_DOWN_S 2
#define KEY_UP     3








void key_init(struct KEY_BODY *key)
{
key->keynum=key->keytype=0;
key->scan_status = KEY_SCAN_FIRST;
key->scan_starttime=0;
key->keyshake_delay=25;//按键消抖时间

}
int key_on(void)
{
ROWPORT_IN;//行,4 IO 入,低电平:下拉
ROW_OUTPUT_LOW;
LINEPORT_OUT; //列:4 IO 出,高电平
LINE_OUTPUT_HING;
if(ROW_PIN1 != ROW_LOW_MASK) //行 4IO 不全为低 有按键发生
return KEY_ACTION;
else  
return NO_KEY_ACTION;       
}

void key_scan (struct KEY_BODY *key)
{
unsigned char i;
unsigned char keymask=0;
switch(key->scan_status)
{
case KEY_SCAN_FIRST:
if(key_on()==KEY_ACTION) //有按键,记录时间TICK,状态变换
{
key->scan_status = KEY_SCAN_SECOND;
key->scan_starttime=GET_currentTimetick();
}
break;

case KEY_SCAN_SECOND:
if(key_on()==KEY_ACTION) //继续有按键
{
if(GET_currentTimetick()- key->scan_starttime > keyshake_delay) //消抖间隔25ms  
{
for(i=0;i<4;i++) //判按键 i是列
{
keymask|=(1<<i); //0000 0001 ,0000 0010,0000 0100,......
LINE_PIN=keymask;
switch(ROW_PIN) //判断行 IO 电平
{
case 0x01: //第一行
key->keynum = i+1; //第一行四个按键,键值:1,2,3,4
break;
case 0x02://第二行
key->keynum = i+5; //第二行四个按键,键值:5,6,7,8
break;
case 0x04://第三行
key->keynum = i+9;//第三行四个按键,键值:9,10,11,12
break;
case 0x08://第四行
key->keynum = i+13;//第死行四个按键,键值:13,14,15,16
break;
}       
}
key->scan_status = KEY_SCAN_THIRD;
}
else return;       
}
else  
key->scan_status = KEY_SCAN_FIRST;
break;

case KEY_SCAN_THIRD:
key->scan_status = KEY_SCAN_FIRST;
key->scan_starttime=GET_currentTimetick(); //获得当前tick
do{ //等待按键释放
if(GET_currentTimetick()- key->scan_starttime > 2000) //按键持续2s,跳出,长按键
{
key->keytype=KEY_DOWNL;
return;
}       
}while(key_on()==KEY_ACTION)       

key->keytype=KEY_DOWN; //释放,短按键

break;

default:
break;
}


}

相关帖子

沙发
电子三极管| | 2012-5-4 15:24 | 只看该作者
本人有工控、交通类产品全部技术资料,有意向者请进(有图有真相)
https://bbs.21ic.com/icview-328904-1-1.html

语言: C,C++;
控制芯片: PIC, AVR, 51系列及LPC2132;   
通讯方式:RS232,RS485,TCPIP,Wi-Fi,CAN,USB等;

使用特权

评论回复
板凳
sedatefire| | 2012-6-6 10:22 | 只看该作者
个人经验,对于四个以上的按键
1.读原始电平
2.防抖滤波
3.判断
4.映射译码丢出事件

使用特权

评论回复
地板
sedatefire| | 2012-6-6 10:24 | 只看该作者
找个定时器挂着去,只要系统没有阻塞的设计,随便你挂主回圈还是定时器里。
定时器里要注意栈分配之类的细节

使用特权

评论回复
5
sedatefire| | 2012-6-6 10:25 | 只看该作者
要请教问题,把你的代码TAB清楚,人家才有心情看啊

使用特权

评论回复
6
chenluck| | 2012-7-10 17:31 | 只看该作者
晕晕晕晕晕晕晕晕晕晕晕

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

5

帖子

1

粉丝