首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

单片机程序架构2

单片机程序架构2

//avr 单片机 中4*3扫描状态机实现

char read_keyboard_FUN2()

{



static char key_state = 0, key_value, key_line,key_time;


char
key_return = No_key,i;

switch (key_state)

{


case 0:
//最初的状态,进行3*4的键盘扫描

key_line = 0b00001000;

for
(i=1; i<=4; i++)
// 扫描键盘

{

PORTD = ~key_line; // 输出行线电平


PORTD =
~key_line; // 必须送2次!!!(注1)

key_value = Key_mask
& PIND; // 读列电平


if (key_value == Key_mask)

key_line
<<= 1; // 没有按键,继续扫描


else

{

key_state++; //
有按键,停止扫描

break; //
转消抖确认状态

}

}

break;


case 1:
//此状态来判断按键是不是抖动引起的

if (key_value == (Key_mask &
PIND)) // 再次读列电平,


{

key_state++; // 转入等待按键释放状态


key_time=0;

}


else

key_state--; //
两次列电平不同返回状态0,(消抖处理)

break;


case 2: // 等待按键释放状态

PORTD
= 0b00000111; // 行线全部输出低电平


PORTD = 0b00000111; // 重复送一次

if (
(Key_mask & PIND) ==
Key_mask)

{

key_state=0; //
列线全部为高电平返回状态0

key_return=
(key_line |
key_value);//获得了键值

}

else

if(++key_time>=100)//如果长时间没有释放

{

key_time=0;

key_state=3;//进入连键状态

key_return=

(key_line | key_value);

}

break;

case

3://对于连键,每隔50ms就得到一次键值,windows xp 系统就是这样做的

PORTD = 0b00000111; //

行线全部输出低电平

PORTD = 0b00000111; // 重复送一次

if ( (Key_mask &

PIND) == Key_mask)

key_state=0; // 列线全部为高电平返回状态0

else

if(++key_time>=5)

//每隔50MS为一次连击的按键

{

key_time=0;

key_return= (key_line |

key_value);

}

break;

}

return key_return;



}


以上用了4个状态,一般的键盘扫描只用前面3个状态就可以了,后面一个状态是为增加“连键”功能设计的。连键——即如果按下某个键不放,则迅速的多次响应

该键值,直到其释放。在主循环中每隔10ms让该键盘扫描函数执行一次即可;我们定其时限为10ms,当然要求并不严格。
返回列表