bbxyliyang08 发表于 2012-11-17 19:24:27

怎么使用状态机?


系统有三个按键,功能分别是调整,加,减。我已经用状态机实现在第一次按下调整键时候,停止走时,显示秒的两位数码管以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]
查看完整版本: 怎么使用状态机?