时钟芯片DS1302时序分析、读写代码解析

文章详细介绍了DS1302时钟芯片的原理,包括其引脚功能、SPI通信接口、寄存器地址定义、命令字解析以及读写时序。此外,还提供了读写芯片寄存器的函数示例,帮助理解与DS1302交互的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、DS1302芯片原理图分析

在这里插入图片描述

引脚名称功能
X1、X2外接32.768kHz 晶振,用于内部计时
SCLK和主控通信的时钟线
I/O数据输入输出引脚
CE使能引脚
VCC1接电池供电,保证主板掉电时间能继续走
VCC2主板的电源供电

(1)DS1302芯片的通信接口是SPI协议接口,只有一根数据线,所以是半双工通信;
(2)SPI协议可参考博客:《SPI协议详解(Standard SPI、Dual SPI和Queued SPI)》

2、芯片寄存器地址定义

在这里插入图片描述

(1)与DS1302通信的大致过程:发送命令码表示本次的操作,发送要读取或者写入的数据;
(2)比如:要读取秒就先发送0x81命令码,然后从数据线上接收8bit数据来获取秒数;要写入秒就先发送0x80命令码,然后往数据线上依次写8bit数据来设置秒;
(3)在DS1302中,时间是以8421BCD码进行保存的,简单一点可以理解成低4bit表示一个含义,高4bit表示一个含义;

3、命令字解析日期在芯片内的保存格式

不同的bit含义
bit7必须是逻辑 1. 如果是 0,则禁止对 DS1302写入
bit60表示读写日期,1表示操作DS1302内部31字节的RAM
bit5-bit1寄存器地址
bit00表示写入,1表示读取

4、读写时序分析在这里插入图片描述

(1)起始条件:使能线从低变高,在整个通讯期间使能线必须保持高电平;
(2)先发送命令字,表示此次是什么操作;
(3)从数据线写入/读取数据;
总结:CE线变高表示通信周期的开始;在每个上升沿,DS1302从数据线读取数据;在每个下降沿,DS1302往数据线写入数据;

5、写芯片寄存器的函数

// 向ds1302的内部寄存器addr写入一个值value
void ds1302_write_reg(unsigned char addr, unsigned char value)
{
	unsigned char i = 0;
	unsigned char dat = 0;

	// 第1部分: 时序起始
	SCLK = 0;
	delay();
	RST = 0;
	delay();
	RST = 1;  		// SCLK为低时,RST由低变高,意味着一个大的周期的开始
	delay();
	// 第2部分: 写入第1字节,addr
	//在每个上升沿之前,把要发送给DS1302的数据放到数据线上
	for (i=0; i<8; i++)
	{
		dat = addr & 0x01;	 	// 从低位开始传输的
		DSIO = dat;	 			// 把要发送的bit数据丢到IO引脚上去准备好
		SCLK = 1;		 		 // 制造上升沿,让DS1302把IO上的值读走
		delay();				// 读走之后,一个小周期就完了
		SCLK = 0;				// 把SCLK拉低,是为了给下一个小周期做准备
		delay();
		addr >>= 1;	   			// 把addr右移一位
	}
	// 第3部分: 写入第2字节,value
	for (i=0; i<8; i++)
	{
		dat = value & 0x01;	 	// SPI是从低位开始传输的
		DSIO = dat;	 			// 把要发送的bit数据丢到IO引脚上去准备好
		SCLK = 1;		 		// 制造上升沿,让DS1302把IO上的值读走
		delay();				// 读走之后,一个小周期就完了
		SCLK = 0;				// 把SCLK拉低,是为了给下一个小周期做准备
		delay();
		value = value >> 1;	   	// 把addr右移一位
	}
	// 第4部分: 时序结束
	SCLK = 0;				  	// SCLK拉低为了后面的周期时初始状态是对的
	delay();
	RST = 0;					// RST拉低意味着一个大周期的结束
	delay();
}

6、读芯片寄存器的函数

// 从ds1302的内部寄存器addr读出一个值,作为返回值
unsigned char ds1302_read_reg(unsigned char addr)
{
	unsigned char i = 0;
	unsigned char dat = 0; 		// 用来存储读取到的一字节数据的
	unsigned char tmp = 0;

	// 第1部分: 时序起始
	SCLK = 0;
	delay();
	RST = 0;
	delay();
	RST = 1;  		// SCLK为低时,RST由低变高,意味着一个大的周期的开始
	delay();
	// 第2部分: 写入要读取的寄存器地址,addr
	//在每个上升沿之前,把要发送给DS1302的数据放到数据线上
	for (i=0; i<8; i++)
	{
		dat = addr & 0x01;	 	// 从低位开始传输的
		DSIO = dat;	 			// 把要发送的bit数据丢到IO引脚上去准备好
		SCLK = 1;		 		// 制造上升沿,让DS1302把IO上的值读走
		delay();				// 读走之后,一个小周期就完了
		SCLK = 0;				// 把SCLK拉低,是为了给下一个小周期做准备
		delay();
		addr >>= 1;	   			// 把addr右移一位
	}
	// 第3部分: 读出一字节DS1302返回给我们的值
	dat = 0;
	for (i=0; i<8; i++)
	{
	// 在前面向ds1302写入addr的最后一个bit后,ds1302就会将读取到的寄存器值
	// 的第一个bit放入到IO引脚上,所以我们应该先读取IO再制造下降沿然后继续
	// 读取下一个bit
		tmp = DSIO;
		dat |= (tmp << i);		// 读出来的数值是低位在前的
		SCLK = 1;  				// 由于上面SCLK是低,所以要先拉到高
		delay();
		SCLK = 0;				// 拉低SCLK制造一个下降沿,让DS1302往数据线放下一个数据
		delay();
	}
	// 第4部分: 时序结束
	SCLK = 0;				  	// SCLK拉低为了后面的周期时初始状态是对的
	delay();
	RST = 0;					// RST拉低意味着一个大周期的结束
	delay();

	// 第5部分:解决读取时间是ff的问题,如果读取时间没有FF乱码,可不加
	DSIO = 0;

	return dat;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在起飞的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值