新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 單片機·實時時鐘DS1302

        單片機·實時時鐘DS1302

        作者: 時間:2016-11-24 來源:網絡 收藏
        一、實時時鐘DS1302的簡介
        DS1302的在實時顯示時間中的應用。它可以對年、月、日、周、時、分、秒進行計時,且具有閏年補償等多種功能。
        Vcc2:電源
        Vcc1:后備電源,斷電后可以繼續工作
        GND:電源地
        X1,X2:振蕩源,外接32.768kHz晶振
        RST:片選信號
        SCLK:讀寫控制字節
        I/O:串行數據輸入輸出
        2. DS1302的控制字節
        bit7:必須是1,否則不能寫入數據 (可以類比LCD1602檢測忙閑)
        bit6:0,存儲時鐘數據;1,存儲RAM數據
        bit1-5:指示操作單元的地址
        bit0:0,表示寫;1,表示讀
        控制字節從低位開始輸出

        寫保護 8EH 8FH
        下面附一張英文表,感覺比中文的全面一點,就是難看

        3.數據流(可參照時序)
        1)RST=1時,DS1302才可被寫入數據,才可被操作;RST=0時,DS1302會終止數據傳輸,變為高阻狀態;
        2)SCK上升沿讀地址,SCK下降沿讀數據;
        3)控制字節輸入后下一個SCLK時鐘的上升沿時,數據被寫入DS1302,從低位開始。
        控制字節輸入后下一個SCLK時鐘的下降沿時,數據被讀出DS1302,從低位開始。
        二、實驗
        程序1:用DS1302實現時鐘計時
        main.h
        # ifndef _MAIN_H_
        # define _MAIN_H_
        # include
        # include
        sbit SCK = P3^5 ;
        sbit SDA = P3^4 ;
        sbit RST = P1^7 ;
        typedef unsigned char uint8 ;
        typedef unsigned int uint16 ;
        uint8 time[7]={50,59,23,15,8,7,10} ;
        # define ds1302_w_addr 0x80
        # define ds1302_r_addr 0x81
        # endif
        main.c
        # include "main.h"
        void delay(uint16 n)
        {
        while(n--) ;
        }
        void reset_ds1302(void)
        {
        RST = 0 ;
        SCK = 0 ;
        RST = 1 ;
        }
        void write_ds1302_byte(uint8 dat)
        {
        uint8 i ;
        for(i=0; i<8; i++)
        {
        SDA = dat&0x01 ;
        dat>>=1 ;
        SCK = 1 ;
        SCK = 0 ;
        }
        }
        uint8 read_ds1302_byte(void)
        {
        uint8 i,dat=0 ;
        for(i=0; i<8; i++)
        {
        dat>>=1 ;
        if(SDA)
        dat |= 0x80 ;
        SCK = 1 ; //這里注意SCK = 1 ,SCK = 0必須連寫,不然會導致輸出出錯,不知原因
        SCK = 0 ;
        }
        return dat ;
        }
        void clear_ds1302_wp(void)
        {
        reset_ds1302() ;
        RST = 1 ;
        write_ds1302_byte(0x8E) ;
        write_ds1302_byte(0) ;
        SDA = 0 ;
        RST = 0 ;
        }
        void set_ds1302_wp(void)
        {
        reset_ds1302() ;
        RST = 1 ;
        write_ds1302_byte(0x8E) ;
        write_ds1302_byte(0x80) ;
        SDA = 0 ;
        RST = 0 ;
        }
        void write_ds1302(uint8 addr, uint8 dat)
        {
        reset_ds1302() ;
        RST = 1 ;
        write_ds1302_byte(addr) ;
        write_ds1302_byte(dat) ;
        SDA = 0 ;
        RST = 0 ;
        }
        uint8 read_ds1302(uint8 addr)
        {
        uint8 temp=0 ;
        reset_ds1302() ;
        RST = 1 ;
        write_ds1302_byte(addr) ;
        temp = read_ds1302_byte() ;
        SDA = 0 ;
        RST = 0 ;
        return temp ;
        }
        void set_time(uint8 *timedata)
        {
        uint8 i, tmp ;
        for(i=0; i<7; i++)
        {
        tmp = timedata[i]/10 ; //轉為BCD碼,這里注意對于DS1302數據的讀取,必
        timedata[i] = timedata[i] % 10 ; // 須轉換成BCD的格式
        timedata[i] = tmp*16 + timedata[i] ;
        }
        clear_ds1302_wp() ;
        tmp = ds1302_w_addr ;
        for(i=0; i<7; i++)
        {
        write_ds1302(tmp,timedata[i]) ;
        tmp+=2 ;
        }
        set_ds1302_wp() ;
        }
        void read_time(uint8 *timedata)
        {
        uint8 i, tmp ;
        tmp = ds1302_r_addr ; //寫地址,讀數據
        for(i=0; i<7; i++)
        {
        timedata[i] = read_ds1302(tmp) ;
        tmp+=2 ;
        }
        }
        void uart_init()
        {
        SCON = 0x50 ;
        TMOD = 0x21 ; //這里我原本設置了timer0的方式2,但是無效;
        TH1 = 0xFD ; //可能我個人的單片機出了點問題,改成timer1就可以了
        TL1 = 0xFD ;
        TR1 = 1 ;
        }
        void UART_send_byte(uint8 byte)
        {
        SBUF = byte ;
        while(!TI) ;
        TI = 0 ;
        }
        void UART_send_dat(uint8 dat)
        {
        UART_send_byte(dat/16 + 0) ;
        UART_send_byte(dat + 0) ;
        }
        void main(void)
        {
        uart_init() ;
        set_time(&time) ;
        while(1)
        {
        read_time(&time) ; //指針的概念,這里必須使用&time,因為指針不能做加法
        //可以傳輸地址*timedata,讓timedata【i】去運算
        UART_send_dat(time[6]) ;
        UART_send_byte(-) ;
        UART_send_dat(time[4]) ;
        UART_send_byte(-) ;
        UART_send_dat(time[3]) ;
        UART_send_byte( ) ;
        UART_send_dat(time[2]) ;
        UART_send_byte(:) ;
        UART_send_dat(time[1]) ;
        UART_send_byte(:) ;
        UART_send_dat(time[0]) ;
        UART_send_byte() ;
        UART_send_byte() ;
        delay(10000) ;
        }
        }
        上一頁 1 2 下一頁

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 杭锦后旗| 合山市| 东兰县| 虎林市| 临汾市| 聂拉木县| 通许县| 旬阳县| 文化| 阿鲁科尔沁旗| 古交市| 静安区| 阿拉善盟| 康平县| 高淳县| 嘉鱼县| 嘉禾县| 阳信县| 泰顺县| 江阴市| 武安市| 若羌县| 安龙县| 兴国县| 桦川县| 和田市| 潍坊市| 元氏县| 赤壁市| 泊头市| 上林县| 昌江| 卫辉市| 黄龙县| 方正县| 十堰市| 贵阳市| 子长县| 阳城县| 海兴县| 孝义市|