实时时钟芯片DS1302的读写程序
- 格式:doc
- 大小:22.50 KB
- 文档页数:5
#include<at89x52.h>#include"xianshi.h"sbit io=P1^0; // 1302通信允许sbit SCLK=P1^1; // 1302串行数据的位同步脉冲信号sbit RST=P1^2; // 1302双向串行数据传送sbit ACC7=ACC^7;sbit ACC0=ACC^0;uchar tab[7];uchar year[12]={2,0,0,0,0x2d-0x30,0,0,0x2d-0x30,0,0,0x20-0x30,0x20-0x30};uchar week[7][3]={"mon","tue","wen","thu","fri","sat","sun"};uchar date[8]={0,0,0x3a-0x30,0,0,0x3a-0x30,0,0};void write1302(uchar date)//向ds1302写数据{uchar i;SCLK=0; //初始时钟线置为0ACC=date;for(i=8;i>0;i--) //开始传输8个字节的数据{io=ACC0; //取最低位,注意DS1302的数据和地址都是从最低位开始传输的SCLK=0; //时钟线拉低,为下一个上升沿做准备ACC=ACC>>1; //数据右移一位,准备传输下一位数据}}uchar read1302()//读ds1302数据{uchar i;for(i=8;i>0;i--){ACC=ACC>>1; //要返回的数据左移一位ACC7=io; //从1302由低位到高位逐渐取数据,存入ACC中SCLK=1; //拉高时钟线SCLK=0; //制造下降沿}return(ACC); //返回读取出的数据}void write1302_b(unsigned char add,unsigned char date){RST=0; //初始rst线置为0SCLK=0; //初始时钟sclk线置为0RST=1; //初始rst置为1,传输开始write1302(add); //传输命令字,要写入的时间/日历地址write1302(date); //写入要修改的时间/日期SCLK=1; //时钟线拉高RST=0; //读取结束,rst置为0,结束数据的传输}uchar read1302_b(uchar add){uchar date=0x00;RST=0;SCLK=0;RST=1;write1302(add); //传输命令字,要读取的时间/日历地址date=read1302(); //读取要得到的时间/日期RST=0;SCLK=1;return(date); //返回得到的时间/日期}/*****************初始化DS1302********************************/void init_ds1302(){if((((tab[6]=read1302_b(0x81))>>7)&&0x01)==1)/*秒寄存器的BIT7 定义为时间暂停位,当BIT1 为1 时,时钟振荡器停止工作,器启动,DS1302 正常工作。
这是对DS1302编程最常见的操作,有很好的参考价值!我们通过本例程可以了解 DS1302时钟芯片的基本原理和使用 ,理解并掌握DS1302时钟芯片,驱动程序的编写以及实现数字字符在数码管中的显示。
#include<reg52.h>#include <intrins.h>sbit SCK=P3^6; //时钟引脚sbit SDA=P3^4; //数据端口sbit RST = P3^5;// DS1302复位sbit LS138A=P2^2;sbit LS138B=P2^3;sbit LS138C=P2^4;bit ReadRTC_Flag;//定义读DS1302标志unsigned char l_tmpdate[7]={0,0,12,15,5,3,8};//秒分时日月周年08-05-15 12:00:00 unsigned char l_tmpdisplay[8];code unsigned char write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年最低位读写位code unsigned char read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};code unsigned chartable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴数码管 0-9 '-' '熄灭‘表/******************************************************************/ /* 函数声明 *//******************************************************************/void Write_Ds1302_byte(unsigned char temp);void Write_Ds1302( unsigned char address,unsigned char dat );unsigned char Read_Ds1302 ( unsigned char address );void Read_RTC(void);//read RTCvoid Set_RTC(void); //set RTCvoid InitTIMER0(void);//inital timer0/******************************************************************/ /* 主函数 *//******************************************************************/ void main(void){InitTIMER0(); //初始化定时器0Set_RTC(); //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽while(1){if(ReadRTC_Flag){ReadRTC_Flag=0;Read_RTC();l_tmpdisplay[0]=l_tmpdate[2]/16; //数据的转换,因我们采用数码管0~9的显示,将数据分开l_tmpdisplay[1]=l_tmpdate[2]&0x0f;l_tmpdisplay[2]=10; //加入"-"l_tmpdisplay[3]=l_tmpdate[1]/16;l_tmpdisplay[4]=l_tmpdate[1]&0x0f;l_tmpdisplay[5]=10;l_tmpdisplay[6]=l_tmpdate[0]/16;l_tmpdisplay[7]=l_tmpdate[0]&0x0f;}}}/******************************************************************/ /* 定时器0初始化 *//******************************************************************/ void InitTIMER0(void){TMOD|=0x01;//定时器设置 16位TH0=0xef;//初始化值TL0=0xf0;ET0=1;TR0=1;EA=1;}/******************************************************************/ /* 写一个字节 *//******************************************************************/ void Write_Ds1302_Byte(unsigned char temp){unsigned char i;for (i=0;i<8;i++) //循环8次写入数据{SCK=0;SDA=temp&0x01; //每次传输低字节temp>>=1; //右移一位SCK=1;}}/******************************************************************/ /* 写入DS1302 *//******************************************************************/ void Write_Ds1302( unsigned char address,unsigned char dat ){RST=0;_nop_();SCK=0;_nop_();RST=1;_nop_(); //启动Write_Ds1302_Byte(address); //发送地址Write_Ds1302_Byte(dat); //发送数据RST=0; //恢复}/******************************************************************/ /* 读出DS1302数据 *//******************************************************************/unsigned char Read_Ds1302 ( unsigned char address ){unsigned char i,temp=0x00;RST=0;_nop_();_nop_();SCK=0;_nop_();_nop_();RST=1;_nop_();_nop_();Write_Ds1302_Byte(address);for (i=0;i<8;i++) //循环8次读取数据{if(SDA)temp|=0x80; //每次传输低字节SCK=0;temp>>=1; //右移一位_nop_();_nop_();_nop_();SCK=1;}RST=0;_nop_(); //以下为DS1302复位的稳定时间_nop_();RST=0;SCK=0;_nop_();_nop_();_nop_();_nop_();SCK=1;_nop_();_nop_();SDA=0;_nop_();_nop_();SDA=1;_nop_();_nop_();return (temp); //返回}/******************************************************************/ /* 读时钟数据 *//******************************************************************/ void Read_RTC(void) //读取日历{unsigned char i,*p;p=read_rtc_address; //地址传递for(i=0;i<7;i++) //分7次读取秒分时日月周年{l_tmpdate[i]=Read_Ds1302(*p);p++;}}/******************************************************************//* 设定时钟数据 *//******************************************************************/ void Set_RTC(void) //设定日历{unsigned char i,*p,tmp;for(i=0;i<7;i++){ //BCD处理tmp=l_tmpdate[i]/10;l_tmpdate[i]=l_tmpdate[i]%10;l_tmpdate[i]=l_tmpdate[i]+tmp*16;}Write_Ds1302(0x8E,0X00);p=write_rtc_address; //传地址for(i=0;i<7;i++) //7次写入秒分时日月周年{Write_Ds1302(*p,l_tmpdate[i]);p++;}Write_Ds1302(0x8E,0x80);}/******************************************************************/ /* 定时器中断函数 *//******************************************************************/ void tim(void) interrupt 1 using 1//中断,用于数码管扫描{static unsigned char i,num;TH0=0xf5;TL0=0xe0;P0=table[l_tmpdisplay[i]]; //查表法得到要显示数字的数码段switch(i){case 0:LS138A=0; LS138B=0; LS138C=0; break;case 1:LS138A=1; LS138B=0; LS138C=0; break;case 2:LS138A=0; LS138B=1; LS138C=0; break;case 3:LS138A=1; LS138B=1; LS138C=0; break;case 4:LS138A=0; LS138B=0; LS138C=1; break;case 5:LS138A=1; LS138B=0; LS138C=1; break;case 6:LS138A=0; LS138B=1; LS138C=1; break;case 7:LS138A=1; LS138B=1; LS138C=1; break;}i++;if(i==8){i=0;num++;if(10==num) //隔段时间读取1302的数据。
#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intuchar table0[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; //液晶显示数字0——9代码sbit SCLK=P1^0;sbit DATA=P1^1;sbit CE=P1^2;sbit RS=P2^0;sbit RW=P2^1;sbit EN=P2^2;sbit FB=P0^7;sbit start=P1^4;sbit stop=P1^5;uchar i;/*******************延时n微秒函数*****************/void delaynus(uchar n) //n us延时函数{// uchar i;for(i=n;i>0;i--);}/*******************写数据函数*****************/void write1302(uchar add,uchar dat){CE=0;SCLK=0;CE=1;for(i=0;i<8;i++) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=0;i<8;i++) //写入数据{DATA=dat&0x01;SCLK=1;SCLK=0;dat>>=1;}SCLK=1;CE=0;}/*******************读数据函数*****************/uchar read1302(uchar add){uchar dat;CE=0;SCLK=0;CE=1;for(i=8;i>0;i--) //写入地址{DATA=add&0x01;SCLK=1;SCLK=0;add>>=1;}for(i=8;i>0;i--) //读出数据/********************为神马???**************************/{dat>>=1;if(DATA==1)dat=dat|0x80;SCLK=1;SCLK=0;}SCLK=1;CE=0;return dat;}/*******************DS1302初始化函数*****************/void init1302(){uchar flag;flag=read1302(0x81);if(flag&0x80){write1302(0x8e,0x00);write1302(0x80,0x00);write1302(0x82,(((1/10)<<4)|(1%10)));write1302(0x84,(((20/10)<<4)|(20%10)));write1302(0x86,(((19/10)<<4)|(19%10)));write1302(0x88,(((7/10)<<4)|(7%10)));write1302(0x8a,((2/10)<<4)|(2%10));write1302(0x8c,(((11/10)<<4)|(11%10)));write1302(0x90,0xa5); //充电。
DS1302实时实钟芯片应用(一)DS1302概述DS1302是DALLAS公司生产的绢流充电时钟芯片,内含有一个实时时钟/日历和31字节静态RAM,通过简单的串行接口与微控制器进行通信。
具有秒、分、时、日、周、月、年信息。
每月的天数和闰年的天数可自动调整。
时钟和RAM的读/写可以以一个字节或多达31个字节的形式进行传输。
DS1302工作时的功耗很低,保持数据和时钟信息时所需功率小于1mW。
有主电源和备用电源。
(二)DS1302的主要性能A. 实时时钟能计算到2099年B. 31字节静态RAMC. 串口通信方式D. 电压范围2~5.5V,2V时工作电流小于300nAE. 温度范围-40~+85℃(三)引脚及功能(四)DS1302的命令字每一次数据传送都由一字节命令字开始,其后紧跟一字节数据或多字节数据。
命令字如下:读写DS1302内部RAM命令字如下:(五)DS1302的数据传送通过把/RST拉至高电平来启动数据传送,将/RST拉至低电平则可终止数据传送,I/O引脚变为高阻状态。
数据输入时,在时钟的上升沿数据必须有效,而数据位在时钟的下降沿输出。
上电时,在Vcc≥2.5V之前,/RST必须为逻辑0。
此外,当把/RST拉至逻辑1时,SCLK必须为逻辑0。
跟随在写命令字节的8个SCLK周期之后,在下8个SCLK周期的上升沿输入数据字节,如果有额外的SCLK 周期,它们将被忽略,数据从最低位(位0)开始传送。
跟随在读命令字节的8个时钟周期之后,在下8个时钟周期的下将沿输出数据字节。
注意:被传送的第一个数据位发生在写命令字节的最后一位之后和第一个下将沿。
只要/RST保持高电平,如果有额外的时钟周期,它们将重新发送数据字节,这一操作使之具有连续的多字节的读能力。
另外,在时钟的每一个上升沿,I/O引脚为三态。
数据从最低位开始是传送。
DS1302的多字节读写:对时钟/日历寄存器进行多字节读写时,其命令字节BFH为读,BEH为写;当对RAM 进行多字节读写时,其命令字节FFH为读,FEH为写。
时钟芯片DS1302 的程序(C51程序)模块名称:DS1302.c功能:实时时钟模块时钟芯片型号:DS1302 程序设计:zhaojunjie********************************************************************* /#includesbit T_CLK = P2^7; /*实时时钟时钟线引脚 */ sbit T_IO = P1^4; /*实时时钟数据线引脚 */ sbit T_RST = P1^5; /*实时时钟复位线引脚 */sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;void RTInputByte(uchar); /* 输入 1Byte */uchar RTOutputByte(void); /* 输出?1Byte */void W1302(uchar, uchar);uchar R1302(uchar);void Set1302(uchar *); /* 设置时间 */void Bcd2asc(uchar,uchar *);void Get1302(uchar curtime[]); /* 读取1302当前时间 *//********************************************************************函数名:RTInputByte()功能:实时时钟写入一字节说明:往DS1302写入1Byte数据 (内部函数)入口参数:d 写入的数据返回值:无设计:zhaojunjie********************************************************************* **/void RTInputByte(uchar d){uchar i;ACC = d;for(i=8; i>0; i--){T_IO = ACC0; /*相当于汇编中的 RRC */T_CLK = 1;T_CLK = 0;ACC = ACC >> 1;}}/********************************************************************函数名:RTOutputByte()功能:实时时钟读取一字节说明:从DS1302读取1Byte数据 (内部函数)入口参数:无返回值:ACC设计:zhaojunjie********************************************************************* **/uchar RTOutputByte(void){uchar i;for(i=8; i>0; i--){ACC = ACC >>1; /*相当于汇编中的 RRC */ACC7 = T_IO;T_CLK = 1;T_CLK = 0;}return(ACC);}/********************************************************************函数名:W1302()功能:往DS1302写入数据说明:先写地址,后写命令/数据 (内部函数)调用:RTInputByte() , RTOutputByte()入口参数:ucAddr: DS1302地址, ucData: 要写的数据返回值:无设计:zhaojunjie********************************************************************* **/void W1302(uchar ucAddr, uchar ucDa){T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令 */RTInputByte(ucDa); /* 写1Byte数据*/T_CLK = 1;T_RST = 0;}/********************************************************************函数名:R1302()功能:读取DS1302某地址的数据说明:先写地址,后读命令/数据 (内部函数)调用:RTInputByte() , RTOutputByte()入口参数:ucAddr: DS1302地址返回值:ucData :读取的数据设计:zhaojunjie********************************************************************* **/uchar R1302(uchar ucAddr){uchar ucData;T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令 */ucData = RTOutputByte(); /* 读1Byte数据 */T_CLK = 1;T_RST = 0;return(ucData);}/********************************************************************函数名:BurstW1302T()功能:往DS1302写入时钟数据(多字节方式)说明:先写地址,后写命令/数据调用:RTInputByte()入口参数:pWClock: 时钟数据地址格式为: 秒分时日月星期年控制8Byte (BCD码)1B 1B 1B 1B 1B 1B 1B 1B返回值:无设计:zhaojunjie********************************************************************* **/void BurstW1302T(uchar *pWClock){uchar i;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(0xbe); /* 0xbe:时钟多字节写命令 */for (i = 8; i>0; i--) /*8Byte = 7Byte 时钟数据 + 1Byte 控制*/{RTInputByte(*pWClock); /* 写1Byte数据*/pWClock++;}T_CLK = 1;T_RST = 0;}/********************************************************************函数名:BurstR1302T()功能:读取DS1302时钟数据说明:先写地址/命令,后读数据(时钟多字节方式)调用:RTInputByte() , RTOutputByte()入口参数:pRClock: 读取时钟数据地址格式为: 秒分时日月星期年7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B返回值:无设计:zhaojunjie********************************************************************* **/void BurstR1302T(uchar *pRClock){uchar i;T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(0xbf); /* 0xbf:时钟多字节读命令 */for (i=8; i>0; i--){*pRClock = RTOutputByte(); /* 读1Byte数据 */pRClock++;}T_CLK = 1;}/********************************************************************函数名:BurstW1302R()功能:往DS1302寄存器数写入数据(多字节方式)说明:先写地址,后写数据(寄存器多字节方式)调用:RTInputByte()入口参数:pWReg: 寄存器数据地址返回值:无设计:zhaojunjie********************************************************************* **/void BurstW1302R(uchar *pWReg){uchar i;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作*/T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(0xfe); /* 0xbe:时钟多字节写命令*/for (i=31; i>0; i--) /* 31Byte 寄存器数据 */{RTInputByte(*pWReg); /* 写1Byte数据*/pWReg++;}T_CLK = 1;T_RST = 0;}/********************************************************************函数名:BurstR1302R()功能:读取DS1302寄存器数据说明:先写地址,后读命令/数据(寄存器多字节方式)调用:RTInputByte() , RTOutputByte()入口参数:pRReg: 寄存器数据地址返回值:无设计:zhaojunjie********************************************************************* **/void BurstR1302R(uchar *pRReg){uchar i;T_CLK = 0;T_RST = 1;RTInputByte(0xff); /* 0xff:时钟多字节读命令 */for (i=31; i>0; i--) /*31Byte 寄存器数据 */{*pRReg = RTOutputByte(); /* 读1Byte数据 */pRReg++;}T_CLK = 1;T_RST = 0;}/********************************************************************函数名:Set1302()功能:设置初始时间说明:先写地址,后读命令/数据(寄存器多字节方式)调用:W1302()入口参数:pClock: 设置时钟数据地址格式为: 秒分时日月星期年7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B返回值:无设计:zhaojunjie********************************************************************* **/void Set1302(uchar *pClock){uchar i;uchar ucAddr = 0x80;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/for(i =7; i>0; i--){W1302(ucAddr,*pClock); /* 秒分时日月星期年*/pClock++;ucAddr +=2;}W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/}/********************************************************************函数名:Get1302()功能:读取DS1302当前时间说明:调用:R1302()入口参数:ucCurtime: 保存当前时间地址。
实时时钟DS1302读写程序(C51)//打开DS1302void TimeSpiOpen(void){TIMECLK = 0;TIMERST = 0;//禁止DS1302TIMEIO = 1;//释放数据总线TIMERST = 1;//使能DS1302}//关闭DS1302void TimeSpiClose(void){TIMERST = 0;//禁止DS1302TIMEIO = 1;//释放数据总线TIMECLK = 1;}//读写DS1302unsigned char TimeSpiReadWrite(unsigned char val) {unsigned char i;ACC = val;//取8位数据for (i = 8;i > 0; i--){TIMECLK = 0;//时钟下降沿输入数据(DS1302读)_nop_();//延时CY = TIMEIO;//接收串行数据到CY_rrca_();//右移一位数据到CY(先存后取)TIMEIO = CY;//发送串行数据TIMECLK = 1;//时钟上升沿打入数据(DS1302写)TIMEIO = 1;//释放数据总线}val = ACC;return val;}//读DS1302字节unsigned char TimeByteRead(unsigned char address) {TimeSpiOpen();//打开DS1302TimeSpiReadWrite(address);//写入DS1302命令address = TimeSpiReadWrite(0xff);//读入DS1302数据 TimeSpiClose();//关闭DS1302return address;//返回数据}//读DS1302RAM字节unsigned char TimeRamByteRead(unsigned char address){TimeSpiOpen();//打开DS1302TimeSpiReadWrite((address << 1) | 0xc1);//写入DS1302命令address = TimeSpiReadWrite(0xff);//读入DS1302数据TimeSpiClose();//关闭DS1302return address;//返回数据}//写DS1302字节void TimeByteWrite(unsigned char address, unsigned char val){TimeSpiOpen();//打开DS1302TimeSpiReadWrite(address);//写地址TimeSpiReadWrite(val);//写数据TimeSpiClose();//关闭DS1302}//写DS1302字节void TimeRamByteWrite(unsigned char address, unsigned char val) {TimeSpiOpen();//打开DS1302TimeSpiReadWrite((address << 1) | 0xc0);//写地址TimeSpiReadWrite(val);//写数据TimeSpiClose();//关闭DS1302}//使能DS1302写保护void TimeWriteEnable(void){TimeByteWrite(timewriteregall, timewriteseg);//使能DS1302写保护}//开放DS1302写保护void TimeWrieDisbale(void){TimeByteWrite(timewriteregall, 0);//开放DS1302写保护}//DS1302工作开始void TimeWorkStart(void){unsigned char val;val = TimeByteRead(timereadseg);//读秒数据val &= 0x7f;//打开晶振TimeWrieDisbale();//开放DS1302写保护TimeByteWrite(timewriteseg, val);//打开晶振TimeByteWrite(tricklewrite, 0xa5);//打开充电二极管 TimeWriteEnable();//使能DS1302写保护}。
DS1302时钟芯片读写详解DS1302时钟芯片读写详解2008-09-26 13:07/*DS1302读写程序(C51)*/sbit DS13CLK =P1^5; /*DS1302的SCLK脚脉冲*/ sbit DS13IO =P1^6; /*DS1302的IO脚数据*/ sbit DS13CS =P1^7; /*DS1302的RST脚片选*/ /*向DS1302写一个字节*/void _wds13byte(uchar _code){uchar i;DS13CLK =0;DS13CLK =0;for(i=0;i<8;i++){if(_code&0x01) DS13IO =1;else DS13IO =0;DS13CLK =1;DS13CLK =1;DS13CLK =0;DS13CLK =0;_code =_code >> 1;}}/*从DS1302读一个字节*/uchar _rds13byte(void){uchar i,_code;_code=0;DS13CLK =0;DS13CLK =0;DS13IO =1;for(i=0;i<8;i++){_code =_code >>1;if(DS13IO) _code =_code|0x80;DS13CLK =1;DS13CLK =1;DS13CLK =0;DS13CLK =0;}return _code;}/*读功能 _code读功能命令 */uchar readds1302(uchar _code){DS13CS =0; /*关闭DS1302*/DS13CLK =0;DS13CLK =0;DS13CS =1; /*使能DS1302*/_wds13byte(_code); /*读代码*/_code=_rds13byte(); /*返回读取数字*/ DS13CLK =1;DS13CS =0; /*关闭DS1302*/ return _code;}/*写功能 fp写的地址,_code写的内容*/ void writeds1302(uchar fp,uchar _code) {DS13CS =0; /*关闭DS1302*/DS13CLK =0;DS13CLK =0;DS13CS =1; /*使能DS1302*/_wds13byte(fp); /*写控制命令*/_wds13byte(_code); /*写入数据*/DS13CLK=1;DS13CS =0; /*关闭DS1302*/}/*******DS1302设置快速充电***************/void ds13_charg(void){writeds1302(0x8e,0x00); /*解除写保护*/writeds1302(0x90,0xa5); /*单二极管2K电阻充电*/writeds1302(0x8e,0x80); /*置位写保护*/};;;DS1302读写程序(汇编);;;;************************************************************** *******/T_CLK Bit P1.5 ;实时时钟时钟线引脚T_IO Bit P1.6 ;实时时钟数据线引脚T_RST Bit P1.7 ;实时时钟复位线引脚;**********************************************************;子程序名:Set1302;功能:设置DS1302 初始时间,并启动计时。
51单片机第二十三课实时时钟芯片DS1302的读写
所属类别:课程代码发布日期:2011-03-05 点击量:385 #include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit sck=P1^0;
sbit io=P1^1;
sbit rst=P3^6;
sbit smgen=P2^3;
unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e, 0x79,0x71,0x00,0x10};
unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};
uchar time_data[7]={10,6,4,17,11,58,30}; //年周月日时分秒
uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};
uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};
uchar disp[8];
void write_ds1302_byte(uchar dat);
void write_ds1302(uchar add,uchar dat);
uchar read_ds1302(uchar add);
void set_rtc(void);
void read_rtc(void);
void time_pros(void);
void display(void);
//************************************************
//延时函数,在12MHz的晶振频率下
//大约50us的延时
//************************************************
void delay_50us(uint t)
{
uchar j;
for(;t>0;t--)
for(j=19;j>0;j--);
}
//************************************************ //延时函数,在12MHz的晶振频率下
//大约50ms的延时
//************************************************ void delay_50ms(uint t)
{
uint j;
for(;t>0;t--)
for(j=6245;j>0;j--);
}
void write_ds1302_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
sck=0;
io=dat&0x01;
dat=dat>>1;
sck=1;
}
}
void write_ds1302(uchar add,uchar dat)
{
rst=0;
_nop_();
sck=0;_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
write_ds1302_byte(dat);
rst=0;
_nop_();
io=1;
sck=1;
}
uchar read_ds1302(uchar add)
{
uchar i,value;
rst=0;
_nop_();
sck=0;
_nop_();
rst=1;
_nop_();
write_ds1302_byte(add);
for(i=0;i<8;i++)
{
value=value>>1;
sck=0;
if(io)
value=value|0x80;
sck=1;
}
rst=0;
_nop_();
sck=0;
_nop_();
sck=1;
io=1;
return value;
}
void set_rtc(void)
{
uchar i,j;
for(i=0;i<7;i++)
{
j=time_data[i]/10;
time_data[i]=time_data[i]%10;
time_data[i]=time_data[i]+j*16;
}
write_ds1302(0x8e,0x00); //去除写保护for(i=0;i<7;i++)
{
write_ds1302(write_add[i],time_data[i]); }
write_ds1302(0x8e,0x80); //加写保护
}
void read_rtc(void)
{
uchar i;
for(i=0;i<7;i++)
{
time_data[i]=read_ds1302(read_add[i]); }
}
void time_pros(void)
{
disp[0]=time_data[6]%16;
disp[1]=time_data[6]/16;
disp[2]=16;
disp[3]=time_data[5]%16;
disp[4]=time_data[5]/16;
disp[5]=16;
disp[6]=time_data[4]%16;
disp[7]=time_data[4]/16;
}
void display(void)
{
uchar i;
for(i=0;i<8;i++)
{
P1=smg_du[disp[i]];
P2=smg_we[i];
delay_50us(20);
}
}
void main(void)
{
set_rtc();
delay_50us(20);
while(1) {
smgen=0; rst=1;
read_rtc(); rst=0;
time_pros(); smgen=1; display(); smgen=0; }
}。