蓝桥杯单片机学习记录(7)(DS1302实时时钟)

DS1302实时时钟

原理图

DS1302封装图

DS1302主要性能

  1. SD1302实时时钟能够计算2100年之前的秒、分、时、日、日期、星期、月、年(闰年可自动调整),还可以通过配置AM/PM来决定采用24小时格式还是12小时格式。
  2. 内部含有31个字节静态数据存储RAM,可供用户访问。
  3. 采用串行I/O通信方式,使得管脚数量最少,简单SPI3线接口。
  4. 工作电压范围宽:2.0~5.5V.
  5. 工作电流小,功耗低:工作电压为2.0V时,小于300NA.
  6. 时钟或RAM数据的读/写有两种传送方式:单字节传送和多字节传送方式。
  7. 采用8脚DIP封装(双列直插式封装)或SOIC封装。
  8. 供电电压Vcc=5V时,与标准TTL兼容,可与单片机通信。
  9. 具有涓流充电能力。
  10. 采用主电源和备份电源双电源供应。备用电源可以是电池或者大电容,确保在系统掉电的情况下,始终还可以走。

各引脚功能:

  • Vcc2 :主电源引脚,当Vcc2比Vcc1高0.2V以上时,DS1302由Vcc2供电,当Vcc2低于Vcc1时,由Vcc1供电。
  • X1  X2:这两个引脚需要接一个32.768K的晶振,给DS1302提供一个基准。特别注意,要求这个晶振的引脚负载电容必须是6pF,而不是要加6pF的电容。如果要使用有源晶振的话,接到X1上即可,X2悬空。
  • GND:接地。
  • CE:DS1302的使能输入引脚。当读写DS1302时,这个引脚必须是高电平,DS1302这个引脚内部有一个40K的下拉电阻。
  • I/O:这个引脚是一个双向通信引脚。读写数据都是通过这条引脚完成。DS1302这个引脚内部有一个40K的下拉电阻。
  • SCLK:输入引脚。SCLK是用来作为通信的时钟信号,DS1302这个引脚内部有一个40K的下拉电阻。
  • Vcc1:备用电源引脚。

其中只有5脚(CE使能)、6脚(I/O)、7脚(SCLK时钟)需接到单片机I/O口上。

DS1302的典型电路:

DS1302寄存器

1.命令字节 

DS1302的一条指令一个字节共8位,其中第7位固定为1,0无效,第6位是RAM/CLOCK选择端,第5位到第1位是寄存器的地址,第0位是读写控制位。

2.寄存器

时钟日历寄存器包含在7个读/写寄存器内,读/写寄存器的数据是BCD码。

  1. 寄存器0:最高位CH时钟停止标志位,通过该位判断时钟在单片机系统掉电后是否正常运(0为有备用电源,正常运行) 。剩余7位的高三位是秒的十位,低四位是秒的个位。由于DS1302内部是BCD码,秒的十位最大是5,所以为3个二进制位。
  2. 寄存器1:最高位未使用,剩余7位的高三位是分钟的十位,低四位是分钟的个位。
  3. 寄存器2:BIT7为1代表采用12小时制,为0代表采用24小时制;BIT6固定为0里BIT5在12小时制下,0表示上午,1表示下午;在24小时制下,和BIT4一起表示小时的十位;低四位表示小时的个位。
  4. 寄存器3:高两位固定为0,BIT5和BIT4是日期的十位,低四位是日期的个位。
  5. 寄存器4:高三位固定为0,BIT4是月的十位,第四位是月的个位。
  6. 寄存器5:高五位固定是0,第三位表示星期。
  7. 寄存器6:高四位表示年的十位,低四位表示年的个位。00~99指的是2000年~2099年。
  8. 寄存器7:最高位为写保护位。如果此位为1,则禁止给任何其它寄存器或者31个字节的RAM写数据,因此在写数据之前,此位必须写成0。

DS1302中附加31字节RAM的地址:

突发模式(Brust)

在读取这7个寄存器的过程中,在一个极端的情况下会出现,比如当前时间是00:00:59,我们先读秒,是59,然后再去读分钟,而就在读完秒到还未开始读分钟的这个时间段内,刚好时间进位了,变成00:01:00这个时间,我们读到的分钟就是01,这个时间显然是错误的,出现这种问题的概率极小,但却是实实在在可能存在的。

解决方案:写操作用0XBE,读操作用0XBF,DS1302收到指令后,会自动识别出来是Brust模式,马上把所有的8个字节同时锁存到另外的8个寄存器缓冲区内,这样时钟继续走,而我们读数据是从另外一个缓冲区内读取的。同理,用Brust写数据,也是先写到这个缓冲区内,最终DS1302会把这个缓冲区内的数据一次性送到它的始终寄存器内。 

用Brust突发模式连续写入8个寄存器数据

//向DS1302中写入一个字节数据
void DS1302WriteByte(uchar dat)
{
	uchar i;
	for(i = 0; i < 8; i++)
	{
		TSCLK = 0;//拉低时钟总线
		TIO = dat & 0x01;//写一个字节,从最低位开始
		TSCLK = 1;//拉高时钟总线,产生上升沿数据被DS1302读走
		dat >>= 1;
	}
}

void DS1302_BrustWrite(uchar *dat)
{
	uchar i;
	TRST = 0;
	TSCLK = 0;
	TRST = 1;
	DS1302WriteByte(0XBE);
	for(i = 0; i < 8; i++)
		DS1302WriteByte(dat[i]);
	TRST = 0;
}

用Brust突发模式连续读取8个寄存器数据

//从DS1302中读一个字节
uchar DS1302ReadByte()
{
	uchar i,dat;
	for(i = 0; i < 8; i++)
	{
		TSCLK = 0;//拉低时钟总线,产生下降沿,DS1302把数据放到TIO上
		dat >>= 1;
		if(TIO) dat |= 0x80;//读取数据
		TSCLK = 1;//拉高时钟总线,以备下一次产生下降沿
	}
	TIO = 0;//释放数据线
	return dat;
}

void DS1302_BrustRead(uchar *dat)
{
	uchar i;
	TRST = 0;
	TSCLK = 0;
	TRST = 1;
	DS1302WriteByte(0XBF);
	for(i = 0; i < 8; i++)
		dat[i] =  DS1302ReadByte();
	TRST = 0;
}

DS1302的读写时序,数据的传输是从最低位开始,数据是以位(BIT)为单位依次写入或读出,读写数据操作中SCLK上升沿时写入数据下降沿时执行读出数据

读数据:CE端从低到高的一个上升沿开始允许开始读数据,拉低CE端则禁止读写数据,开始的8个SCLK周期,写命令字节,数据的后8个SCLK周期读出数据。

//从DS1302中读数据
uchar Read_DS1302(uchar cmd)
{
	uchar dat;
	TRST = 0;
	TSCLK = 0;
	TRST = 1;
	DS1302WriteByte(cmd);
	dat = BCD_chg_DAT(DS1302ReadByte());
	return dat;
}

写数据:CE端从低到高的一个上升沿开始允许开始写数据,拉低CE端则禁止读写数据,开始的8个SCLK周期,写命令字节,数据后的8个SCLK周期写入数据。

//向DS1302中写数据
void Write_DS1302(uchar cmd,uchar dat)
{
	TRST = 0;//拉低使能端
	TSCLK = 0;//拉低时钟总线
	TRST = 1;//拉高使能端,产生上升沿开始写数据
	DS1302WriteByte(cmd);
	DS1302WriteByte(DAT_chg_BCD(dat));
	TRST = 0;
}

BCD码的转换

//十进制转BCD
uchar DAT_chg_BCD(uchar dat)
{
	uchar dat1, dat2;
	dat1 = dat / 10;
	dat2 = dat % 10;
	dat2 = dat2 + dat1 * 16;
	return dat2;
}

//BCD转十进制
uchar BCD_chg_DAT(uchar dat)
{
	uchar dat1, dat2;
	dat1 = dat / 16;
	dat2 = dat % 16;
	dat2 = dat2 + dat1 * 10;
	return dat2;
}

 设置/获取时钟

//设置DS1302初值
void Set_DS1302()
{
	uchar i;
	Write_DS1302(0x8e,0x00);
	for(i = 0; i < 7; i++)
		Write_DS1302(WriteReg[i],Time[i]);
	Write_DS1302(0x8e,0x80);
}

//获取DS1302的值
void Get_DS1302()
{
	uchar i;
	for(i = 0; i < 7; i++)
		Time[i] = Read_DS1302(ReadReg[i]);
}

onewire.h

#ifndef _ONEWIRE_H_
#define _ONEWIRE_H_

#include <STC15F2K60S2.H>
#include <intrins.h>

sbit TRST = P1^3;
sbit TSCLK = P1^7;
sbit TIO = P2^3;

#define uchar unsigned char

extern unsigned char Time[7];

//ds1302.c
unsigned char DAT_chg_BCD(unsigned char dat);
unsigned char BCD_chg_DAT(unsigned char dat);
void DS1302WriteByte(unsigned char dat);
unsigned char DS1302ReadByte();
void Write_DS1302(unsigned char cmd,unsigned char dat);
unsigned char Read_DS1302(unsigned char cmd);
void Set_DS1302();
void Get_DS1302();

#endif

初始化时间读/写寄存器

uchar Time[7] = {55,59,23,1,2,2,22};
//2022年星期二2月2号23时59分55秒
uchar ReadReg[7] = {0X81, 0X83, 0X85, 0X87, 0X89, 0X8B, 0X8D};
uchar WriteReg[7] = {0X80, 0X82, 0X84, 0X86, 0X88, 0X8A, 0X8C};
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Wu小燕呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值