新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 一個51單片機實現數字時鐘(1602顯示)

        一個51單片機實現數字時鐘(1602顯示)

        作者: 時間:2016-11-17 來源:網絡 收藏
        單片機實現數字時鐘,關于時間顯示,是用的1602液晶,C51單片機,然后再加一個定時器,每到一秒就動態的更新一下液晶的時間顯示,在更新的時候也要計算相應的分針和時針的變化,還要注意邊界問題.為了能夠達到一個最好的效果,我還加了一個鍵盤掃描,用到了3個鍵,分別為功能鍵,增1,減1來實現用戶自定義時間.

        在實現過程中,用到了單片機的中斷系統的相關知識,還有定時器,液晶顯示,鍵盤的動態掃描,都是以前的知識,沒什么難度.
        程序如下,可以正常運行.

        本文引用地址:http://www.104case.com/article/201611/315485.htm

        C代碼
        #i nclude
        #define uint unsigned int
        #define uchar unsigned char

        sbit lcdrs = P1^0;
        sbit lcdrw = P1^1;
        sbit lcden = P1^2;

        sbit key0 = P2^0;//功能鍵,選擇時分秒
        sbit key1 = P2^1;//加1鍵
        sbit key2 = P2^2;//減1鍵
        sbit key4 = P2^4;

        uchar key0_count;//按鍵0被按的次數(0~3)

        char hour,minute,second; //時分秒
        uint timer_count; //定時器中斷計數

        uchar table_date[] = "2009-4-12 Mon";
        uchar table_time[] = "00:00:00";

        /****** 函數申明 ********/
        void write_cmd_1602(uchar cmd);
        void write_data_1602(uchar dat);
        void write_add(uchar add,uchar dat);
        void init1602();
        void delay(uint z);
        uchar reverse(uchar c);
        void keyscan();
        void init();
        /****** 主函數 ********/
        void main()
        {
        init();
        //init1602();
        //while(1);
        while(1)
        {
        keyscan();
        delay(5);
        }
        }
        //1602液晶初始化
        void init1602()
        {
        lcdrw = 0; //本程序只讀不寫,故將其置低
        lcden = 0; //關閉1602
        delay(5);
        write_cmd_1602(0x01); //清屏
        write_cmd_1602(0x38); //顯示模式
        write_cmd_1602(0x0c); //開顯示,不顯示光標,不閃爍
        write_cmd_1602(0x06); //地址指針自動加1
        write_cmd_1602(0x80+1);//將光標指向第一行第二個位置
        delay(5);
        }
        void delay(uint z)
        {
        uint x,y;
        for(x=z;x>0;x--)
        for(y=110;y>0;y--);
        }
        /** 將發送的數據進行翻轉,高位到低位,低位轉到高位 **/
        uchar reverse(uchar c)
        {
        uchar chbuff=0;
        if (c&0x01) chbuff=chbuff|0x80;
        if (c&0x02) chbuff=chbuff|0x40;
        if (c&0x04) chbuff=chbuff|0x20;
        if (c&0x08) chbuff=chbuff|0x10;
        if (c&0x10) chbuff=chbuff|0x08;
        if (c&0x20) chbuff=chbuff|0x04;
        if (c&0x40) chbuff=chbuff|0x02;
        if (c&0x80) chbuff=chbuff|0x01;
        return chbuff;
        }
        //向液晶寫命令
        void write_cmd_1602(uchar cmd)
        {
        lcdrs = 0; //低表示寫命令,高表示寫數據
        delay(5);
        P0 = reverse(cmd);
        delay(5);
        lcden = 1; //給一個高脈沖
        delay(5);
        lcden = 0;
        delay(5);
        }
        //向液晶寫數據
        void write_data_1602(uchar dat)
        {
        lcdrs = 1; //低表示寫命令,高表示寫數據
        delay(5);
        P0 = reverse(dat);
        delay(5);
        lcden = 1; //給一個高脈沖
        delay(5);
        lcden = 0;
        delay(5);
        }
        //根據地址向液晶寫數據
        void write_add(uchar add,uchar dat)
        {
        uchar shi,ge;
        shi = dat/10;
        ge = dat%10;
        delay(5);
        write_cmd_1602(0x80+add);
        write_data_1602(shi+0x30);
        delay(5);
        write_data_1602(ge+0x30);
        }
        //鍵盤掃描函數
        void keyscan()
        {
        key4 = 0;
        if(0==key0) //第一個鍵被按下
        {
        delay(5); //消抖
        if(0==key0)
        {
        key0_count ++;
        if(4==key0_count)
        key0_count = 0;
        while(!key0); //松手檢測
        if(0==key0_count)
        {
        TR0 = 1; //重新開始計時
        write_cmd_1602(0x0c); //禁止顯示光標并不讓其閃爍
        }
        if(1==key0_count)
        {
        TR0 = 0; //暫停計時
        write_cmd_1602(0x80+0x40+11);//將地址指針指向秒的位置
        write_cmd_1602(0x0f); //顯示光標并閃爍
        delay(5);
        }
        if(2==key0_count)
        {
        TR0 = 0; //暫停計時
        write_cmd_1602(0x80+0x40+8);//將地址指針指向分的位置
        write_cmd_1602(0x0f); //顯示光標并閃爍
        delay(5);
        }
        if(3==key0_count)
        {
        TR0 = 0; //暫停計時
        write_cmd_1602(0x80+0x40+5);//將地址指針指向小時的位置
        write_cmd_1602(0x0f); //顯示光標并閃爍
        delay(5);
        }
        }
        }
        if(0==key1) //第二個鍵被按下
        {
        delay(5); //消抖
        if(0==key1)
        {
        while(!key1); //松手檢測
        if(key0_count==1)
        {
        second ++;
        if(60==second)
        second = 0;
        write_add(0x40+10,second);
        }
        if(key0_count==2)
        {
        minute ++;
        if(60==minute)
        minute = 0;
        write_add(0x40+7,minute);
        }
        if(key0_count==3)
        {
        hour ++;
        if(24==hour)
        hour = 0;
        write_add(0x40+4,hour);
        }
        }
        }
        if(0==key2) //第三個鍵被按下
        {
        delay(5); //消抖
        if(0==key2)
        {
        while(!key2); //松手檢測
        if(key0_count==1)
        {
        second --;
        if(-1==second)
        second = 59;
        write_add(0x40+10,second);
        }
        if(key0_count==2)
        {
        minute --;
        if(-1==minute)
        minute = 59;
        write_add(0x40+7,minute);
        }
        if(key0_count==3)
        {
        hour --;
        if(-1==hour)
        hour = 23;
        write_add(0x40+4,hour);
        }
        }
        }

        }
        //程序初始化函數
        void init()
        {
        uchar i;
        hour = 0;
        minute = 0;
        second = 0;
        key0_count = 0;
        init1602();
        delay(20); //延長時間,確保液晶處于非忙狀態
        for(i=0;i<14;i++)
        {
        write_data_1602(table_date[i]);
        delay(5);
        }
        write_cmd_1602(0x80+0x40+4); //調整地址指針
        for(i=0;i<8;i++)
        {
        write_data_1602(table_time[i]);
        delay(5);
        }
        //初始化定時器
        TMOD = 0x01; //定時器模式
        TH0 = (65536-50000)/256; //裝初值
        TL0 = (65536-50000)%256;
        EA = 1;//開總中斷
        ET0 = 1;//開定時器0中斷
        TR0 = 1; //啟動定時器,此時開始計時
        }
        void timer0() interrupt 1 //定時器0的中斷處理函數
        {
        TH0 = (65536-50000)/256; //裝初值
        TL0 = (65536-50000)%256;
        timer_count ++;
        if(20==timer_count) //到了1秒更新時分秒的顯示
        {
        timer_count = 0; //中斷次數清0,重新計數
        second ++; //秒針加1
        if(second==60)
        {
        second = 0;
        minute ++; //分針加1
        if(60==minute)
        {
        minute = 0;
        hour ++; //小時加1
        if(24==hour)
        {
        hour = 0;
        }
        write_add(0x40+4,hour);
        }
        write_add(0x40+7,minute); //更新分針的顯示
        }
        write_add(0x40+10,second); //更新秒針
        }
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 淳安县| 瑞安市| 衢州市| 教育| 邹城市| 惠安县| 阿鲁科尔沁旗| 中宁县| 山西省| 镇巴县| 长子县| 白城市| 杭锦旗| 辛集市| 湟源县| 普兰县| 方城县| 岱山县| 锡林浩特市| 清丰县| 阿拉善左旗| 襄垣县| 大英县| 平江县| 恭城| 正阳县| 昭觉县| 行唐县| 安吉县| 绥江县| 长治市| 铅山县| 黔西县| 山西省| 南澳县| 六盘水市| 汪清县| 洛宁县| 定南县| 嵊州市| 容城县|