<acronym id="xonnx"></acronym>
      <td id="xonnx"></td>
    1. <pre id="xonnx"></pre>

      1. 專注電子技術學習與研究
        當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

        單片機開源項目之Stopwatch數碼管顯示-實用秒表

        作者:寒竹子   來源:本站原創   點擊數:  更新時間:2014年05月02日   【字體:

        此程序是在51hei單片機開發板上面做的,如需要移植到自己的電路上,修改相應的端口即可,開發板完整的電路圖下載:  點這里 (注意:只需要看相關部分即可,其他部分可以忽略)

        /**
          ****************************************************************************************
          *file   :   main.c
          *author :   xr
          *date   :   2014年4月15日10:08:26 - 2014年4月15日12:40:51
          *version:   V1.2.3
          *brief  :   Stopwatch數碼管顯示-實用秒表   單片機STC89C52RC MCU 晶振 11.0592MHZ
          ****************************************************************************************
          */
        #include <reg52.h>

        //74HC138
        sbit ADDR0 = P1^0;
        sbit ADDR1 = P1^1;
        sbit ADDR2 = P1^2;
        sbit ADDR3 = P1^3;
        sbit ENLED = P1^4;
        //矩陣按鍵
        sbit KEY_IN_1 = P2^4;//列
        sbit KEY_IN_2 = P2^5;
        sbit KEY_IN_3 = P2^6;
        sbit KEY_IN_4 = P2^7;
        //數碼管編碼
        unsigned char code LedTable[] = {
            0xC0,  //"0"
                        0xF9,  //"1"
                        0xA4,  //"2"
                        0xB0,  //"3"
                        0x99,  //"4"
                        0x92,  //"5"
                        0x82,  //"6"
                        0xF8,  //"7"
                        0x80,  //"8"
                        0x90,  //"9"
                        0x88,  //"A"
                        0x83,  //"B"
                        0xC6,  //"C"
                        0xA1,  //"D"
                        0x86,  //"E"
                        0x8E   //"F"
           };
        //數碼管顯示緩沖區
        unsigned char LedBuff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
        bit flag10ms = 0;//10ms標志位
        bit stopwatchRunning = 0;//秒表啟動和停止標志
        unsigned char thr0, tlr0;//T0重載值的高低字節
        unsigned char decimal = 0;//小數位
        unsigned int  integer = 0;//整數位
        static unsigned char volatile KeySta[4] = {1, 1, 1, 1}; //保存按鍵的當前值(static 保存在靜態存儲區,加上volatile關鍵字使KeySta[i]的值每次都從靜態存儲區讀取,避免讀取錯誤!)
        /****************function definition**********************/
        void Initial();
        void ConfigTimer0(unsigned long xms);
        void StopwatchDisplay();
        void KeyAction();
        /*主程序main()*/
        void main(void)
        {
         Initial();
         ConfigTimer0(1);//定時1ms
         while (1)
         {
          KeyAction();       //檢測按鍵動作
          if (flag10ms)      //10ms檢測秒表的運行狀態,當stopwatchRunning標志=1時進行計時++,否則就停止計時
          {
           flag10ms = 0;
           if (stopwatchRunning)  //10ms刷新秒表計數
           {
            decimal++;
            if (decimal >= 100)
            {
             decimal = 0;
             integer++;
             if (integer >= 10000)
             {
              integer = 0;
             }
            }
            StopwatchDisplay();//分解decimal和integer,存入LedBuff數碼管緩沖區 
           }
          }
         }
        }
        /*程序初始化*/
        void Initial()
        {
         ADDR3 = 1;
         ENLED = 0;//選擇數碼管
         P2 = 0xFE;  //選擇第四行按鍵檢測(原理圖上是第四列)
         P0 = 0xFF;//默認關閉段選
         LedBuff[0] = LedTable[decimal % 10];  //初始顯示0.00
         LedBuff[1] = LedTable[decimal / 10 % 10];
         LedBuff[2] = LedTable[integer % 10];
         LedBuff[2] &= 0x7F;//點亮小數點
        }
        /*配置定時器T0*/
        void ConfigTimer0(unsigned long xms)
        {
         unsigned long tmp;//32bit 注意:此處必須用unsigned long 數據,因為11059200已經超出了16位unsigned int
         tmp = 11059200/12;//單片機的機器周期頻率
         tmp = (tmp * xms) / 1000;//定時xms所需的頻率
         tmp = 65536-tmp;//定時xms的初始裝載值
         tmp += 18;  //補償值
         thr0 = (unsigned char)(tmp >> 8);
         tlr0 = (unsigned char)tmp;
         TMOD &= 0xF0;//清零T0控制位
         TMOD |= 0x01;//配置T0工作在方式1,16位可設定定時器
         TH0 = thr0;
         TL0 = tlr0;
         TR0 = 1;
         ET0 = 1;
         EA  = 1;  
        }
        /*數碼管刷新*/
        void LedCharRefresh()
        {
         static unsigned char j = 0;
         P0 = 0xFF;//消隱
         P1 = (P1 & 0xF8) | j;//先清零P1口低三位,再|j
         P0 = LedBuff[j++];
         if (j > 5)
          j = 0;
        }
        /*分解decimal和integer,存入LedBuff數碼管緩沖區*/
        void StopwatchDisplay()
        {
         signed char i = 0;
         unsigned char buf[6];
         buf[0] = decimal % 10;
         buf[1] = decimal / 10 % 10;
         buf[2] = integer % 10;
         buf[3] = integer / 10 % 10;
         buf[4] = integer / 100 % 10;
         buf[5] = integer / 1000 % 10;
         for (i = 5; i >= 3; i--)    //去掉無效位
         {
          if (buf[i] == 0)
           buf[i] = 0xFF;
          else
           break;
         }
         //處理有效位
         for (; i >=0; i--)
         {
          buf[i] = LedTable[buf[i]]; //轉為實際的數字
         }
         //拷貝
         for (i = 0; i <= 5; i++)
         {
          LedBuff[i] = buf[i];//拷貝到顯示緩沖區
         }
         LedBuff[2] &= 0x7F;//點亮小數點
        }
        /*秒表啟動和停止*/
        void StopwatchAction()
        {
         if (stopwatchRunning)   //當前狀態為運行
         {
          stopwatchRunning = 0;  //停止運行
         }
         else
         {
          stopwatchRunning = 1;  //啟動
         }
        }
        /*秒表復位*/
        void StopwatchReset()
        {
         stopwatchRunning = 0;//停止秒表計時
         decimal = 0;
         integer = 0;//清零
         StopwatchDisplay();//顯示
        }
        /*按鍵動作*/
        void KeyAction()
        {
            static unsigned char keybackup[4] = {1, 1, 1, 1};//按鍵的備份值(前一次按鍵值) 必須是靜態的
         unsigned char i = 0;
         for (i = 0; i < 4; i++)
         {
          if (keybackup[i] != KeySta[i])  //按鍵的上一次的狀態和當前狀態不相同,即按鍵有動作
          {
           if (keybackup[i] != 0) //如果上一次按鍵的值是1,則此時按鍵是按下動作
           {
            switch (i)
            {
             case 1: StopwatchReset();  break;   //ESC鍵秒表復位
             case 2: StopwatchAction(); break; //Enter鍵控制秒表的啟動和停止
             default: break;
            }
           }
           keybackup[i] = KeySta[i];//備份當前按鍵值
          }
         }
        }
        /*按鍵掃描函數*/
        void KeyScan()
        {
         static unsigned char KeyBuf[4] = {0xFF, 0xFF, 0xFF, 0xFF}; //按鍵掃描緩沖區
         unsigned char i = 0;
         
         //檢測一行按鍵的狀態并存入按鍵檢測緩沖區中
         KeyBuf[0] = (KeyBuf[0] << 1) | KEY_IN_1;
         KeyBuf[1] = (KeyBuf[1] << 1) | KEY_IN_2;
         KeyBuf[2] = (KeyBuf[2] << 1) | KEY_IN_3;
         KeyBuf[3] = (KeyBuf[3] << 1) | KEY_IN_4;
         //更新消抖后按鍵的值(1ms檢測一次,8ms檢測)
         for (i = 0; i < 4; i++)
         {
          if ((KeyBuf[i] & 0xFF) == 0x00)
           KeySta[i] = 0;//8次檢測按鍵狀態都是0,即按鍵穩定按下
          else if ((KeyBuf[i] & 0xFF) == 0xFF)
           KeySta[i] = 1;//8次檢測按鍵的狀態都是1,即按鍵穩定彈起
         }
        }
        /*定時器Timer0中斷服務*/
        void Timer0_ISP() interrupt 1
        {
         static unsigned char counter = 0;//計數器
         TH0 = thr0;
         TL0 = tlr0;//重新裝載定時器初值
         counter++;
         LedCharRefresh();//數碼管刷新
         KeyScan();   //按鍵掃描
         if (counter >= 10)
         {
          counter = 0;
          flag10ms = 1;
         }
        }
        關閉窗口

        相關文章

        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮