文章目录
- 引言
- 基本特性
- 什么是RAM?
- 什么是涓流充电?
- 电路图和引脚说明
- 通信协议以及工作流程
- 寄存器
- 控制寄存器
- 日历/时钟寄存器
- DS1302读写时序
- 代码演示——数码管显示时分秒
引言
DS1302 是一款广泛使用的实时时钟 (RTC) 芯片,具有低功耗、内置电池备份和串行通信接口等优点。它常用于需要精确时间保持的应用中,如电子时钟、数据记录器和嵌入式系统。
基本特性
DS1302是一款高性能、低功耗的实时时钟芯片,兼容TTL电平,可以直接与单片机的IO口连接。以下是其主要特性:
- 时间保持功能:DS1302 可以保持秒、分、时、日、周、月、年等时间信息,并能自动调整月份天数和闰年。
- 串行通信接口:使用简单的串行接口 (SPI) 进行通信,仅需三根线:RST(复位)、SCLK(串行时钟)和 I/O(串行数据)。
- 低功耗:工作电流低,适合电池供电的应用。工作电压范围为2.0V至5.5V,工作电流小于300nA。
- 内置 RAM:31 字节的静态 RAM,用于存储用户数据。RAM数据时有两种方式:单字节传送或多字节传送(字符组的方式)
- 电池备份:支持备用电池,确保在主电源断电时继续保持时间。
- 涓流充电:当主电源关闭或电压不足时,DS1302可以通过涓流充电寄存器从备用电源(VCC2)获取电力,维持时钟的运行和RAM中的数据。
什么是RAM?
RAM,全称为随机存取存储器(Random Access Memory),是计算机中的一种重要存储器。它的主要特点是可以随时读写数据,并且速度非常快。
RAM是计算机的“短期记忆”。当你打开一个程序或文件时,计算机会将其数据加载到RAM中,以便快速访问和处理。例如,当你在编辑一篇文档时,文档的内容会暂时存储在RAM中,这样你可以快速进行编辑和保存。RAM是易失性存储器,这意味着一旦断电,存储在RAM中的数据就会丢失。这就像是你在白板上写字,一旦擦掉(断电),字迹就消失了。RAM与CPU直接交换数据,速度非常快。它是计算机运行速度的重要因素之一。更多的RAM意味着计算机可以同时处理更多的任务,而不会变慢。
在DS1302时钟芯片中,31字节的静态RAM(SRAM)是一个小型的存储区域,用于存储用户数据。静态表示SRAM中的数据只要保持通电,就可以一直保存,不需要像动态RAM(DRAM)那样定期刷新。31字节表示这个SRAM可以存储31个字节的数据,总共248位(31 x 8 = 248位)。
假设你有一个小笔记本,每一页可以写8个字母,那么31字节的SRAM就相当于这个笔记本有31页,每页可以写8个字母。你可以随时在任何一页上写字或擦掉重写。
什么是涓流充电?
想象一下,你有一个珍贵的水晶杯,需要用极细的水流来清洗,以防止水流过猛导致损坏。涓流充电也是同样的道理。这是一种以非常低的电流对电池进行充电的方法,目的是在电池接近充满时,继续以小电流充电,确保电池完全充满而不受损。
电池充电通常有三个阶段:恒流充电、恒压充电和涓流充电。当电池电量接近满电时,充电器会自动切换到涓流模式,这时候的电流非常小,就像是给电池做最后的“润色”。
在许多电子设备中,如手机、笔记本电脑,甚至一些特殊的芯片(例如DS1302时钟芯片)都采用了涓流充电技术。这些设备在主电源断电后,可以依靠涓流充电来维持电池健康,保证设备在关键时刻不掉链子。
电路图和引脚说明
引脚名 | 引脚顺序 | 作用 |
---|---|---|
VCC1 | 1 | 主电源电压输入 |
VCC2 | 8 | 备用电源电压输入(电池) |
X1、X2 | 2,3 | 外部晶振引脚 |
GND | 4 | 地 |
SCLK | 7 | 串行时钟输入(串行通信) |
I/O | 6 | 串行数据输入/输出 |
CE | 5 | 控制使能 |
详细作用说明
- VCC1 (1号引脚):这是DS1302的主电源输入引脚。在正常工作时,它接收来自外部电源的电压。如果VCC1的电压高于VCC2(备用电源),DS1302将使用VCC1作为其电源。
- VCC2 (8号引脚):此引脚通常连接到一个电池,作为备用电源。在主电源VCC1失效的情况下,VCC2可以继续为DS1302提供电源,确保时间信息不会丢失。
- X1、X2 (2号和3号引脚):这两个引脚需要外接一个32.768kHz的晶振。晶振为DS1302提供时钟信号,确保时间的准确性。X1是输入端,X2是输出端(在某些应用中可能不使用)。
- GND (4号引脚):这是DS1302的接地引脚,用于建立电路的参考电位,确保电路中的信号有正确的电压水平。
- SCLK (7号引脚):此引脚接收来自微控制器或其他控制设备的串行时钟信号。数据传输的时序由SCLK控制,数据在SCLK的上升沿或下降沿被读取或写入,具体取决于通信协议。
- I/O (6号引脚):这个双向引脚用于在DS1302和外部设备之间传输数据。在写入操作中,数据通过此引脚输入到DS1302;在读取操作中,数据从DS1302输出到此引脚。
- CE (5号引脚):CE引脚用于控制DS1302的激活状态。当CE引脚被拉高(即逻辑1)时,DS1302芯片被激活并开始工作;当CE引脚被拉低(即逻辑0)时,芯片进入低功耗状态,停止工作。
通信协议以及工作流程
DS1302 通过三线接口 (SPI) 与主控设备通信。通信过程如下:
- 启动通信:将 RST 引脚置高。
- 发送命令字节:通过 SCLK 引脚发送一个命令字节,指定读写操作和寄存器地址。
- 数据传输:通过 I/O 引脚进行数据读写。
- 结束通信:将 RST 引脚置低。
寄存器
对DS1302
的操作就是对其内部寄存器的操作,DS1302内部共有12个寄存器,其中有:7 个寄存器与日历、时钟相关,存放的数据位为 BCD码形式。此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与 RAM 相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器以外的寄存器。
控制寄存器
用于存放DS1302控制命令的,DS1302的RST复位引脚,如果是高电平,可以开始工作,第一个写入的自己就是控制命令,它用于对DS1302读写进行控制。格式如下:
控制寄存器的字节格式中,最高位(D7)固定为1,这是命令有效的标志。第六位(D6)如果为0
则表示存取日历时钟数据,为1
表示存取RAM数据。接下来的五位(D5~D1)是地址位,用于选择将要进行读写操作的寄存器。最低位(D0)是读写选择位,0表示写入,1表示读取。
控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
日历/时钟寄存器
DS1302时钟芯片的日历/时钟寄存器是其核心功能之一,用于存储和提供当前的日期和时间信息。存放是以BCD码格式进行操作。
- 秒寄存器(地址0x80):存储秒的值,格式为BCD码。低四位表示秒的个位,第五位到第七位表示秒的十位。第八位(CH)是时钟运行标志位,当CH=0时,时钟运行;当CH=1时,时钟暂停。
- 分寄存器(地址0x82):存储分钟的值,格式为BCD码。低四位表示分钟的个位,第五位到第七位表示分钟的十位。最高位(第八位)固定为
0
- 小时寄存器(地址0x84):存储小时的值,格式为BCD码。低四位表示小时的个位,第五位到第七位表示小时的十位。第八位(12/24)用于选择12小时制或24小时制。当12/24=0时,为24小时制;当12/24=1时,为12小时制,且第5位表示上午(AM)或下午(PM)。
- 日期寄存器(地址0x86):存储日期的值,格式为BCD码。低四位表示日期的个位,第五位到第七位表示日期的十位。
- 月份寄存器(地址0x88):存储月份的值,格式为BCD码。低四位表示月份,第五位表示月份的十位。
- 星期寄存器(地址0x8A):存储星期的值,格式为BCD码。低三位表示星期几,从星期一到星期日。
- 年份寄存器(地址0x8C):存储年份的值,格式为BCD码。低四位表示年份的个位,第五位到第七位表示年份的十位。DS1302的年份是从2000年开始的,因此设置年份时需要减去2000。
- 写保护寄存器:DS1302具有写保护功能,低七位全部为固定0,WP用于控制是否开启写保护功能,WP逻辑
1
为开启,只能读不能写,如果要进行写操作,将WP设置为逻辑0
,关闭保护进行写入。 - 慢充电寄存器:DS1302支持涓流充电,当主电源关闭或电压不足时,DS1302可以通过涓流充电寄存器从备用电源(VCC2)获取电力,维持时钟的运行和RAM中的数据。通过特定的控制命令,可以启用或禁用涓流充电功能。这允许用户根据需要控制充电过程,以节省电力或延长备用电源的使用寿命。
BCD码:所有日历/时钟寄存器中的数据都以BCD码格式存储。BCD码是一种二进制编码的十进制数,每四位二进制数表示一个十进制数字(0~9)。
DS1302读写时序
数据是从低位开始写入,三线制SPI的接口:CE,SELK、I/O,当对DS1302操作的时候,CE要设置为"1"(高电平),操作完成之后对CE设置“0”(低电平),等待下一次操作。SCLK为上升沿的时候写入数据。当发送完一个控制命令字节。下一个下降沿开始进行数据的读取。
代码演示——数码管显示时分秒
初始化显示时间:13时51分47秒。实物图:SCLK连接到P36引脚,IO连接到P34引脚,CE连接到P35引脚,具体可查看所使用的开发板电路图进行查看。关于数码管讲解请查看:普中51单片机:数码管显示原理与实现详解(四)
#include <REGX52.H>
#include <intrins.h>sbit DS1302_RST = P3^5;
sbit DS1302_SCLK = P3^6;
sbit DS1302_IO = P3^4;//共阴极数码管显示 0~F 的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void DelayXms(unsigned int xms) //@12.000MHz
{unsigned char data i, j;while(xms){i = 2;j = 239;do{while (--j);} while (--i);xms--;}
}void Init_Port(unsigned char Location)
{ switch(Location){case 1:P2_2 = 0;P2_3 = 0;P2_4 = 0;break;case 2:P2_2 = 1;P2_3 = 0;P2_4 = 0;break;case 3:P2_2 = 0;P2_3 = 1;P2_4 = 0;break;case 4:P2_2 = 1;P2_3 = 1;P2_4 = 0;break;case 5:P2_2 = 0;P2_3 = 0;P2_4 = 1;break;case 6:P2_2 = 1;P2_3 = 0;P2_4 = 1;break;case 7:P2_2 = 0;P2_3 = 1;P2_4 = 1;break;case 8:P2_2 = 1;P2_3 = 1;P2_4 = 1;break;}
}void DS1302_write_byte(unsigned char addr,unsigned char dat)
{unsigned char i = 0;DS1302_RST = 0;_nop_();//延时一微秒DS1302_SCLK = 0;_nop_();//延时一微秒DS1302_RST = 1;//通信开始_nop_();for(i = 0;i < 8;i++)//写入控制{DS1302_IO = addr&0x01;//从低位开始addr>>=1;DS1302_SCLK = 1;_nop_();//延时一微秒DS1302_SCLK = 0;_nop_();}for(i = 0;i < 8;i++)//写入数据{DS1302_IO = dat&0x01;//从低位开始dat>>=1;DS1302_SCLK = 1;_nop_();//延时一微秒DS1302_SCLK = 0;_nop_();}DS1302_RST = 0;//通信结束
}//读
unsigned char DS1302_read_byte(unsigned char addr)
{unsigned char i = 0;unsigned char temp = 0;unsigned char value = 0;DS1302_RST = 0;_nop_();//延时一微秒DS1302_SCLK = 0;_nop_();//延时一微秒DS1302_RST = 1;//通信开始for(i = 0;i < 8;i++)//写入控制{DS1302_IO = addr&0x01;//从低位开始addr>>=1;DS1302_SCLK = 1;_nop_();//延时一微秒DS1302_SCLK = 0;}for(i = 0;i < 8;i++)//读取数据{temp = DS1302_IO;//从低位开始value=(temp<<7)|(value>>1);DS1302_SCLK = 1;_nop_();//延时一微秒DS1302_SCLK = 0;}DS1302_RST = 0;_nop_(); DS1302_SCLK=1;//对于实物中,P3.4口没有外接上拉电阻的,此处代码需要添加,使数据口有一个上升沿脉冲。_nop_();DS1302_IO = 0;_nop_();DS1302_IO = 1;_nop_(); return value;
}//秒分时日月周年
unsigned char gWrite_rtc_addr[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char gRead_rtc_addr[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};unsigned char gDS1302_time[]={0x47,0x51,0x13,0x24,0x07,0x06,0x24};void Init_Ds1302(void)
{unsigned char i = 0;//关闭写保护0x8e表示写保护寄存器DS1302_write_byte(0x8e,0x00);for(i = 0;i < 7;i++){DS1302_write_byte(gWrite_rtc_addr[i],gDS1302_time[i]);}//打开写保护DS1302_write_byte(0x8e,0x80);
}void ds1302_read_time(void)
{unsigned char i = 0;for(i = 0;i < 7;i++){gDS1302_time[i] = DS1302_read_byte(gRead_rtc_addr[i]);}
}void main()
{unsigned char i = 0;unsigned char time_buf[8];Init_Ds1302();//设置时间 while(1){ds1302_read_time();//读取时间time_buf[0] = gsmg_code[gDS1302_time[2]/16];//时 转换为数码管 16进制获取第一位time_buf[1] = gsmg_code[gDS1302_time[2]&0x0f];//时 转换为数码管 16进制获取第二位time_buf[2] = 0x40;// -time_buf[3] = gsmg_code[gDS1302_time[1]/16];//分 转换为数码管 16进制获取第一位time_buf[4] = gsmg_code[gDS1302_time[1]&0x0f];//分 转换为数码管 16进制获取第二位time_buf[5] = 0x40;// -time_buf[6] = gsmg_code[gDS1302_time[0]/16];//秒 转换为数码管 16进制获取第一位time_buf[7] = gsmg_code[gDS1302_time[0]&0x0f];//秒 转换为数码管 16进制获取第二位for(i = 1; i <= 8;i++){Init_Port(i);P1 = time_buf[i-1];DelayXms(1);P1 = 0x00;//消影} }
}