新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機學習——用ds1302制作一個精密電子鐘,按鍵調節

        單片機學習——用ds1302制作一個精密電子鐘,按鍵調節

        作者: 時間:2016-11-23 來源:網絡 收藏
        題目:用ds1302制作一個精密的電子時鐘,且實現按鍵調節時間

        解決方案:

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

        #include
        #include
        #define uchar unsigned char
        #define uint unsigned int
        #define DEC2BCD(X) ((X/10)<<4 | (X%10)) //用于將十進制轉成BCD碼的宏
        #define BCD2DEC(X) (((X&0x70)>>4)*10 + (X&0x0F)) //用于將BCD碼轉成十進制的宏
        void write_com(uchar com);
        void write_data(uchar dat);
        void init();
        void write_time(uchar add,uchar dat);
        void write_riqi(uchar add,uchar dat);
        void write_xingqi(uchar dat);
        void write_byte(uchar dat);
        uchar read_byte();
        void s_write(uchar add,uchar dat);
        void s_write(uchar add,uchar dat);
        uchar s_read(uchar add);
        void set_ds1302(uchar *pClock);
        void rw_ds1302();
        void keyscan();

        uchar data table[]="2009-01-01 Mon.";
        uchar data table1[]=" 00:00:00";
        uchar code xingqi[]="Mon. Tue. Wed. Thu. Fri. Sat. Sun.";
        uchar code time[]={0x00,0x00,0x00,0x06,0x09,0x07,0x09};//sec,min,hour,date,month,week,year
        uchar data time1[]={0x00,0x00,0x00,0x06,0x09,0x07,0x09};//sec,min,hour,date,month,week,year
        uchar hour,min,sec,week,day,month,year,num,sfcount,flag;
        sbit ds1302_sclk=P1^4;
        sbit ds1302_io=P1^5;
        sbit ds1302_ce=P2^2;
        sbit acc0=ACC^0;
        sbit acc7=ACC^7;
        sbit lcdrs=P1^7; //端口定義
        sbit lcdrw=P1^6;
        sbit lcde=P2^4;
        sbit le=P3^6;
        sbit leden=P2^5;
        sbit dkle=P3^7;
        sbit beep=P2^7;
        sbit sf=P1^0;
        sbit sup=P1^1;
        void delay(uint a);
        void keyscan();

        void main()//main函數
        {
        s_write(0x8e,0x80);
        init();
        P0=0xff;
        while(1)
        {
        keyscan();
        if(flag==0){
        rw_ds1302();
        }


        }
        }

        void write_byte(uchar dat)//寫入一個字節
        {
        uchar i;
        ACC=dat;
        for(i=8;i>0;i--)
        {
        ds1302_io=acc0;
        ds1302_sclk=1;
        ds1302_sclk=0;
        ACC=ACC>>1;
        }
        }
        uchar read_byte() //讀出一個字節
        {
        uchar i;
        for(i=8;i>0;i--)
        {
        ACC=ACC>>1;
        acc7=ds1302_io;
        ds1302_sclk=1;
        ds1302_sclk=0;
        }
        return(ACC);
        }

        void s_write(uchar add,uchar dat)//單字節寫入子函數
        {
        ds1302_ce=0;
        ds1302_sclk=0;
        ds1302_ce=1;
        write_byte(add);
        write_byte(dat);
        ds1302_sclk=1;
        ds1302_ce=0;
        }
        uchar s_read(uchar add) //單字節讀出子函數
        {
        uchar temp;
        ds1302_ce=0;
        ds1302_sclk=0;
        ds1302_ce=1;
        write_byte(add);
        temp=read_byte();
        ds1302_sclk=1;
        ds1302_ce=0;

        temp=BCD2DEC(temp);

        return(temp);
        }
        void set_ds1302(uchar *pClock)//設置ds1302的時間
        {
        uchar i;
        uchar add=0x80;
        EA=0;
        s_write(0x8e,0x00);
        for(i=7;i>0;i--)
        {
        s_write(add,*pClock);
        pClock++;
        add+=2;
        }
        s_write(0x8e,0x80);
        EA=1;
        }
        void rw_ds1302() //讀寫ds1302
        {
        EA=0;
        sec=s_read(0x81);
        write_time(8,sec);
        write_com(0x80+0x40+9);
        min=s_read(0x83);
        write_time(5,min);
        write_com(0x80+0x40+6);
        hour=s_read(0x85);
        write_time(2,hour);
        write_com(0x80+0x40+3);
        week=s_read(0x8b);
        write_xingqi(week);
        write_com(0x80+0x0d);
        day=s_read(0x87);
        write_riqi(8,day);
        write_com(0x80+9);
        month=s_read(0x89);
        write_riqi(5,month);
        write_com(0x80+6);
        year=s_read(0x8d);
        write_riqi(2,year);
        write_com(0x80+3);
        EA=1;
        }
        void write_com(uchar com) //寫命令子函數
        {
        lcde=0;
        lcdrw=0;
        lcdrs=0;
        delay(1);
        lcde=1;
        delay(1);
        P0=com;
        delay(1);
        lcde=0;
        }
        void write_data(uchar dat)//寫數據子函數
        {
        lcde=0;
        lcdrw=0;
        lcdrs=1;
        delay(1);
        lcde=1;
        delay(1);
        P0=dat;
        delay(1);
        lcde=0;
        }
        void init()
        {
        s_write(0x90,0xa5);
        set_ds1302(time);
        delay(5);
        lcde=0; //LCD1602初始化
        le=0;
        leden=0;
        write_com(0x38);
        delay(100);
        write_com(0x38);
        delay(50);
        write_com(0x38);
        delay(10);
        write_com(0x08);
        write_com(0x01);
        write_com(0x0c);
        write_com(0x80);

        for(num=0;num<15;num++) //在第一行顯示“ 2000-00-00 Mon.”
        {
        write_data(table[num]);
        }
        write_com(0x80+0x40);
        for(num=0;num<10;num++) //在第二行末尾顯示“ 00:00:00”
        {
        write_data(table1[num]);
        }

        }
        void write_time(uchar add,uchar dat) //寫入時間子函數
        {
        uchar shi,ge;
        shi=dat/10;
        ge=dat%10;
        write_com(0x80+0x40+add);
        write_data(0x30+shi);
        write_data(0x30+ge);
        }
        void write_riqi(uchar add,uchar dat) //寫入日期子函數
        {
        uchar shi,ge;
        shi=dat/10;
        ge=dat%10;
        write_com(0x80+add);
        write_data(0x30+shi);
        write_data(0x30+ge);
        }
        void write_xingqi(uchar dat) //寫入星期子函數
        {
        write_com(0x80+0x0b);
        switch(dat)
        {
        case 1: for(num=0;num<4;num++)
        {
        write_data(xingqi[num]);
        };break;
        case 2: for(num=5;num<9;num++)
        {
        write_data(xingqi[num]);
        };break;
        case 3: for(num=10;num<14;num++)
        {
        write_data(xingqi[num]);
        };break;
        case 4: for(num=15;num<19;num++)
        {
        write_data(xingqi[num]);
        };break;
        case 5: for(num=20;num<24;num++)
        {
        write_data(xingqi[num]);
        };break;
        case 6: for(num=25;num<29;num++)
        {
        write_data(xingqi[num]);
        };break;
        case 7: for(num=30;num<34;num++)
        {
        write_data(xingqi[num]);
        };break;

        }
        }
        void keyscan() //按鍵掃描子函數
        {
        if(sf==0)//功能鍵
        {
        delay(2);
        if(sf==0)
        {
        while(!sf);

        sfcount++;
        if(sfcount==1) //秒針閃爍
        {
        flag=1;
        s_write(0x80,0x80);//使時鐘暫停
        write_com(0x80+0x40+9);
        write_com(0x0f);
        }
        if(sfcount==2) //分針閃爍
        {
        write_com(0x80+0x40+6);
        }
        if(sfcount==3) //時針閃爍
        {
        write_com(0x80+0x40+3);
        }
        if(sfcount==4) //星期閃爍
        {
        write_com(0x80+0x0d);
        }
        if(sfcount==5)//天閃爍
        {
        write_com(0x80+9);
        }
        if(sfcount==6)//月閃爍
        {
        write_com(0x80+6);
        }
        if(sfcount==7)//年閃爍
        {
        write_com(0x80+3);
        }
        if(sfcount==8)//取消閃爍
        {
        sfcount=0;
        flag=0;
        set_ds1302(time1);
        delay(5);
        write_com(0x0c);
        s_write(0x80,0x00);//使時鐘啟動
        }
        }
        }
        if(sup==0) //調節時間(上升鍵)
        {
        delay(5);
        if(sup==0)
        {
        while(!sup);
        if(sfcount==1)//調節秒
        {
        sec++;
        if(sec==60)
        sec=0;
        time1[0]=DEC2BCD(sec);
        write_time(8,sec);
        write_com(0x80+0x40+9);
        }
        if(sfcount==2) //調節分鐘
        {
        min++;
        if(min==60)
        min=0;
        time1[1]=DEC2BCD(min);
        write_time(5,min);
        write_com(0x80+0x40+6);
        }
        if(sfcount==3) //調節小時
        {
        hour++;
        if(hour==24)
        hour=0;
        time1[2]=DEC2BCD(hour);
        write_time(2,hour);
        write_com(0x80+0x40+3);
        }
        if(sfcount==4) //調節星期
        {
        week++;
        if(week==8)
        week=1;
        time1[5]=week;
        write_xingqi(week);
        write_com(0x80+0x0d);
        }
        if(sfcount==5) //調節日
        {
        day++;
        if(day==32)
        day=1;
        time1[3]=DEC2BCD(day);
        write_riqi(8,day);
        write_com(0x80+9);
        }
        if(sfcount==6) //調節月
        {
        month++;
        if(month==13)
        month=1;
        time1[4]=DEC2BCD(month);
        write_riqi(5,month);
        write_com(0x80+6);
        }
        if(sfcount==7) //調節年
        {
        year++;
        if(year==100)
        year=9;
        time1[6]=DEC2BCD(year);
        write_riqi(2,year);
        write_com(0x80+3);
        }
        }
        }
        }
        void delay(uint a) { //1ms延時子函數
        uint i,j;
        for(j=a;j>0;j--)
        for(i=250;i>0;i--) ;
        }



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 安岳县| 恩施市| 浪卡子县| 东平县| 长葛市| 资溪县| 泉州市| 德钦县| 武平县| 宣恩县| 体育| 建始县| 茶陵县| 牡丹江市| 海南省| 太白县| 庄浪县| 固安县| 延庆县| 长海县| 抚州市| 公主岭市| 佛山市| 康定县| 宜昌市| 荔浦县| 德安县| 托克托县| 大同市| 凤山县| 三河市| 昭平县| 双辽市| 三台县| 乐平市| 水城县| 酉阳| 汤原县| 获嘉县| 兴仁县| 大同县|