DS1302详解

DS1302详解DS1302 是由美国 DALLAS 公司推出的具有涓细电流充电能力的低功耗实时时钟芯片 它可以对年 月 日 周 时 分 秒进行计时 并且具有闰年补偿等多种功能


前言

现在流行的串行时钟电路很多,如DS1302、 DS1307、PCF8485等。这些电路的接口简单、价格低廉、使用方便,被广泛地采用。本文介绍的实时时钟电路DS1302是DALLAS公司的一种具有涓细电流充电能力的电路,主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。采用普通32.768kHz晶振。


一、DS1302简介

在这里插入图片描述

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,并且具有闰年补偿等多种功能。

1. 工作原理

DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。

2. 内部结构

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引脚变为高阻态。上电运行时,在Vcc>2.0V之前,RST必须保持低电平。只有在SCLK为低电平时,才能将RST置为高电平。I/O为串行数据输入输出端(双向),后面有详细说明。SCLK为时钟输入端。

图1为DS1302的引脚功能图:

在这里插入图片描述

3. 控制字节

4. 数据流

在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。

5. 寄存器

6. 参考电路

在这里插入图片描述

二、DS1302通信时序

DS1302有三根线,分别是 CE、I/O 和 SCLK,其中 CE 是使能线,SCLK 是时钟线,I/O 是数据线。大家有没有发现这个 DS1302的通信线定义和 SPI 很相像呢。

事实上,DS1302 的通信是 SPI 的变异种类,它用了 SPI 的通信时序,但是通信的时候没有完全按照 SPI 的规则来,下面我们一点点解剖 DS1302 的变异 SPI 通信方式。先看一下单字节写入操作,如下图:

在这里插入图片描述

然后我们再对比一下CPOL=0/CPHA=0情况下的 SPI 的操作时序,如下图:

在这里插入图片描述
上面俩图的通信时序,其中 CE 和 SSEL 的使能控制是反的,对于通信写数据,都是在 SCK 的上升沿,从机进行采样,下降沿的时候,主机发送数据。DS1302 的时序里,单片机要预先写一个字节指令,指明要写入的寄存器的地址以及后续的操作是写操作,然后再写入一个字节的数据。

第二个需要注意的地方就是,我们的单片机没有标准的 SPI 接口,和 I2C 一样需要用 IO口来模拟通信过程。在读 DS1302 的时候,理论上 SPI 是上升沿读取,但是程序是用 IO 口模拟的,所以数据的读取和时钟沿的变化不可能同时了,必然就有一个先后顺序。通过实验发现,如果先读取 IO 线上的数据,再拉高 SCLK 产生上升沿,那么读到的数据一定是正确的,而颠倒顺序后数据就有可能出错。这个问题产生的原因还是在于 DS1302 的通信协议与标准SPI 协议存在的差异造成的,如果是标准 SPI 的数据线,数据会一直保持到下一个周期的下降沿才会变化,所以读取数据和上升沿的先后顺序就无所谓了;但 DS1302 的 IO 线会在时钟上升沿后被 DS1302 释放,也就是撤销强推挽输出变为弱下拉状态,而此时在 51 单片机引脚内部上拉的作用下,IO 线上的实际电平会慢慢上升,从而导致在上升沿产生后再读取 IO 数据的话就可能会出错。因此这里的程序我们按照先读取 IO 数据,再拉高 SCLK 产生上升沿的顺序。

三、程序设计

1. 初始化

void DS1302_Init(void) { 
      DS1302_CE=0; DS1302_SCLK=0; } 

2. 写入 / 读出一个字节

/ * @brief DS1302写一个字节 * @param Command 命令字/地址 * @param Data 要写入的数据 * @retval 无 */ void DS1302_WriteByte(unsigned char Command,Data) { 
      unsigned char i; DS1302_CE=1; for(i=0;i<8;i++) { 
      DS1302_IO=Command&(0x01<<i); DS1302_SCLK=1; DS1302_SCLK=0; } for(i=0;i<8;i++) { 
      DS1302_IO=Data&(0x01<<i); DS1302_SCLK=1; DS1302_SCLK=0; } DS1302_CE=0; } / * @brief DS1302读一个字节 * @param Command 命令字/地址 * @retval 读出的数据 */ unsigned char DS1302_ReadByte(unsigned char Command) { 
      unsigned char i,Data=0x00; Command|=0x01; //将指令转换为读指令 DS1302_CE=1; for(i=0;i<8;i++) { 
      DS1302_IO=Command&(0x01<<i); DS1302_SCLK=0; DS1302_SCLK=1; } for(i=0;i<8;i++) { 
      DS1302_SCLK=1; DS1302_SCLK=0; if(DS1302_IO){ 
     Data|=(0x01<<i);} } DS1302_CE=0; DS1302_IO=0; //读取后将IO设置为0,否则读出的数据会出错 return Data; } 

3. 设置 / 读取时间

/ * @brief DS1302设置时间,调用之后,DS1302_Time数组的数字会被设置到DS1302中 * @param 无 * @retval 无 */ void DS1302_SetTime(void) { 
      DS1302_WriteByte(DS1302_WP,0x00); DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入 DS1302_WriteByte(DS1302_MONTH,DS1302_Time[1]/10*16+DS1302_Time[1]%10); DS1302_WriteByte(DS1302_DATE,DS1302_Time[2]/10*16+DS1302_Time[2]%10); DS1302_WriteByte(DS1302_HOUR,DS1302_Time[3]/10*16+DS1302_Time[3]%10); DS1302_WriteByte(DS1302_MINUTE,DS1302_Time[4]/10*16+DS1302_Time[4]%10); DS1302_WriteByte(DS1302_SECOND,DS1302_Time[5]/10*16+DS1302_Time[5]%10); DS1302_WriteByte(DS1302_DAY,DS1302_Time[6]/10*16+DS1302_Time[6]%10); DS1302_WriteByte(DS1302_WP,0x80); } / * @brief DS1302读取时间,调用之后,DS1302中的数据会被读取到DS1302_Time数组中 * @param 无 * @retval 无 */ void DS1302_ReadTime(void) { 
      unsigned char Temp; Temp=DS1302_ReadByte(DS1302_YEAR); DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取 Temp=DS1302_ReadByte(DS1302_MONTH); DS1302_Time[1]=Temp/16*10+Temp%16; Temp=DS1302_ReadByte(DS1302_DATE); DS1302_Time[2]=Temp/16*10+Temp%16; Temp=DS1302_ReadByte(DS1302_HOUR); DS1302_Time[3]=Temp/16*10+Temp%16; Temp=DS1302_ReadByte(DS1302_MINUTE); DS1302_Time[4]=Temp/16*10+Temp%16; Temp=DS1302_ReadByte(DS1302_SECOND); DS1302_Time[5]=Temp/16*10+Temp%16; Temp=DS1302_ReadByte(DS1302_DAY); DS1302_Time[6]=Temp/16*10+Temp%16; } 

总结

很多DS1302 存在时钟精度不高,是因为选用的晶振易受环境影响,出现时钟混乱等缺点。DS1302可以用于数据记录,特别是对某些具有特殊意义的数据点的记录,能实现数据与出现该数据的时间同时记录。这种记录对长时间的连续测控系统结果的分析及对异常数据出现的原因的查找具有重要意义。传统的数据记录方式是隔时采样或定时采样,没有具体的时间记录,因此,只能记录数据而无法准确记录其出现的时间;若采用单片机计时,一方面需要采用计数器,占用硬件资源,另一方面需要设置中断、查询等,同样耗费单片机的资源,而且,某些测控系统可能不允许。但是,如果在系统中采用时钟芯片DS1302,则能很好地解决这个问题。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/218389.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午7:22
下一篇 2026年3月18日 上午7:23


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号