您的位置:首页 > 编程语言

按键状态机—实现连发

2010-07-02 17:18 169 查看
状态机的编程,最好的地方就是在于,一旦框架出现了,如果需要实现新的功能,只是需要增加新的状态。在c语言中,只需要增加几个简单的变量即可。而在labview中,只需要增加一个分支框图即可。就跟累积积木一样,为后期的更改提高了很大的可塑性。

在上次的程序中,更改一下,实现连发功能。关键是设置变量,检测按键按下的时间。同时增加一个状态,就是所谓的“连发状态”。

//这个的案件带有连按的功能,如果按下的时间超过一秒的话,进行连按的计算,也就是相应的加上一个状态key_state_3,一次通过
#include <avr/io.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define key_state_0 0		//空闲状态
#define key_state_1 1		//确认状态,消斗
#define key_state_2 2		//按键按下状态,等待释放
#define key_state_3 3		//连按状态在3状态之后
#define key_input PIND&_BV(PD7)
const uchar sec[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void IO_initial(){
PORTD = 0xff;
DDRD = 0x00;	//输入,上拉电阻有效
DDRB = 0xff;
PORTB = 0x00;	//输出,初始值为0
}
uchar key_state = 0;			//记录此刻按键的状态
volatile uchar key_stime_ok = 0x00;    // 这里面的volatile一定要加,否则就被优化掉了,attention
volatile uchar key_time_state2 = 0x00; //在状态2中的时间计数器
volatile uchar key_time_state3 = 0x00; //在状态3中的时间计数器
uchar getKey(){
uchar key_press,key_return = 0;
key_press = key_input;
switch(key_state){
case key_state_0:
if(!key_press){
key_state = key_state_1;			//按键被按下,装换到状态1
}
else key_state = key_state_0;					//否则保持0状态,可以去掉,但是这样结构清晰,表示出了所有的情况
break;
case key_state_1:
if(!key_press) {								//按键依然被按下,确定按键被按下
key_state = key_state_2;
key_time_state2 = 0x00;					//进入状态2,状态2的counter开始计数
key_return = 1;
}
else {
key_state = key_state_0;
}
break;
case key_state_2:
if(key_press)
key_state = key_state_0;
else if((!key_press)&(key_time_state2<50))
key_state = key_state_2;
else if((!key_press)&&(key_time_state2>=50)){
key_state = key_state_3 ;
key_time_state3 = 0;
}
break;
case key_state_3:
if((!key_press)&&(key_time_state3 >= 100)){
key_time_state3 = 0;
key_return = 1;
}
if(key_press){
key_state = key_state_0;
}
}
return key_return;
}
void Timer0_initial(){
TCCR0B = _BV(CS02)|_BV(CS00);				//1024分频,8/1024
TCNT0 = 0xb2;				//设置定时器初始值,使得每次定时值为10ms
TIMSK0 = _BV(TOIE0);
sei();
}
ISR(TIMER0_OVF_vect){
TCNT0 = 0xb2;
key_stime_ok = 0xff;
key_time_state2++;
key_time_state3++;
}

int main(){
IO_initial();
Timer0_initial();
uchar dispos = 0x00;
while(1){
if(key_stime_ok){
key_stime_ok = 0x00;
if(getKey()==1){
PORTB = sec[dispos];
if((++dispos) == 0x0e)
dispos = 0;
}
}
}
}


proteus图和上次的一样,gcc,mega48实现。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  timer input io 框架 gcc 编程