|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2011-9-24 11:01:09
|
显示全部楼层
按键处理状态机:
#ifndef _KEY_H
#define _KEY_H
#include <avr/io.h>
#include <avr/iom16.h>
//PORTD 7 6 5 4 3 2 X X高四位接按键,低电平(按下)
// key4 key3 key2 key1
//根据使用的端口不同,修改key_mask,及计算键值部分
//按键返回值:
//0:无按键
//1:短按 <0.5s
//2:长按 >1s为长按,以后每0.5s返回一个长按信号
#define key_input PIND
#define key_mask 0x3c
#define key_state_0 0
#define key_state_1 1
#define key_state_2 2
#define key_state_3 3
#define key_no 0
#define key1_s 1
#define key1_l 2
#define key2_s 3
#define key2_l 4
#define key3_s 5
#define key3_l 6
#define key4_s 7
#define key4_l 8
//10ms调用一次key_read()
uchar key_read(void)
{
static uchar key_state = 0, key_old, key_time;
uchar key_press, key_temp, key_code = 0, key_return = key_no;
key_press = key_input & key_mask; //read IO
switch(key_state)
{
case key_state_0:
if(key_press != key_mask)
{
key_old = key_press;
key_state = key_state_1; //有键按下,转入状态1确认按键
}
break;
case key_state_1:
if(key_press == key_old)
{
key_state = key_state_2; //已确认,进入2
key_time = 0; //清零计时
}
else
key_state = key_state_0; //为干扰,回到0
break;
case key_state_2:
if(key_press == key_mask)
{
key_temp = (key_old ^ key_mask) >> 2; //key_old高四位取反,然后右移4位
while(key_temp)
{
key_temp >>= 1;
key_code++; //得到键值(1,2,3,4)
}
key_state = key_state_0; //键已释放,返回状态0
key_return = key_code * 2 - 1; //返回键的短按值
}
else if(++key_time >= 100) //按下时间>1s,进入状态2计时
{
key_temp = (key_old ^ key_mask) >> 2; //长按时,用当前按键输入计算键值
while(key_temp)
{
key_temp >>= 1;
key_code++; //得到键值(1,2,3,4)
}
key_state = key_state_3; //进入状态3计时
key_time = 0; //清零计时
key_return = key_code * 2; //返回按键的长按值
}
break;
case key_state_3:
if(key_press == key_mask)
key_state = key_state_0; //按键已释放,回到状态0
else
{ key_temp = (key_old ^ key_mask) >> 2; //长按时,用当前按键输入计算键值
while(key_temp)
{
key_temp >>= 1;
key_code++; //得到键值(1,2,3,4)
}
if(++key_time >= 50) //按下时间>0.5s
{
key_time = 0;
key_return = key_code * 2;
}
}
break;
default:
key_state = key_state_0;
}
return key_return;
}
#endif |
|