久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計(jì)實(shí)例 >> 瀏覽文章

計(jì)數(shù)器(狀態(tài)機(jī)按鍵檢測(cè))程序

作者:佚名   來源:本站原創(chuàng)   點(diǎn)擊數(shù):  更新時(shí)間:2014年02月13日   【字體:

       狀態(tài)機(jī)是軟件編程中的重要概念,比這個(gè)概念更重要的是對(duì)它的靈活應(yīng)用。在一個(gè)思路清晰而且高效的程序中,必然有狀態(tài)機(jī)的身影浮現(xiàn)。例如,一個(gè)按鍵命令解析程序就可以被看做狀態(tài)機(jī):本來在A狀態(tài)下,觸發(fā)一個(gè)按鍵后切換到了B狀態(tài);再觸發(fā)另一個(gè)鍵后切換到C狀態(tài),或者返回到A狀態(tài)。這就是最簡單的按鍵狀態(tài)機(jī)的例子。實(shí)際的按鍵解析程序會(huì)比這更復(fù)雜,但這并不影響我們對(duì)狀態(tài)機(jī)的認(rèn)識(shí)。
       進(jìn)一步看,擊鍵動(dòng)作本身可以看做一個(gè)狀態(tài)機(jī)。一個(gè)擊鍵動(dòng)作包含按下、抖動(dòng)、釋放等狀態(tài)。其實(shí)狀態(tài)機(jī)的思想不單只是用在按鍵方面,數(shù)碼管顯示動(dòng)態(tài)掃描、LED燈亮滅都存在狀態(tài)機(jī)的思想。使用狀態(tài)機(jī)思想進(jìn)行單片機(jī)編程,比較通用的方法就是使用switch的選擇性分支語句來進(jìn)行狀態(tài)跳轉(zhuǎn)。
      通過計(jì)數(shù)器這個(gè)實(shí)驗(yàn)向大家展示狀態(tài)機(jī)的思想。


上圖是proteus仿真圖,時(shí)間每過1s計(jì)數(shù)器值自動(dòng)加1,K1啟動(dòng)和停止計(jì)數(shù)器,K2選擇要修改的位,K3當(dāng)前位加1,K4當(dāng)前位減1。
完整代碼如下:
#include<reg51.h>

typedef unsigned char UINT8;
typedef unsigned int  UINT16;
typedef unsigned long UINT32;
typedef char          INT8;
typedef int              INT16;
typedef long          INT32;

#define TIMER0_INITIAL_VALUE 5000    //5ms定時(shí)
#define SEG_PORT             P0        //數(shù)碼管占用的IO口
#define KEY_PORT             P1        //按鍵占用的IO口
#define KEY_MASK             0x0F    //按鍵掩碼
#define KEY_SEARCH_STATUS     0        //查詢按鍵狀態(tài)
#define KEY_ACK_STATUS         1        //確認(rèn)按鍵狀態(tài)
#define    KEY_REALEASE_STATUS     2        //釋放按鍵狀態(tài)
#define KEY1                 1        //按鍵1鍵值
#define KEY2                 2        //按鍵2鍵值
#define KEY3                 3        //按鍵3鍵值
#define KEY4                 4        //按鍵4鍵值

#define HIGH                1
#define LOW                    0
#define ON                    1
#define OFF                    0

sbit DATA = P0^4;
sbit CLK = P0^5;

UINT8 Timer0IRQEvent = 0;    //定時(shí)器0中斷事件
UINT8 Time1SecEvent = 0;    //1s定時(shí)事件
UINT8 TimeCount = 0;        //定時(shí)器0計(jì)數(shù)器,用于計(jì)數(shù)產(chǎn)生1s定時(shí)事件
UINT8 SegCurPosMark = 0;    //被選中的數(shù)碼管
UINT16 CounterValue = 0;    //計(jì)數(shù)器
UINT8 SegCurSel = 0;        //當(dāng)前選中的數(shù)碼管
UINT8 SegBuf[4] = {0};
code UINT8 SegCode[10] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F};
code UINT8 SegSelTbl[4] = {0xFE,0xFD,0xFB,0xF7};
UINT8 bSetTime = 0;            //標(biāo)志位:是否設(shè)置計(jì)數(shù)值

void LS164_DATA(unsigned char x)
{
    if(x)
    {
        DATA = 1;
    }
    else
    {
        DATA = 0;
    }
}
void LS164_CLK(unsigned char x)
{
    if(x)
    {
        CLK = 1;
    }
    else
    {
        CLK = 0;
    }
}
/**********************************************************
*函數(shù)名稱:LS164Send
*輸    入:byte單個(gè)字節(jié)
*輸    出:無
*功    能:74LS164發(fā)送單個(gè)字節(jié)
***********************************************************/
void LS164Send(UINT8 byte)
{
    UINT8 j;
    for(j=0;j<=7;j++)
    {
        if(byte&(1<<(7-j)))
        {
            LS164_DATA(HIGH);
        }
        else
        {
            LS164_DATA(LOW);
        }
        LS164_CLK(LOW);
        LS164_CLK(HIGH);
    }
}
/**********************************************************
*函數(shù)名稱:SegRefreshDisplayBuf
*輸    入:無
*輸    出:無
*功    能:數(shù)碼管刷新顯示緩存
***********************************************************/
void  SegRefreshDisplayBuf(void)
{
     SegBuf[0] = CounterValue%10;
     SegBuf[1] = CounterValue/10%10;
     SegBuf[2] = CounterValue/100%10;
     SegBuf[3] = CounterValue/1000%10;       
}
/**********************************************************
*函數(shù)名稱:SegDisplay
*輸    入:無
*輸    出:無
*功    能:數(shù)碼管顯示數(shù)據(jù)
***********************************************************/
void SegDisplay(void)
{
    UINT8 t;
    SEG_PORT = 0x0F;                                    //熄滅所有數(shù)碼管
  
    if(bSetTime)                                          //檢查是否設(shè)置計(jì)數(shù)值
    {
        if(SegCurSel == SegCurPosMark)
        {
            t = SegCode[SegBuf[SegCurSel]] & 0x7F;        //加上小數(shù)點(diǎn)
        }
        else
        {
            t = SegCode[SegBuf[SegCurSel]];               //正常顯示當(dāng)前數(shù)值
        }
    }
    else
    {
        t = SegCode[SegBuf[SegCurSel]];                       //正常顯示當(dāng)前數(shù)值
    }
  
    LS164Send(t);
    SEG_PORT = SegSelTbl[SegCurSel];                       //點(diǎn)亮當(dāng)前要顯示的數(shù)碼管
    if(++SegCurSel >= 4)
    {
        SegCurSel = 0;
    }  
}
/**********************************************************
*函數(shù)名稱:TimerInit
*輸    入:無
*輸    出:無
*功    能:定時(shí)器初始化
***********************************************************/
void TimerInit(void)
{
    TH0 = (65536 - TIMER0_INITIAL_VALUE)/256;
    TL0 = (65536 - TIMER0_INITIAL_VALUE)%256;
    TMOD = 0x01;
}
/**********************************************************
*函數(shù)名稱:Timer0Start
*輸    入:無
*輸    出:無
*功    能:定時(shí)器啟動(dòng)
***********************************************************/
void Timer0Start(void)
{
    TR0 = 1;
    ET0 = 1;
}
/**********************************************************
*函數(shù)名稱:Timer0Stop
*輸    入:無
*輸    出:無
*功    能:定時(shí)器停止
***********************************************************/
void Timer0Stop(void)
{
    TR0 = 0;
    ET0 = 0;
}
/**********************************************************
*函數(shù)名稱:PortInit
*輸    入:無
*輸    出:無
*功    能:I/O初始化
***********************************************************/
void PortInit(void)
{
    P0 = P1 = P2 = P3 = 0xFF;  
}
/**********************************************************
*函數(shù)名稱:KeyRead
*輸    入:無
*輸    出:當(dāng)前按下的按鍵
*功    能:讀取按鍵值
***********************************************************/
UINT8 KeyRead(void)
{
    //KeyStatus:靜態(tài)變量,保存按鍵狀態(tài)
    //keyCurPress:靜態(tài)變量,保存當(dāng)前按鍵的鍵值
    static UINT8 KeyStatus = KEY_SEARCH_STATUS,KeyCurPress = 0;
    UINT8 KeyValue;
    UINT8 i = 0;

    KeyValue = (~KEY_PORT) & KEY_MASK;

    switch(KeyStatus)
    {
        case KEY_SEARCH_STATUS:                       //按鍵查詢狀態(tài)
        {
            if(KeyValue)
            {
                KeyStatus = KEY_ACK_STATUS;        //按鍵下一個(gè)狀態(tài)為確認(rèn)狀態(tài)  
            }
            return 0;
        }
        break;
      
        case KEY_ACK_STATUS:                    //按鍵確認(rèn)狀態(tài)
        {
            if(!KeyValue)
            {
                KeyStatus = KEY_SEARCH_STATUS;
            }
            else
            {
                for(i=0;i<4;i++)
                {
                    if(KeyValue&(1<<i))
                    {
                        KeyCurPress = KEY1 + i;
                        break;
                    }
                }
                KeyStatus = KEY_REALEASE_STATUS;
            }
            return 0;
        }
        break;

        case KEY_REALEASE_STATUS:                 //按鍵釋放狀態(tài)
        {
            if(!KeyValue)
            {
                KeyStatus = KEY_SEARCH_STATUS;
                return KeyCurPress;
            }
            return 0;
        }
        default:
            return 0;
        break;
    }
}
/**********************************************************
*函數(shù)名稱:main
*輸    入:無
*輸    出:無
*功    能:函數(shù)主題
***********************************************************/
void main(void)
{
    PortInit();
    TimerInit();
    Timer0Start();
    SegRefreshDisplayBuf();
    EA = 1;
    while(1)
    {
        SegRefreshDisplayBuf();
        if(Timer0IRQEvent)
        {
            Timer0IRQEvent = 0;
            switch(KeyRead())
            {
                case KEY1:
                {
                    bSetTime = ~bSetTime;
                    SegCurPosMark = 0;  
                }
                break;

                case KEY2:
                {
                    if(++SegCurPosMark>=4)
                    {
                        SegCurPosMark = 0;
                    }
                }
                break;

                case KEY3:
                {
                    if(!bSetTime)
                        break;
                    if(CounterValue>=9999)
                        CounterValue = 0;
                    if     (SegCurPosMark == 0)
                        CounterValue += 1;
                    else if(SegCurPosMark == 1)
                        CounterValue += 10;
                    else if(SegCurPosMark == 2)
                        CounterValue += 100;
                    else
                        CounterValue += 1000;
                }
                break;

                case KEY4:
                {
                    if(!bSetTime)
                         break;
                    if(CounterValue<=0)
                    CounterValue = 9999;
                    if     (SegCurPosMark == 0)
                        CounterValue -= 1;
                    else if(SegCurPosMark == 1)
                        CounterValue -= 10;
                    else if(SegCurPosMark == 2)
                        CounterValue -= 100;
                    else
                        CounterValue -= 1000;
                }
                break;

                default:
                break;
            }
        }
        else if(Time1SecEvent)
        {
            Time1SecEvent = 0;
            if(!bSetTime)
            {
                 if(++CounterValue>=9999)
                {
                    CounterValue = 0;
                }
            }
        }  
    }
}
/**********************************************************
*函數(shù)名稱:Timer0IRQ
*輸    入:無
*輸    出:無
*功    能:定時(shí)器中斷函數(shù)
***********************************************************/
void Timer0IRQ(void) interrupt 1
{
    TH0 = (65536 - TIMER0_INITIAL_VALUE)/256;
    TL0 = (65536 - TIMER0_INITIAL_VALUE)%256;
    Timer0IRQEvent = 1;

    SegDisplay();

    if(++TimeCount >= 200)
    {
        TimeCount = 0;
        Time1SecEvent = 1;
    }
}
 

關(guān)閉窗口

相關(guān)文章

主站蜘蛛池模板: 国产不卡在线观看 | 最新高清无码专区 | 国产人免费人成免费视频 | 亚洲视频免费在线 | 日本国产高清 | av网站在线看 | 美女视频一区 | 日日欧美 | 完全免费av在线 | 亚洲图片一区二区三区 | 色婷婷一区二区三区四区 | 日本午夜一区二区三区 | www.99re | 伊人99| 北条麻妃一区二区三区在线视频 | 久久精品色欧美aⅴ一区二区 | 国产精品久久久久久婷婷天堂 | 91资源在线 | 久久久夜 | 免费av电影网站 | 中文无吗 | 三级黄色大片网站 | avav在线看| 欧美男人天堂 | 国产麻豆乱码精品一区二区三区 | 久久噜噜噜精品国产亚洲综合 | 欧美久久一区 | 天天弄 | 人妖一区 | 国产精品av久久久久久毛片 | 国产成人精品一区二区三区四区 | 亚洲二区视频 | 久久久新视频 | 人人叉 | 欧美一区二区三区一在线观看 | 国产精品美女久久久久aⅴ国产馆 | 欧美国产精品一区二区 | 91精品国产777在线观看 | 精品成人 | 亚洲人在线观看视频 | 亚洲女人天堂网 |