石头

基于 残奕悟恩(刘平老师) 的状态机按键扫描程序学习

0
阅读(3137)

/************************************

学习笔记:基于 残奕悟恩(刘平老师)的状态机按键扫面方法
实现功能:按键Key1按下小于2S,按键按下一下,小灯依次点亮一个
               按键Key1按下大于2S,小灯以0.2S的速度依次点亮
硬件平台:面包板+STC12C5A60S2单片机
硬件接法: P1 口接8个LED,小灯
                P2^1 接 按键Key1  
晶振频率:11.0592Mhz
**********************************/

#include<STC12C5A60S2.H>   //头文件包含

typedef unsigned char uint8;
typedef unsigned int  uint16;

#define Led   P1
#define Initial_State  0       //按键初始状态
#define Affirm_State   1   //按键消抖状态
#define Single_State   2   //按键单击状态
#define Double_State   3   //按键连击状态

sbit Key1 = P2^1;

uint8 i = 0;

char Key_Scan();
void initial_myself();
void initial_peripheral();
void Delayms(uint16 z);
void Key_sever();

void main()
{  
    initial_myself();  //上电初始化 
    Delayms(10);
    initial_peripheral(); //外围设备初始化
    while(1)
    {
        Key_sever();     
    }

}

char Key_Scan()   //按键扫描函数
{
    static uint8 Key_Step = 0; //按键状态变量
    static Key_Time_Cnt1 = 0; //按键按下时间计数变量
    uint8 Key_Press1;
    Key_Press1 = Key1;

    switch(Key_Step)
    {
         case Initial_State:   //按键初始状态
        {
            if(!Key_Press1)
           {
               Key_Step = Affirm_State; 
           }
           else
          {
               Key_Step = Initial_State;
          }
       }
       break;

        case Affirm_State:  //按键确认状态
       {
            if(!Key_Press1)
           {
                Key_Step = Single_State;
           }
           else
           {
               Key_Step = Initial_State;
           }
       }
        break;

        case Single_State: //按键单击状态
       {
             Key_Time_Cnt1++;

             if(Key_Time_Cnt1>200) //按键按下一旦大于2秒,转到连击状态。
             {
                   Key_Time_Cnt1 = 0;
                   Key_Step = Double_State;
             }
             else if(Key_Press1) //按键松开,变量i加一次
            {
                  Key_Time_Cnt1 = 0;
                  Key_Step = Initial_State;
                  i++;
                  if(i == 8)
                  {
                        i = 0;
                  }
              }
         }
         break;
         case Double_State: //按键连击状态
        {
              if(!Key_Press1)
              {
                   Key_Time_Cnt1++;
                   if(20 == Key_Time_Cnt1)
                   {
                          Key_Time_Cnt1 = 0;
                          i++;
                         if(8 == i)
                         {
                                 i = 0;
                         }    
                    }   
             }
             else
             if(Key_Press1)
             {
                 Key_Step = Initial_State;
             }
          }
          break;
        }
       return i; 
}

void Key_sever() //按键服务函数
{
    Led = ~(0x01<<i);
}

void initial_myself() //上电初始化
{
    Led = 0xff;
    Key1 = 1;

    TMOD|= 0x01;
    TH0 = 0xdc;
    TL0 = 0x00;     
}

void initial_peripheral()  //外围设备初始化
{
    EA = 1;
    ET0 = 1;
    TR0 = 1;
}

void Delayms(uint16 z)
{
    uint16 x,y;
    for(x=0; x<z ; x++)
        for(y=0; y<1000; y++);
}

void interruptT0() interrupt 1 //T0中断函数,按键扫描函数放到中断中
{
    TF0 = 0;
    TH0 = 0xdc;
    TL0 = 0x00;
    Key_Scan();
}