怎么使用状态机?
系统有三个按键,功能分别是调整,加,减。我已经用状态机实现在第一次按下调整键时候,停止走时,显示秒的两位数码管以1 Hz 频率闪烁;如果第二次按下调整键,则分开始闪烁,秒恢复正常显示;如果第三次按下调整键,则时开始闪烁,分恢复正常显示;如果第四次按下调整键,时恢复正常显示,开始走时。怎么用状态机实现在数码管闪烁的时候,按下加或者减键可以调整相应的显示内容,
/************
作者:liyang
日期:2012年11月17日
目标MCU:STC89C51晶振:11.0592M
******************************/
#include<reg51.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
uint8 LedBitCnt; //LedBitCnt控制数码管的位选
uint8 flagm=0,flagf=0,flags=0;//时分秒闪烁的控制标志位
uint8 ms2_flag; //2ms数码管动态扫描时标消息
uint8 ms10_flag,ms500_flag,s1num;
uint8 ms2_cnt,ms10_cnt,count,s1num;
uint8 dis_buff={0};
uint8 shi=12,fen=23,miao=56;
uint8 code SegTab[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x40,0x00};
sbit ADDR0 = P2^0;//74hc138的输入控制端A
sbit ADDR1 = P2^1;//74hc138的输入控制端B
sbit ADDR2 = P2^2;//74hc138的输入控制端C
sbit adjust=P3^2;
sbit add=P3^3;
sbit sub=P3^4;
#define key_state_00
#define key_state_11
#define key_state_22
void disp()
{
P0=SegTab];
switch(LedBitCnt)
{
case 0:
ADDR0=0;ADDR1=0;ADDR2=0;
break;
case 1:
ADDR0=1;ADDR1=0;ADDR2=0;
break;
case 2:
ADDR0=0;ADDR1=1;ADDR2=0;
break;
case 3:
ADDR0=1;ADDR1=1;ADDR2=0;
break;
case 4:
ADDR0=0;ADDR1=0;ADDR2=1;
break;
case 5:
ADDR0=1;ADDR1=0;ADDR2=1;
break;
case 6:
ADDR0=0;ADDR1=1;ADDR2=1;
break;
case 7:
ADDR0=1;ADDR1=1;ADDR2=1;
break;
}
}
void time_to_disbuff(void)
{
if(flagm&(!ms500_flag))
{
dis_buff=11;
dis_buff=11;
}
else
{
dis_buff=miao%10;
dis_buff=miao/10;
}
dis_buff=10;
if(flagf&(!ms500_flag))
{
dis_buff=11;
dis_buff=11;
}
else
{
dis_buff=fen%10;
dis_buff=fen/10;
}
dis_buff=10;
if(flags&(!ms500_flag))
{
dis_buff=11;
dis_buff=11;
}
else
{
dis_buff=shi%10;
dis_buff=shi/10;
}
}
void init()
{
TMOD=0x11;
TH1=0xf8;
TL1=0xcd;
TH0=0x4c;
TL0=0x00;
TR0=1;
ET0=1;
TR1=1;
ET1=1;
}
char read_key(void)
{
static char key_state=0;
char key_press,key_return=0;
key_press = adjust;// 读按键 I/O电平
switch (key_state)
{
case key_state_0:// 按键初始态
if (!key_press)
key_state = key_state_1;//键被按下,状态转换到键确认态
break;
case key_state_1:// 按键确认态
if (!key_press)
{
s1num++;
key_return = 1;// 按键仍按下,按键确认输出为“1”
key_state = key_state_2;// 状态转换到键释放态
}
else
key_state = key_state_0;// 按键已抬起,转换到按键初始态
break;
case key_state_2:
if(key_press)
key_state = key_state_0;//按键已释放,转换到按键初始态
break;
}
return key_return;
}
void main()
{
init();
EA=1;
time_to_disbuff();
P0=0x00;
while(1)
{
if(ms2_flag)
{
ms2_flag=0;
LedBitCnt++;
if(LedBitCnt>7)
{
LedBitCnt=0;
}
time_to_disbuff();
disp();
}
if(ms10_flag)
{
ms10_flag=0;
if(read_key())
{
if(s1num==1)
{
flagm=1;
TR0=0;
}
}
if(s1num==2)
{
flagm=0;
flagf=1;
}
if(s1num==3)
{
flagm=0;
flagf=0;
flags=1;
}
if(s1num==4)
{
TR0=1;
flags=0;
s1num=0;
}
}
}
}
void timer0() interrupt 1
{
TH0=0x4c;
TL0=0x00;
count++;
if(count==20)
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
}
}
}
}
void timer1() interrupt 3//定时1ms
{
TH1=0xf8;
TL1=0xcd;
ms2_flag=1; //用于数码管显示
ms2_cnt++;
if(ms2_cnt>=5)
{
ms2_cnt=0;
ms10_flag=1;//用于键扫描
if(++ms10_cnt>=50)
{
ms10_cnt=0;
ms500_flag=~ms500_flag;
}
}
}
页:
[1]