DS1302基础知识(一)

 


DS1302实时时钟模块

芯片手册:datasheet pdf 索引DS1302数据表

时钟芯片DS1302含有实时时钟/日历和31字节静态RAM。与单片机之间采用3线同步串行方式进行通信。

1、DS1302的引脚

PIN 引脚说明
X1、X2 晶振接入引脚,晶振频率为32.768kHz
RST 复位引脚,高电平启动输入输出,低电平结束输入输出
I/O 数据输入输出引脚
SCLK 串行时钟输入引脚
GND 接地引脚
Vcc1,Vcc2 工作电源、备份工作电源

2、命令字节

命令字节如下图所示:

每个数据传输都是由一个命令字节发起,MSB(Bit7)必须是逻辑1。如果它是0,对DS1302的写入将被禁用。

第6位如果逻辑为0,则指定时钟/日历数据;如果逻辑为1,则指定RAM数据。

第1位到第五位指定要输入或输出的寄存器,LSB(第0位)指定逻辑0时的写操作或逻辑0时的读操作(输出)。

命令字节总是从LSB开始输入(第0位)

3、复位和时钟控制

所有的数据传输都是通过驱动RST高输入来启动的。

RST输入有两个功能:

  • 首先RST打开控制逻辑,允许访问地址/命令序列的移位寄存器。
  • 第二,RST信号提供了一种终止单字节或多字节数据传输的方法。

时钟周期是一个由下降边和上升边组成的序列。对于数据输入,数据必须在时钟上升沿有效数据位在时种下沿输出。(即写入数据是在时钟上升沿,读出数据在时钟下降沿)

如果RST输入低,所有数据传输终止,IO引脚进入高阻状态,

上电时,RST必须是逻辑0,知道Vcc > 2.0V。同时,当RST被驱动到逻辑1时,SCLK必须处于逻辑0。(看下面的输入输出的图,一开始都是RST低,SCLK低,然后RST高;然后才是开始数据传输)

4、数据输入输出

(1)数据输入

在八个SCLK周期输入一个写命令字节之后(看上图I/O那行,首先是8个SCLK周输入写命令字节),

在接下来的8个SCLK周期的上升沿上输入一个数据字节(注意看上图每次字节输入都是从上升沿),

如果数据从位0开始输入,则忽略额外的SCLK周期。

示例:

  • 每次CLK拉低,IO给值,CLK拉高
  • dat每次都是从最低位给IO值,所以dat要右移1位
void DS1302_WByte(uchar dat)
{
	uchar i;
	for(i = 8; i > 0; i--)			// 从图中也可以看到,数据是从D0开始输入的
	{
		DS1302_CLK = 0;				// 时钟线给低电平
		Delay4Us();					// 延时
		DS1302_IO = dat & 0x01;		// IO输入一个字节
		DS1302_CLK = 1;				// 时钟线拉高
		dat = dat >> 1;				// 数据右移一位
	}
}

(2)数据输出

在输入一个读命令字节的8个SCLK周期之后,在接下来的8个SCLK周期的下降边缘输出一个数据字节。

请注意,要传输的第一个数据位发生在写入命令字节的最后一位之后的第一个下降沿

额外的SCLK周期重传数据字节,只要RST保持高,它们就会在不经意间发生。允许连续突出模式的读能力。此外,IO引脚在SCLK的每个上升边缘上是三列的。数据从第0位开始输出。

uchar DS1302_RByte(void)
{
	uchar i,temp = 0;
	DS1302_IO = 1;
	for(i=8; i>0; i--)
	{
		DS1302_CLK=0;				// CLK时钟拉低,准备取数据
		Delay4Us();
		temp = temp >> 1;			// 先低位在高位,所以每次需要右移
		if( DS1302_IO == 1)			// 当IO引脚是高电平,则数据位或操作0x80
		{
			temp = temp | 0x80;	
		}
		DS1302_CLK=1;
		Delay4Us();
	}
	return temp;
}

5、其他示例函数

1)写数据到ds1302某地址

void DS1302_W_Addr_Dat(uchar addr, uchar dat)
{
	DS1302_RST = 0;
	DS1302_CLK = 0;
	DS1302_RST = 1;		// 一开始的三行原因见 3、复位和时钟控制那边最后一句话加粗部分
	DS1302_WByte(addr);			// 地址,命令
	DS1302_WByte(dat);			// 写1字节数据,一个字节等于8个位
	DS1302_CLK = 1;
	DS1302_RST = 0;
}

2)读ds1302某地址的数据

void DS1302_R_All(uchar addr)
{
	uchar dat;
	DS1302_RST = 0;
	DS1302_CLK = 0;
	DS1302_RSt = 1;
	DS1302_WByte(addr | 0x01);			// 地址,命令
	dat = DS1302_RByte();				// 读1字节数据
	DS1302_CLK=1;
	DS1302_RST=0;
	return(dat);
}

3)读时间和日期

寄存器地址

示例程序

// 定义结构体
typedef struct
{
	uchar Second;
	uchar Minute;
	uchar Hour;
	uchar Week;
	uchar Day;
	uchar Month;
	uchar Year;
	uchar DataString[9];
	uchar TimeString[9];
}TIMETYPE;

// 这边表示的是寄存器的地址
#define DS1302_SECOND      0x80
#define DS1302_MINUTE      0x82
#define DS1302_HOUR        0x84
#define DS1302_WEEK		   0x8A
#define DS1302_DAY		   0x86
#define DS1302_MONTH       0x88
#define DS1302_YEAR		   0x8C

// 0x70=0111 0000, 0x0F=0000 1111
// 从上面寄存器地址图可知,高四位是存放十位上的数,第四位是存放个位的数
void DS1302_R_All( TIMETYPE *TIME)
{
	uchar Rtemp;
	Rtemp = DS1302_R_Addr(DS1302_SECOND);				// 秒
	Time->Second = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 
	Rtemp = DS1302_R_Addr(DS1302_MINUTE);				// 分钟
	Time->Minute = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 
	Rtemp = DS1302_R_Addr(DS1302_HOUR);					// 小时
	Time->Hour = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 
	Rtemp = DS1302_R_Addr(DS1302_DAY);					// 天
	Time->Day = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 	
	Rtemp = DS1302_R_Addr(DS1302_WEEK);					// 星期
	Time->Week = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 	
	Rtemp = DS1302_R_Addr(DS1302_MONTH);				// 月
	Time->Month = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 	
    Rtemp = DS1302_R_Addr(DS1302_YEAR);					// 年
	Time->Year = ((Rtemp&0x70)>>4)*10 + (Rtemp & 0x0F); 
}

4)ds1302初始化

void DS1302_Init(void)

{
	uchar Second;
	DS1302_RST = 0;
	DS1302_CLK = 0;
	Second = DS1302_R_Addr(DS1302_SECOND);
	DS1302_W_Addr_Dat(0x8e, 0x00);
	DS1302_W_Addr_Dat(0x80, Second & 0x7f);
	DS1302_W_Addr_Dat(0x90, 0xa6);				// DS1302寄存器配置一个二极管,4kΩ充电电阻
	DS1302_W_Addr_Dat(0x8E, 0x80);
}
posted @   乞力马扎罗山的雪  阅读(1087)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示

目录导航