本章概述思维导图:
51单片机驱动DS1302时钟芯片模块
DS1302简介
DS1302 是美国 DALLAS 公司(现属 MAXIM Integrated)推出的高性能、低功耗实时时钟芯片,具备闰年补偿、双电源供电、串行通信等特性,广泛应用于消费电子、工业自动化及物联网设备中。实物图如下:
DS1302核心功能
1、实时时钟与日历
支持年、月、日、星期、时、分、秒的精确计时,自动处理闰年及月份天数变化(如2 月天数调整);提供 12/24 小时制切换,通过小时寄存器位 7 控制(1=12 小时制,0=24 小时制), 12 小时制下位 5 表示 AM/PM。
2、低功耗设计
工作电压范围 2.0V~5.5V,待机功耗低至 300nA(2.0V 时),适合电池供电场景;双电源供电:主电源(VCC2)与备用电源(VCC1)自动切换,主电源断电时由备用电 源维持计时,数据不丢失。
3、数据存储
内置 31 字节静态 RAM,可用于临时数据存储,支持单字节或突发模式(Burst Mode) 读写。
3、涓流充电
集成充电控制电路,可通过外部电阻和二极管为备用电池充电,延长电池寿命。
DS1302关键技术参数
参数 | 描述 |
晶振频率 | 32.768kHz(标准时钟晶振) |
通信接口 | 三线 SPI 兼容接口(SCLK、I/O、RST) |
数据格式 | BCD 码(二进制编码十进制,便于显示) |
工作温度 | -40°C~+85°C(工业级) |
封装形式 | 8 引脚 DIP 或 SOIC |
寄存器数量 | 12 个(7 个时钟寄存器、1 个控制寄存器、1个充电寄存器、1个时钟突发寄存器、2个 RAM 相关寄存器) |
DS1302引脚定义与封装
DS1302采用8引脚DIP或SOIC封装,各引脚功能如下:
引脚号 | 名称 | 功能描述 |
1 | VCC2 | 主电源引脚,接3.3V或5V电源,优先级高于VCC1。 |
2 | X1 | 晶振引脚,外接32.768kHz晶振,为芯片提供计时基准。 |
3 | X2 | 晶振引脚,与X1构成振荡回路。 |
4 | GND | 接地引脚,确保芯片工作稳定性。 |
5 | RST | 复位/片选引脚,高电平时启动数据传输,低电平时终止传输并使I/O引脚呈高阻态。 |
6 | I/O | 双向数据引脚,用于串行数据输入/输出。 |
7 | SCLK | 串行时钟引脚,控制数据传输的同步信号。 |
8 | VCC1 | 备用电源引脚,外接电池(如CR1220),主电源断电时维持时钟运行。 |
DS1302时钟芯片寄存器介绍
DS1302芯片的12个寄存器中,7个为日历/时钟寄存器,用于存储秒、分、时、日、月、年、星期数据;1个为控制寄存器,用于用于配置 DS1302 的工作模式(如时钟/日历模式、RAM 读写模式)以及控制数据传输,复用功能为写保护设置;1个为充电寄存器,用于配置涓流充电参数;1个为时钟突发寄存器,支持多字节连续读写;剩余31字节为独立RAM单元(部分资料将其拆分为31个单字节寄存器描述)。
控制寄存器格式:
位 | 名称 | 功能描述 |
D7 | 固定为1 | 命令有效标志。 |
D6 | RAM/CK | 0=访问时钟寄存器,1=访问RAM。 |
D5-D1 | 地址位 | 选择要读写的寄存器地址。 |
D0 | RD/WR | 0=写操作,1=读操作。 |
位7:固定为1,是控制命令标志。如果该位为0,则不能把数据写入DS1302中。
位6(RAM/CK):片内RAM或日历、时钟寄存器选择位。当RAM/CK=1时,表示对片内RAM 进行读写操作;当RAM/CK=0时,表示对日历、时钟寄存器进行读写操作。
位5-位1(A4-A1):地址位,用于选择进行读写的日历、时钟寄存器或片内RAM的具体地 址。这些地址位的具体取值决定了要访问哪个寄存器或RAM单元。
位0(RD/W):读写位。当RD/W=1时,表示下一步操作是读操作;当RD/W=0时,表示下一步操作是写操作
控制寄存器的操作
写入控制命令字:在对DS1302进行读写操作之前,需要先向控制寄存器写入一个控制命令 字。这个命令字通过DS1302的I/O引脚在SCLK时钟的上升沿逐位写入。
读取数据:在写入控制命令字后,可以根据RD/W位的设置来读取或写入数据。如果是读操作,DS1302会在SCLK时钟的下降沿将数据放在I/O引脚上供微控制器读取;如 果是写操作,微控制器则需要在SCLK时钟的上升沿将数据放在I/O引脚上供 DS1302写入。
DS1302日历寄存器(7个)
存储时间数据,采用BCD码格式,支持自动闰年补偿(至2100年):
1、秒寄存器(地址:写0x80/读0x81)
D7:时钟暂停位(CH=1时停止计时,CH=0时启动)。
D6-D0:秒的十位(D6-D4)和个位(D3-D0),范围00-59。
2、分寄存器(地址:写0x82/读0x83)
D7:固定为0。
D6-D0:分的十位(D6-D4)和个位(D3-D0),范围00-59。
3、时寄存器(地址:写0x84/读0x85)
D7:12/24小时模式选择(1=12小时制,0=24小时制)。
D5:AM/PM标志(12小时制下,1=PM,0=AM)。
D4-D0:小时的十位(D4)和个位(D3-D0)范围1-12(12小时制)或0-23(24 小时制)。
4、日寄存器(地址:写0x86/读0x87)
存储日期,范围1-31。
5、月寄存器(地址:写0x88/读0x89)
存储月份,范围1-12。
6、星期寄存器(地址:写0x8A/读0x8B)
存储星期几,范围0-6(0=周日,1=周一,…,6=周六)。
7、年寄存器(地址:写0x8C/读0x8D)
存储年份后两位,范围00-99(对应2000-2099年)。
充电寄存器(1个)
涓流充电寄存器(地址:写0x90/读0x91)
D7-D4:保留位,固定为0。
D3-D2:二极管选择(DS=01/10/11分别表示1/2/禁用二极管)。
D1-D0:电阻选择(RS=00/01/10/11分别对应2kΩ、4kΩ、8kΩ、禁用充电)。
功能:配置外接电池的涓流充电参数(需外接二极管和电阻)。
时钟突发寄存器(1个)
突发模式寄存器(命令字:写0xBE/读0xBF)
功能:支持一次性连续读写所有时钟/RAM寄存器(除充电寄存器外)。
操作:写入0xBE后,DS1302会自动按顺序传输秒、分、时、日、月、星期、年寄存器 的数据。
RAM相关寄存器(31个字节,逻辑上视为独立单元)
独立RAM单元(地址:C0H-FDH)
分类:
单字节读写:每个地址对应1字节RAM(偶地址写,奇地址读,如C0H写/C1H读)。
突发模式读写:通过FEH(写)和FFH(读)命令一次性访问全部31字节RAM。
用途:存储用户自定义数据,与时钟功能无关。
DS1302读写时序介绍
DS1302采用三线串行通信接口(SCLK、I/O、RST)与CPU进行同步通信。无论是读操作还是写操作,都必须由微控制器先向DS1302写入一个命令字发起。这个命令字决定了后续操作是读还是写,以及操作的目标寄存器或RAM单元。
DS1302写时序
起始条件:
RST(或CE)线从低电平变为高电平,表示通信周期的开始。在整个通讯期间,RST 必须保持高电平。
SCLK线在初始状态应为低电平。
写入命令字:
命令字的最高位(D7)必须为逻辑1,如果为0则禁止写入DS1302。
命令字的D6位用于选择操作对象:0表示选择时钟/日历数据,1表示选择RAM数 据。
命令字的D5-D1位(A4-A1)用于指定进行输入或输出的特定寄存器或RAM单元的地址。
命令字的D0位(RD/W)用于选择操作类型:0表示写操作,1表示读操作。
命令字总是从最低位(D0)开始输入,每一位都是在SCLK的上升沿被DS1302读 取。
写入数据:
在写入命令字后,微控制器可以在接下来的8个SCLK脉冲的上升沿依次写入8位 数据。
数据也是从最低位开始写入。
结束条件:
在数据写入完成后,可以将RST线拉低,表示通信周期的结束。
DS1302读时序
起始条件:
与写时序相同,RST线从低电平变为高电平,SCLK线在初始状态为低电平。
写入命令字:
与写时序相同,写入一个用于指定读操作和目标寄存器或RAM单元的命 令字。
读取数据:
在写入命令字后,DS1302会在接下来的8个SCLK脉冲的下降沿依次输出8位数据。
微控制器需要在SCLK的下降沿读取数据,数据从最低位开始输出。
结束条件:
在数据读取完成后,将RST线拉低,表示通信周期的结束。
DS1302硬件电路原理分析
如图所示:
DS1302的主电源脚连接电源电压VCC,给DS1302时钟芯片供电;
DS1302的GND脚接地,确保芯片工作稳定;
DS1302的X1引脚,外接32.768KHZ晶振,为芯片提供计时基准,与X2构成振荡回路;
DS1302的SCLK串行时钟引脚与单片机P36IO管脚进行连接,控制数据传输的同步信号;
DS1302的I/O双向数据引脚与单片机P34管脚进行连接,用于串行数据输入/输出;
DS1302的CE脚复位/片选引脚与但单片机P35进行连接,输出高电平时启动数据传输。低电平I/O呈高阻态;
DS1302软件编程设计
本章所要实现的功能为:在数码管中上实现电子时钟时分秒,格式为XX-XX-XX
关键操作注意事项:
写保护机制:修改时钟/RAM前需先关闭写保护(WP=0),操作完成后可重新开启(WP=1)。
BCD码转换:十位=(BCD/16);个位=(BCD&0x0F);
实现步骤:
第一步:将实现DS1302发送字节函数,函数形参有两个字节参数。第一个参数是控制指令,第二个参数是发送的数据。按照时序图实现函数封装
void DS1302_wriet_byte(u8 command,u8 dat) //DS1302写入字节函数封装
{
u8 i=0;
DS1302_SCLK=0; //时钟线为低电平
_nop_();
DS1302_RET=0; //复位线为低电平
_nop_(); //延时1微秒
DS1302_RET=1; //复位线为高电平,开始通信
_nop_();
for(i=0;i>=1;
DS1302_SCLK=1; //时钟线为高电平
_nop_(); //延时1微秒
DS1302_SCLK=0; //时钟线为低电平
_nop_(); //延时1微秒
}
for(i=0;i>=1;
DS1302_SCLK=1; //时钟线为高电平
_nop_(); //延时1微秒
DS1302_SCLK=0; //时钟线为低电平
_nop_(); //延时1微秒
}
DS1302_RET=0; //复位线为低电平
_nop_();
}
第二步实现DS1302接收字节函数封装,形参为控制指令
u8 DS1302_read_byte(u8 command) //DS1302读取字节函数封装
{
u8 i=0;
u8 temp=0;
u8 dat=0;
DS1302_SCLK=0; //时钟线为低电平
_nop_(); //延时1微秒
DS1302_RET=0; //复位线为低电平
_nop_(); //延时1微秒
DS1302_RET=1; //复位线为高电平,开始通信
_nop_(); //延时1微秒
for(i=0;i>=1;
DS1302_SCLK=1; //时钟线为高电平
_nop_(); //延时1微秒
DS1302_SCLK=0; //时钟线为低电平
_nop_(); //延时1微秒
}
for(i=0;i>=1;
dat|=(temp<<7);
DS1302_SCLK=1; //时钟线为高点平
_nop_(); //延时1微秒
DS1302_SCLK=0; //时钟线为低电平
_nop_(); //延时1微秒
}
DS1302_RET=0; //通信完成
_nop_(); //延时1微秒
DS1302_SCLK=1; //P3.4没有上拉电阻,软件实现上拉
_nop_(); //延时1微秒
DS1302_IO=0;
_nop_(); //延时1微秒
DS1302_IO=1;
_nop_();
return dat;
}
第三步:实现DS1302初始化函数,首先我们要关闭写保护功能,在将秒,分,时,日,月,星期,年数据发送给DS1302实现初始化
u8 wriet_time_dat[7]={0x30,0x03,0x00,0x22,0x09,0x07,0x25};
u8 wriet_time_adder[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //DS1302写入时钟地址指令
u8 read_time_adder[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //DS1302读取时钟地址指令
void DS1302_init(void) //DS1302时钟模块初始化函数
{
u8 i=0;
DS1302_wriet_byte(0x8e,0x00); //发送控制寄存器指令,允许写入数据
for(i=0;i<7;i++)
{
DS1302_wriet_byte(wriet_time_adder[i],wriet_time_dat[i]);
}
DS1302_wriet_byte(0x8e,0x80); //发送控制寄存器指令,不允许写入数据
}
第四步:实现DS1302时钟芯片获取实时计数时间数据封装成函数
void DS1302_read_time(void)
{
u8 i=0;
for(i=0;i<7;i++)
{
wriet_time_dat[i]=DS1302_read_byte(read_time_adder[i]);
}
}
第五步:在主函数中联合数码管现实函数实现显示
#include "TYPEDEF.h" //u8、u16定义
#include "reg52.h" //STC89C52RC
#include "Delay.h" //延时
#include "DIGITALTUBE.h" //数码管
#include "DS1302.h" //DS1302
int main()
{
u8 buffer_time[8];
DS1302_init();
while(1)
{
DS1302_read_time();
buffer_time[0]=Display[wriet_time_dat[2]/16];
buffer_time[1]=Display[wriet_time_dat[2]&0x0f];
buffer_time[2]=0x40;
buffer_time[3]=Display[wriet_time_dat[1]/16];
buffer_time[4]=Display[wriet_time_dat[1]&0x0f];
buffer_time[5]=0x40;
buffer_time[6]=Display[wriet_time_dat[0]/16];
buffer_time[7]=Display[wriet_time_dat[0]&0x0f];
DIGITALTUBE_EEPROM_Display2(buffer_time,1);
}
}
展示效果:
制作不易!喜欢的小伙伴给个小赞赞!喜欢我的小伙伴点个关注!有不懂的地方和需要的资源随时问我哟!