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

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

        LCD1602液晶秒表C51程序

        作者:寒竹子   來源:用戶上傳   點擊數:  更新時間:2014年05月18日   【字體:

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

        /**

          ***********************************************************************
          * @file     main.c
          * @author   xr
          * @date     2014年5月8日22:11:33 -- 2014年5月9日12:03:49
          * @version  V1.2.3
          * @brief    LCD1602液晶跑表  單片機STC89C52RC MCU 晶振 11.0592MHZ
          ***********************************************************************
          */
          
        #include <reg52.h>
         
        /* 系統時鐘 */
        #define SYS_XTAL (11059200UL/12)
         
        /* 定時器T0重載值 */
        unsigned char thr0, tlr0;
        unsigned char thr1, tlr1;
        /* 跑表計數 */
        unsigned char timer[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; //分別表示跑表的各個位上的數字
        bit flag10ms = 0;
        extern bit stopflag;//跑表走停標志位
         
        extern void InitalLCD1602();
        extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);
        extern void KeyDriver();
        extern void KeyScan();
         
        void DisplayTimer();
        void ConfigTimer0(unsigned int xms);
        void ConfigTimer1(unsigned int xms);
         
        /* 主函數main() */
        void main(void)
        {  
            ConfigTimer0(10);                    //定時10ms
            ConfigTimer1(1);
            InitalLCD1602();
            
            LcdShowStr(0, 0, "stopwatch");
            LcdShowStr(2, 1, "0000000.00s");     //液晶初始化顯示
            LcdShowStr(10, 0, "stop!");
            
            while (1)
            {
                KeyDriver();
                DisplayTimer();
                
                if ((flag10ms == 1) && (stopflag == 1))
                {
                    flag10ms = 0;
                    timer[0]++;
                    if (timer[0] > 9)
                    {
                        timer[0] = 0;
                        timer[1]++;
                        if (timer[1] > 9)
                        {
                            timer[1] = 0;
                            timer[2]++;
                            if (timer[2] > 9)
                            {
                                timer[2] = 0;
                                timer[3]++;
                                if (timer[3] > 9)
                                {
                                    timer[3] = 0;
                                    timer[4]++;
                                    if (timer[4] > 9)
                                    {
                                        timer[4] = 0;
                                        timer[5]++;
                                        if (timer[5] > 9)
                                        {
                                            timer[5] = 0;
                                            timer[6]++;
                                            if (timer[6] > 9)
                                            {
                                                timer[6] = 0;
                                                timer[7]++;
                                                if (timer[7] > 9)
                                                {
                                                    timer[7] = 0;
                                                    timer[8]++;
                                                    if (timer[8] > 9)
                                                    {
                                                        timer[8] = 0;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
         
        /* 將跑表時間顯示到液晶上 */
        void DisplayTimer()
        {
            unsigned char str[20];
            /* 分解timer */
            str[0] = timer[8] + '0';
            str[1] = timer[7] + '0';
            str[2] = timer[6] + '0';
            str[3] = timer[5] + '0';
            str[4] = timer[4] + '0';
            str[5] = timer[3] + '0';
            str[6] = timer[2] + '0';
            str[7] = '.';
            str[8] = timer[1] + '0';
            str[9] = timer[0] + '0';
            str[10] = '\0';
            LcdShowStr(2, 1, str);
        }
         
        /* 定時器T0配置 */
        void ConfigTimer0(unsigned int xms)
        {
            unsigned long tmp;
            tmp = (SYS_XTAL * xms) / 1000;
            tmp = 65536-tmp + 18;
            thr0 = (unsigned char)(tmp >> 8) ;
            tlr0 = (unsigned char)tmp;
            TMOD &= 0xF0;                   //清零T0控制位
            TMOD |= 0x01;                   //定時器方式1
            TH0 = thr0;
            TL0 = tlr0;
            TR0 = 1;                        //開啟timer0
            ET0 = 1;                        //開啟T0中斷
            EA  = 1;                        //開啟總中斷
        }
         
        /* 配置定時器T1 */
        void ConfigTimer1(unsigned int xms)
        {
            unsigned long tmp;
            tmp = (SYS_XTAL * xms) / 1000;
            tmp = 65536 - tmp + 18;
            thr1 = (unsigned char)(tmp >> 8);
            tlr1 = (unsigned char)tmp;
            TMOD &= 0x0F;
            TMOD |= 0x10;
            TH1 = thr1;
            TL1 = tlr1;
            TR1 = 1;
            ET1 = 1;
            EA  = 1;
        }
         
        /* 定時器T0中斷服務 */
        void Timer0_ISP() interrupt 1
        {   
            TH0 = thr0;
            TL0 = tlr0;
            flag10ms = 1; //定時10ms
        }
         
        /* 定時器T1中斷服務 */
        void Timer1_ISP() interrupt 3
        {
            TH1 = thr1;
            TL1 = tlr1; //定時1ms  
            KeyScan();
        }
         
         /**
          ***********************************************************************
          * @file     Lcd1602.c
          * @author   xr
          * @date     2014年5月7日13:33:17
          * @version  V1.2.3
          * @brief    LCD1602液晶底層驅動
          ***********************************************************************
          */
          
        #include <reg52.h>
         
        //LCD1602_IO
        sbit LCD1602_RS = P1^0;
        sbit LCD1602_RW = P1^1;
        sbit LCD1602_EN = P1^5;
         
        #define LCD1602_DB P0
         
        /* 液晶忙碌等待 */
        void LCD1602Wait()
        {
            unsigned char sta;
            LCD1602_DB = 0xFF;//總線拉高,檢測液晶狀態字
            
            LCD1602_RS = 0;
            LCD1602_RW = 1;
            
            do
            {
                LCD1602_EN = 1;
                sta = LCD1602_DB;
                LCD1602_EN = 0;//避免液晶輸出數據
            } while (sta & 0x80);//狀態字最高位STA7 == 0空閑,1忙碌
        }
         
        /* 液晶寫命令 */
        void LCD1602WriteCmd(unsigned char cmd)
        {
            LCD1602Wait();
            
            LCD1602_RS = 0;
            LCD1602_RW = 0;
            LCD1602_EN = 0;
            LCD1602_DB = cmd;
            LCD1602_EN = 1;
            LCD1602_EN = 0;
        }
         
        /* 液晶寫數據 */
        void LCD1602WriteData(unsigned char dat)
        {
            LCD1602Wait();
            
            LCD1602_RS = 1;
            LCD1602_RW = 0;
            LCD1602_EN = 0;
            LCD1602_DB = dat;
            LCD1602_EN = 1;
            LCD1602_EN = 0;
        }
         
        /* 液晶初始化 */
        void InitalLCD1602()
        {
            LCD1602WriteCmd(0x38);
            LCD1602WriteCmd(0x0C);
            LCD1602WriteCmd(0x06);
            LCD1602WriteCmd(0x01);//清屏
        }
         
        /* 寫數據到液晶上,字符串str,坐標(x, y),地址addr */
        void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str)
        {
            unsigned char addr;
            
            if (y == 0)
            {
                addr = 0x00 + x;
            }
            else
            {
                addr = 0x40 + x;
            }
            LCD1602WriteCmd(addr | 0x80);
            while (*str != '\0')
            {
                LCD1602WriteData(*str++);
            }
        }
         
         /**
          ***********************************************************************
          * @file     keyboard.c
          * @author   xr
          * @date     2014年5月8日22:11:33 -- 2014年5月9日12:03:49
          * @version  V1.2.3
          * @brief    按鍵驅動  單片機STC89C52RC MCU 晶振 11.0592MHZ
          ***********************************************************************
          */
          
        #include <reg52.h>
         
        /* 按鍵輸出輸入端口定義 */
        sbit KEY_IN1 = P2^4;
        sbit KEY_IN2 = P2^5;
        sbit KEY_IN3 = P2^6;
        sbit KEY_IN4 = P2^7;
        sbit KEY_OUT1 = P2^3;
        sbit KEY_OUT2 = P2^2;
        sbit KEY_OUT3 = P2^1;
        sbit KEY_OUT4 = P2^0;
         
        extern unsigned char timer[9]; //分別表示跑表的各個位上的數字
        /* 按鍵當前狀態 */
        unsigned char volatile keySta[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
        /* 按鍵對應標準PC鍵盤編碼 */
        const unsigned char code keyCodeMap[4][4] = {
                                         {'1', '2', '3', 0x26},   /* 數字鍵 1, 2, 3 和 向上鍵 */
                                         {'4', '5', '6', 0x25},   /* 數字鍵 4, 5, 6 和 向左鍵 */
                                         {'7', '8', '9', 0x28},   /* 數字鍵 7, 8, 9 和 向下鍵 */
                                         {'0', 0x1B, 0x0D, 0x27}  /* 數字鍵 0 和 向右鍵 */
                            };
         
        bit stopflag = 0;//跑表走停標志位 0 停止,1運行
                            
        void KeyAction(unsigned char keycode);
        void LcdShowStr(unsigned char x, unsigned char y, unsigned char * str);
                            
        /* 按鍵驅動函數 */
        void KeyDriver()
        {
            /* 上一次按鍵的備份值 */
            static unsigned char keybackup[4][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
            unsigned char i, j;
         
            for (i = 0; i < 4; i++)
            {
                for (j = 0; j < 4; j++)
                {
                    if (keySta[i][j] != keybackup[i][j])  //當前按鍵狀態和上一次的按鍵狀態不同
                    {  //按鍵有動作
                        if (keybackup[i][j] != 0) //上一次按鍵是彈起
                        {
                            KeyAction(keyCodeMap[i][j]); //當前按鍵是想、按下
                        }
                        keybackup[i][j] = keySta[i][j]; //備份當前按鍵值
                    }
                }
            }
        }    
         
        /* 按鍵掃描函數 */
        void KeyScan()
        {
           unsigned char i = 0;
           static unsigned char keyout = 0;//按鍵行索引
           static unsigned char keybuf[4][4] = {{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}, 
                                                {0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}        
                                                };
           /* 按鍵消抖 */
           keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN1;
           keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN2;
           keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN3;
           keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN4;
           
           /* 更新按鍵的值 */
           for (i = 0; i < 4; i++)
           {
                if ((keybuf[keyout][i] & 0x1F) == 0x1F)
                {
                    //五次檢測按鍵的值都是1
                    keySta[keyout][i] = 1;
                }
                else if ((keybuf[keyout][i] & 0x1F) == 0x00)
                {
                    //五次檢測的按鍵值都是0
                    keySta[keyout][i] = 0;
                }
           }
           /* 按鍵行索引++ */
           keyout++;
           keyout &= 0x03;//到4歸零
           /* 根據按鍵索引選擇行按鍵進行掃描 */
           switch (keyout)
           {
               case 0: KEY_OUT1 = 0; KEY_OUT4 = 1;//選擇第一行按鍵
               case 1: KEY_OUT2 = 0; KEY_OUT1 = 1;
               case 2: KEY_OUT3 = 0; KEY_OUT2 = 1;
               case 3: KEY_OUT4 = 0; KEY_OUT3 = 1;
               default: break;
           }
        }
         
        /* 按鍵動作函數 */
        void KeyAction(unsigned char keycode)
        {
            unsigned char i = 0;
            
            if (keycode == 0x1B)       //ESC
            {
                /* 跑表復位 */
                stopflag = 0;
                for (i = 0; i < 9; i++)
                {
                    timer[i] = 0;
                }
                LcdShowStr(2, 1, "0000000.00s");
                LcdShowStr(10, 0, "reset!");
            }
            else if (keycode == 0x0D)  //回車鍵 跑表走停
            {
                if (stopflag == 0)
                {
                    stopflag = 1;
                    LcdShowStr(10, 0, "start!");
                }
                else
                {
                    stopflag = 0;
                    LcdShowStr(10, 0, "stop! "); //多寫入一個空格
                }
            }
        }
         
        關閉窗口
        欧美性色欧美精品视频,99热这里只有精品mp4,日韩高清亚洲日韩精品一区二区,2020国自产拍精品高潮