一、功能说明
如图为DS1302的实物及引脚排列图,其中VCC2引脚接备用电池,VCC1为主电源。在主电源掉电的情况下,备用电池能保持时钟的连续运行。DS1302由Vcc1或Vcc2两者中的较大者供电。当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是谐振引脚,外接32.768kHz晶振。RST是复位/片选线, RST置高电平启动所有的数据传送。RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
在传送过程中如果RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。因此DS1302上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向), SCLK始终是输入端。
二、控制指令
(1)DS1302的时间控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中:位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址,最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
(2)在控制指令字输入后的下一个SCLK时钟的上升沿时数据被写入DS1302,数据发送从低位即位0开始依次写入8位。在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位至高位7。
(3)写保护寄存器控制DS1302时间的写允许操作, WP高电平有效,对应控制字为0x8e。当系统对DS1302进行时间调整时,必须向写保护寄存器中写入0x00,时间调整后再写入0x10。
三、读写时序
基本操作含系统对DS1302初始化、写一字节、读一字节。初始化主要对DS1302的RST、SCLK引脚初始化。RST置1时才能芯片正常的工作。但DS1302上电开始运行时,RST须保持低电平,只有在SCLK为低电平时,才能将RST置为高电平。
从由DS1302的读写时序可以看出,在SCLK上升沿来到时写数据,下降沿来到时读数据,单片机向DS1302中发送和接收的数据先从低位开始,因此在读写操作中需根据读写时序完成一个字节的读写。
四、代码
由于DS1302内部时间寄存器中的时间数据8421BCD码,因此读出的时间需要进行码制转换;在对DS1302进行时间调整时,也需要把十进制数据转换成8421BCD码后写入DS1302。
写入一字节
void Write_Ds1302(unsigned char temp) { unsigned char i; for (i=0;i<8;i++) //由低到高依次写入 { SCK = 0; //SCLK在上升沿时数据写入 SDA = temp&0x01; temp>>=1; SCK=1; } }
向指定地址写入一字节
void Write_Ds1302_Byte( unsigned char address,unsigned char dat ) { RST=0; _nop_(); SCK=0; _nop_(); //在SCLK低电平时才可将RST置高 RST=1; _nop_(); Write_Ds1302(address); Write_Ds1302(dat); RST=0; }
从指定地址读出一字节数据
unsigned char Read_Ds1302_Byte ( unsigned char address ) { unsigned char i,temp=0x00; RST=0; _nop_(); SCK=0; _nop_(); RST=1; _nop_(); Write_Ds1302(address); for (i=0;i<8;i++) { SCK=0; temp>>=1; if(SDA) temp|=0x80; //在上升沿由低到高依次读出 SCK=1; } RST=0; _nop_(); SCK=0; _nop_(); SCK=1; _nop_(); SDA=0; _nop_(); SDA=1; _nop_(); return (temp); }
void DS1302_SetTime() //设置时间 { unsigned char i; Write_Ds1302_Byte(0x8e,0x00); for(i=0;i<3;i++) { //十进制 -> BCD Write_Ds1302_Byte(RTC_write[i],DS1302_Time[i] / 10 * 16 + DS1302_Time[i] % 10); } Write_Ds1302_Byte(0x8e,0x80); } void DS1302_ReadTime() //读取时间 { unsigned char i; for(i=0;i<3;i++) { // BCD -> 十进制 DS1302_Time[i] = Read_Ds1302_Byte(RTC_read[i]) / 16 * 10 + Read_Ds1302_Byte(RTC_read[i]) % 16; } }
存放时间和地址
unsigned char DS1302_Time[3]={9,3,20}; unsigned char RTC_write[]={0x84,0x82,0x80};// 时 分 秒 unsigned char RTC_read[]={0x85,0x83,0x81};
tips:每次传递时间数据时要先读取。