单片机常用芯片总结(二)——DS1302时钟芯片

一、芯片介绍

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。
RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片。

在这里插入图片描述

二、芯片引脚定义

DS1302电路图如下:
在这里插入图片描述
其内部结构框图如下:
在这里插入图片描述

引脚名作用
VCC2主电源
VCC1备用电池
GND电源接地
X1,X232.768kHz晶振
CE芯片使能
IO数据输入/输出
SCLK串行时钟

三、寄存器定义

相关寄存器如下:
在这里插入图片描述
其中,第一行的CH表示时钟暂停控制位,置1表示时钟暂停,置0表示时钟静止;倒数第二行的WP表示write protect(写保护),置1表示写入操作无效;最后一行的TCS用于控制涓流充电,一般不进行设置,其他部分放在第四章进行介绍。

四、命令字

命令字如下:
在这里插入图片描述

  • 第0位表示读还是写(置1表示读,置0表示写);
  • 第1-5位表示地址(秒地址为0,分钟地址为10,…);
  • 第6位表示操作RAM还是时钟CK(置1表示操作RAM,置0表示操作CK);
  • 第7位:固定为1;

举个例子,对时钟操作、秒地址操作、读:
10000001(0x81)
对时钟操作、秒地址操作、写:
10000000(0x80)
这与上方第三章寄存器中的读地址和写地址是对应的。

五、时序图与数据读写

时序图:
在这里插入图片描述
三个引脚:CE(使能端)、SCLK(时钟)和I/O(数据)。

规定:在时钟的上升沿,I/O口的数据将会被写入,在时钟的下降沿,时钟芯片的数据将会被读出。

5.1 单字节写步骤(Write)

Step1:将CE置1;
Step2:命令字(I/O)发两个字节:第一个字节是命令字(先发最低位R/W),第二个字节是数据;【一位一位依次发送】
Step3:SCLK给上升沿,将命令字最低位写入单片机;
Step4:将SCLK置回0;
Step5:SCLK给上升沿,将命令字次低位写入单片机;
Step6:将SCLK置回0;
…(依次循环8次)
Step7:SCLK给上升沿,将数据最低位写入单片机;
Step8:将SCLK置回0;
Step9:SCLK给上升沿,将数据次低位写入单片机;
Step10:将SCLK置回0;
…(依次循环8次)
Step11:将CE置0;
(每个上升沿写入数据)

代码示例:

//单字节写,Command为命令字(地址),Data为要写入的数据
void DS1302_WriteByte(unsigned char Command,Data){
	unsigned char i;
	DS1302_CE=1;
	for(i=0;i<8;i++){
		DS1302_IO=Command&(0x01<<i);//0000 0001 左移
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	for(i=0;i<8;i++){
		DS1302_IO=Data&(0x01<<i);//0000 0001 左移
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;
}

5.2 单字节读步骤(Read)

Step1:将CE置1;
Step2:命令字(I/O)发两个字节:第一个字节是命令字(先发最低位R/W),第二个字节是数据;【一位一位依次发送】
Step3:SCLK给上升沿,将命令字最低位写入单片机;
Step4:将SCLK置回0;
Step5:SCLK给上升沿,将命令字次低位写入单片机;
Step6:将SCLK置回0;
…(依次循环8次)
Step7:SCLK给下降沿,将数据最低位读出;
Step8:将SCLK置回0;
Step9:SCLK给下降沿,将数据次低位读出;
Step10:将SCLK置回0;
…(依次循环8次)
Step11:将CE置0;
Step12:将I/O置0;
(每个下降沿读出数据)

【注意】:需要注意的是,从上述时序图中可以看出,单字节写(Write)有16个脉冲,而单字节读(Read)只有15个脉冲,因为当最后一个命令字的上升沿之后的下降沿数据马上就读出来了,如下图所示。
在这里插入图片描述
因此这里编写代码时需要调整顺序,对DS1302_SCLK先给0再给1,正好进行切分:
在这里插入图片描述

代码示例:

//DS1302读一个字节,Command为命令字(地址),Data为读出的数据
unsigned char DS1302_ReadByte(unsigned char Command){
	unsigned char i,Data=0x00;
	DS1302_CE=1;
	for(i=0;i<8;i++){
		DS1302_IO=Command&(0x01<<i);//0000 0001 左移
//		DS1302_SCLK=1;
//		DS1302_SCLK=0;
		DS1302_SCLK=0;
		DS1302_SCLK=1;		
	}
	for(i=0;i<8;i++){
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data=Data|(0x01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;//清零

	return Data;
}

六、BCD码

6.1 问题描述

Question:在利用DS1302进行操作时,假设我们对秒(0x80)写入初始值1(Data=0x01),每隔一秒它会进行+1,但是当它加到9之后,马上变成16了,这是什么原因呢?
(1——>2——>…——>8——>9——>16——>17——>…)

这里要引入BCD码的概念。
DS1302寄存器数据不是以二进制进行存储的,而是以BCD码进行存储的。
BCD码(Binary Coded Decimal‎),用4位二进制数来表示1位十进制数。

例:0001 0011表示13,1000 0101表示85,0001 1010不合法(因为1010无法表示十进制数)

在十六进制中的体现:0x13表示13,0x85表示85,0x1A不合法

6.2 问题原因

现象的原因:在BCD码中,0000 1001表示数字9,而0001 0000表示数字10,而0001 0000转为十进制数字为16,因此才会在这里造成突变。

再回过头来看一下寄存器,0-3位存的是秒,4-6位存的是10秒
在这里插入图片描述

6.3 解决方案

DS1302写数据时需要将十进制数据转为BCD码的形式,读数据时需要将BCD码转为十进制数据形式。
BCD码转十进制:DEC=BCD/16*10+BCD%16; (2位BCD)
十进制转BCD码:BCD=DEC/10*16+DEC%10; (2位BCD)

解释:BCD/16表示将数据的高四位取出(作为十位),BCD%16表示将低四位取出(作为个位)。


参考:以上相关图片和资源均参考自DS1302时钟芯片的数据手册,关于中英文相关数据手册可以参考资源:https://download.csdn.net/download/didi_ya/85170337


ok,以上便是本文的全部内容了,如果对你有所帮助,记得点个赞哟~

C51单片机是一种经典的8位单片机,而DS1302是一种实时时钟芯片常用单片机系统中。DS1302具有时钟、日历和RAM功能,可以提供准确的时间和日期信息,并且可以通过C51单片机与其他外设进行通信。 DS1302时钟芯片的主要特点包括: 1. 时钟和日历功能:DS1302可以提供准确的时间和日期信息,包括秒、分、时、日、月、年等。 2. 低功耗设计:DS1302采用低功耗设计,可以在电池供电下长时间运行。 3. 串行接口:DS1302通过串行接口与C51单片机进行通信,可以方便地读取和设置时钟和日历信息。 4. RAM功能:DS1302还具有31个字节的RAM,可以用于存储一些临时数据。 使用C51单片机DS1302进行通信,可以实现对时钟和日历的读取和设置。具体步骤如下: 1. 初始化DS1302:设置DS1302的控制寄存器,使其进入读写模式。 2. 读取时钟和日历信息:通过串行接口从DS1302读取秒、分、时、日、月、年等信息。 3. 设置时钟和日历信息:通过串行接口向DS1302写入秒、分、时、日、月、年等信息,实现对时钟和日历的设置。 下面是一个示例代码,演示了如何使用C51单片机DS1302进行通信: ```c #include <reg52.h> sbit DS1302_SCLK = P1^0; // DS1302的串行时钟引脚 sbit DS1302_IO = P1^1; // DS1302的串行数据引脚 sbit DS1302_RST = P1^2; // DS1302的复位引脚 // DS1302写入一个字节数据 void DS1302_WriteByte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { DS1302_IO = dat & 0x01; // 写入最低位 DS1302_SCLK = 1; // 上升沿时钟 DS1302_SCLK = 0; // 下降沿时钟 dat >>= 1; // 右移一位 } } // DS1302读取一个字节数据 unsigned char DS1302_ReadByte() { unsigned char i, dat = 0; for(i=0; i<8; i++) { dat >>= 1; // 右移一位 if(DS1302_IO) // 读取数据 dat |= 0x80; // 最高位为1 DS1302_SCLK = 1; // 上升沿时钟 DS1302_SCLK = 0; // 下降沿时钟 } return dat; } // 初始化DS1302 void DS1302_Init() { DS1302_RST = 0; // 复位DS1302 DS1302_SCLK = 0; // 初始化时钟引脚 DS1302_RST = 1; // 结束复位 DS1302_WriteByte(0x8E); // 写入控制寄存器,使DS1302进入读写模式 DS1302_WriteByte(0x00); // 关闭写保护 } // 读取DS1302时钟和日历信息 void DS1302_ReadTime(unsigned char *time) { unsigned char i; DS1302_WriteByte(0xBF); // 写入读命令 for(i=0; i<7; i++) { time[i] = DS1302_ReadByte(); // 读取时钟和日历信息 } } // 设置DS1302时钟和日历信息 void DS1302_SetTime(unsigned char *time) { unsigned char i; DS1302_WriteByte(0xBE); // 写入写命令 for(i=0; i<7; i++) { DS1302_WriteByte(time[i]); // 设置时钟和日历信息 } } void main() { unsigned char time[7]; // 存储时钟和日历信息 DS1302_Init(); // 初始化DS1302 DS1302_ReadTime(time); // 读取时钟和日历信息 // 在这里可以对time数组进行处理或输出 DS1302_SetTime(time); // 设置时钟和日历信息 while(1); } ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wendy_ya

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

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

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

打赏作者

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

抵扣说明:

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

余额充值