51单片机-第七节-DS1302实时时钟

 一、DS1302介绍:

实时时钟芯片,可对年,月,日,周,时,分,秒计时,是一种集成电路。

二、DS1302原理:

1.寄存器定义:

Command:操作模式,决定要进行的操作是读/写,以及读写内容(秒、分、时。。。)

如下图,其中最左侧的值即为进行对应操作的Command的值。

例:对小时进行读取,Command = 0x85;

2.引脚定义与电路:

其中Vcc1/2是电源,X1/X2是晶振。重点在于后三个。

后三个的作用为输入和读取数据。

其中后三个的原理与_74HC595_完全类似,均为1位1位输入,详细过程见上一节。

CE:总开关,置1时开始工作;

I/O:传入的数据,0/1;

SCLK:来回置01,由0到1时依次传入I/O中的数据。

3.时序:

怎么看?--- 低为0高为1,画一条竖线,在同一竖线上的事是同时发生的。

例:下图中读操作:

将CE = 1,随后使SCLK在01切换,每次上升沿(0到1)依次将I/O口的数据传给R/W、A0等。

(注:R/W-1的8位即为Command)

8次上升后,确定Command,在下降沿(1到0)读取数据给I/O口。

(其中具体8位,每一位代表什么,详见上面的RTC图)

三、集成DS1302:

.h文件:

//时钟初始化
void DS1302_Init();
//数组:储存时钟的时间:年月日时分秒周(0-6)
unsigned char DS1302_Time[];
//用于设置和读取时钟数据,设置会将数组中的时间传入,读取会将时钟数据导出存在上面数组中
void DS1302_SetTime();
void DS1302_ReadTime();

.c文件:

sbit DS1302_SCLK = P3 ^ 6;
sbit DS1302_IO = P3 ^ 4;
sbit DS1302_CE = P3 ^ 5;

#define DS1302_SECOND    0x80
#define DS1302_MINUTE    0x82
#define DS1302_HOUR    0x84
#define DS1302_DATE    0x86
#define DS1302_MONTH    0x88
#define DS1302_DAY    0x8A
#define DS1302_YEAR    0x8C
#define DS1302_WP    0x8E


//储存时钟的时间:年月日时分秒周
unsigned char DS1302_Time[] = { 19,11,16,12,59,55,6 };
//时钟初始化
void DS1302_Init()
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}
//写入数据,参数:Command,Data
void DS1302_WriteByte(unsigned char Command, unsigned char Data)
{
	unsigned char i;
	DS1302_CE = 1;

	for (i = 0; i < 8; i++)
	{
		DS1302_IO = Command & (0x01<<i);
		DS1302_SCLK = 1;
		DS1302_SCLK = 0;
	}	
	for (i = 0; i < 8; i++)
	{
		DS1302_IO = Data & (0x01<<i);
		DS1302_SCLK = 1;
		DS1302_SCLK = 0;
	}

	DS1302_CE = 0;
}
//读取数据,参数:Command,返回值:Data
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i;
	unsigned char Data = 0x00;
	DS1302_CE = 1;
	Command |= 0x01;

	for (i = 0; i < 8; i++)
	{
		DS1302_IO = Command & (0x01 << i);
		DS1302_SCLK = 0;
		DS1302_SCLK = 1;
	}	
	for (i = 0; i < 8; i++)
	{
		
		DS1302_SCLK = 1;
		DS1302_SCLK = 0;
		if (DS1302_IO) { Data |= (0x01<<i); }
	}

	DS1302_CE = 0;
	DS1302_IO = 0;
	return Data;
}
//用于设置和读取时钟数据
void DS1302_SetTime()
{
	DS1302_WriteByte(DS1302_WP, 0x00);
	DS1302_WriteByte(DS1302_YEAR, DS1302_Time[0] / 10 * 16 + DS1302_Time[0] % 10);
	DS1302_WriteByte(DS1302_MONTH, DS1302_Time[1] / 10 * 16 + DS1302_Time[1] % 10);
	DS1302_WriteByte(DS1302_DATE, DS1302_Time[2] / 10 * 16 + DS1302_Time[2] % 10);
	DS1302_WriteByte(DS1302_HOUR, DS1302_Time[3] / 10 * 16 + DS1302_Time[3] % 10);
	DS1302_WriteByte(DS1302_MINUTE, DS1302_Time[4] / 10 * 16 + DS1302_Time[4] % 10);
	DS1302_WriteByte(DS1302_SECOND, DS1302_Time[5] / 10 * 16 + DS1302_Time[5] % 10);
	DS1302_WriteByte(DS1302_DAY, DS1302_Time[6] / 10 * 16 + DS1302_Time[6] % 10);
	DS1302_WriteByte(DS1302_WP, 0x80);
}
void DS1302_ReadTime()
{
	DS1302_Time[0] = DS1302_ReadByte(DS1302_YEAR) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;
	DS1302_Time[1] = DS1302_ReadByte(DS1302_MONTH) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;
	DS1302_Time[2] = DS1302_ReadByte(DS1302_DATE) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;
	DS1302_Time[3] = DS1302_ReadByte(DS1302_HOUR) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;
	DS1302_Time[4] = DS1302_ReadByte(DS1302_MINUTE) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;
	DS1302_Time[5] = DS1302_ReadByte(DS1302_SECOND) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;
	DS1302_Time[6] = DS1302_ReadByte(DS1302_DAY) / 16 * 10 + DS1302_ReadByte(DS1302_YEAR) % 16;

}

四、实战:显示秒:

利用LCD1602调试:

unsigned char Second;
void main()
{
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1, 1, "RTC");

	DS1302_WriteByte(0x80, 0x03);
	while (1)
	{
		Second = DS1302_ReadByte(0x81);
		LCD_ShowNum(2, 1, Second, 3);
	}
}

问题:此时调试会出现问题,由9直接变为16。

原因:DS1302不是以正常的2进制转10进制表示的,而是用BCD码。(详见:寄存器定义)

BCD码:用4位二进制数表示一位10进制数:

例:0001 0011 = 13 ; 1000 0101 = 85 ; 即 0x85 = 85 ;

解决方法:利用LCD1602中显示16进制的函数即可:LCD_ShowHexNum

正确版:

unsigned char Second;
void main()
{
	LCD_Init();
	DS1302_Init();
	LCD_ShowString(1, 1, "RTC");

	DS1302_WriteByte(0x80, 0x03);
	while (1)
	{
		Second = DS1302_ReadByte(0x81);
		LCD_ShowHexNum(2, 1, Second, 3);
	}
}

五:实战:实时时钟:

void main()
{
	LCD_Init();
	DS1302_Init();
	LCD_Showstring(1, 1, "  -  -  ");
	LCD_Showstring(2, 1, "  :  :  ");
	DS1302_SetTime();

	while (1)
	{
		DS1302_ReadTime();
		LCD_ShowNum(1, 1, DS1302_Time[0], 2);
		LCD_ShowNum(1, 4, DS1302_Time[1], 2);
		LCD_ShowNum(1, 7, DS1302_Time[2], 2);
		LCD_ShowNum(2, 1, DS1302_Time[3], 2);
		LCD_ShowNum(2, 4, DS1302_Time[4], 2);
		LCD_ShowNum(2, 7, DS1302_Time[5], 2);
	}
}

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值