江科大51单片机学习笔记之DS1302时钟

一、DS1302介绍

DS1302是由美国DALLAS公司推出的具有涓细电流充电能力低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能

RTC(Real Time Clock):实时时钟,是一种集成电路,通常称为时钟芯片

二、工作原理

典型工作电路如图所示

51-DS1302典型工作电路
管脚名称功能
VCC2连接主电源VCC(VCC有电时,对DS1302供电,同时对备用电池进行充电)
VCC1连接备用电源(VCC没有电时,备用电源对其供电)
X1与X2接32.768KHz的晶振
CE使能信号,CE信号在读写时必须保持高电平
I/O数据输入输出
SCLK串行时钟

DS1302的内部结构框图如图所示:

51-DS1302内部结构框图

X1、X2接外部32.768KHz的晶振,经过相应的逻辑电路处理后,产生1Hz的时钟

31*8RAM是存储时间信息

工作原理类似于74HC595

开发板中DS1302的原理图如图所示

51-DS1302原理图

其中VCC1并没有接备用电源,也就是说无法使用掉点继续运行走时的功能

三、与RTC有关的寄存器
51-DS1302寄存器

注:其中“Day”表示星期

WP:写保护,当WP为1时,不能对上述寄存器进行写操作

91h和90h命令对应的是与涓流充电相关的寄存器,本开发板没有使用备用电源,故这个寄存器不用

命令字:

51-DS1302命令字

上图显示的是命令字,命令字启动每一次数据传输。MSB (位7)必须是逻辑 1,如果是 0,则禁止对 DS1302写入。位 6 在逻辑 0时规定为时钟/日历数据,逻辑 1时为 RAM数据。位 1 至 位 5 表示了输入输出的指定寄存器。LSB (位 0) 在逻辑0时为写操作(输出),逻辑1时为读操作(输入)。命令字以 LSB (位 0)开始总是输入。

例如,要进行读秒,对应的寄存器地址为00000,位0位1,位6位0(读时钟数据),则命令字为0b10000001,即为0x81,与上图的命令字相对应。

四、实验1

(实验前记得把LED点阵屏的那个黄帽改回原处)

现象:在LCD屏幕上显示时钟,包括年、月、日、时、分、秒

1、模拟时序

DS1302.c

#include <REGX52.H>

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

void DS1302_Init()//系统上电时,IO口为高电平
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}
void DS1302_WriteByte(unsigned char command, myData)
{
	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 = myData & (0x01 << i);
		//产生下降沿
		DS1302_SCLK = 1;
		DS1302_SCLK = 0;
	}
	DS1302_CE = 0;
}

unsigned char DS1302_ReadByte(unsigned char command)
{
	unsigned char i;
	unsigned char Data = 0x00;
	DS1302_CE = 1;
	
	
	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;
	return Data;
}
2、测试
#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"

unsigned char second;
void main()
{
	LCD_Init();
	DS1302_Init();
	DS1302_WriteByte(0x8e,0x00);//关闭写保护,没有这一行则显示255
	LCD_ShowString(1,1,"RTC");
	DS1302_WriteByte(0x80,0x03);

	second = DS1302_ReadByte(0x81);
	LCD_ShowNum(2,1,second,3);
	while(1)
	{
		
	}
}

当循环显示秒数的时候,即

while(1)
	{
		second = DS1302_ReadByte(0x81);
		LCD_ShowNum(2,1,second,3);
	}

会出现显示数字从9直接跳到16的情况,而不是显示10。这是因为DS1302采用的是BCD(Binary Coded Decimal)码,即用4位二进制数来表示1位十进制数。例如0001 0011表示13(前4位表示1,后四位表示3),1000 0101表示85,0001 1010不合法。

而9对应的BCD码为0000 1001,10对应的BCD码为0001 0000,而这个二进制数被理解为16,故LCD显示16。

所以需要进行BCD码和十进制的转换

•BCD码转十进制:DEC=BCD/16*10+BCD%16; (2位BCD)

•十进制转BCD码:BCD=DEC/10*16+DEC%10; (2位BCD)

LCD_ShowNum(2,1,second/16*10+second%16,3);
3、定义时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time = {23,7,13,23,59,10,4};
4、根据上图写命令进行宏定义,目的是为了增加可读性和可维护性
//寄存器写入地址/指令定义
#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

由于读命令与写命令只是最后一位不同,将command最后一位或上一个1,就可以将命令的最后一位变为1,即将写命令转换成读命令,这样就可以用写命令来当做DS1302_ReadByte函数的形参了,也就是不需要单独定义读命令了

command |= 0x01;
5、定义DS1302_SetTime函数,设置时间
void DS1302_SetTime()
{
	DS1302_WriteByte(DS1302_WP,0x00);//取消写保护
	DS1302_WriteByte(DS1302_YEAR,DS1302_Time[0]/10*16+DS1302_Time[0]%10);//十进制转BCD码后写入
	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,0x00);//打开写保护
}
6、定义DS1302_ReadTime函数,读出时间
void DS1302_ReadTime()
{
	unsigned char Temp;//用于临时存储读出结果
	
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}
7、DS1302_Time数组的外部声明

因为DS1302_Time数组需要在主函数中调用,所以该数组需要声明为extern(在DS1302.h中)

extern unsigned char DS1302_Time[];
8、主函数

现象:LCD对应位置能正常显示时间

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
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);
	}
}
五、实验2

在实验1的基础上通过按键可以对时间进行调节

1、添加按键模块代码和定时器模块代码

Key.cKey.h

Timer.cTimer.h

2、定义全局变量keyNum,用于接收按键按下的键值(通过GetKeyNum获取)
unsigned char keyNum;

keyNum = GetKeyNum();
3、创建TimeShow函数,将显示时间的代码放入
void TimeShow()
{
	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、创建TimeSet函数,用于按键设置时间

创建变量timeSet_select用于选择设置哪个时间量

timeSet_select=0设置年份,timeSet_select=1设置月份,timeSet_select=2设置天数

timeSet_select=3设置小时,timeSet_select=4设置分钟,timeSet_select=5设置秒数

unsigned char timeSet_select;

与江科大视频中的日期越界的判断方式不同,我使用了一个数组month_day来保存每个月的天数,进而再进行判断

unsigned char month_day[]={31,28,31,30,31,30,31,31,30,31,30,31};
void TimeSet()
{
	if(keyNum == 2)//按键2按下
	{
		timeSet_select++;
		timeSet_select %= 6;//越界清零
	}
	if(keyNum == 3)//按键3按下
	{
		DS1302_Time[timeSet_select]++;//时间设置位数值加1
		//越界判断
		//年份越界
		DS1302_Time[0] %= 100;//或 if(DS1302_Time[0]>99){DS1302_Time[0]=0;}
		//判断是否是闰年,若是,则2月为29天
		month_day[1] = DS1302_Time[0] % 4 == 0 ? 29 : 28;
		//月份越界
		DS1302_Time[1] = DS1302_Time[1] > 12 ? 1 : DS1302_Time[1];//或 if(DS1302_Time[1]>12){DS1302_Time[1]=1;}
		//日期越界
		if(DS1302_Time[2] > month_day[DS1302_Time[1] - 1]){DS1302_Time[2] = 1;}
		//时
		if(DS1302_Time[3] > 23){DS1302_Time[3] = 0;}
		//分
		if(DS1302_Time[4] > 59){DS1302_Time[4] = 0;}
		//秒
		if(DS1302_Time[5] > 59){DS1302_Time[5] = 0;}
	}
	if(keyNum == 4)
	{
		DS1302_Time[timeSet_select]--;
		//年
		if(DS1302_Time[0] < 0){DS1302_Time[0] = 99;}
		month_day[1] = DS1302_Time[0] % 4 == 0 ? 29 : 28;
		//月
		if(DS1302_Time[1] < 0){DS1302_Time[1] = 12;}
		//日
		if(DS1302_Time[2] < 1){DS1302_Time[2] = month_day[DS1302_Time[1] - 1];}
		//时
		if(DS1302_Time[3] < 0){DS1302_Time[3] = 23;}
		//分
		if(DS1302_Time[4] < 0){DS1302_Time[4] = 59;}
		//秒
		if(DS1302_Time[5] < 0){DS1302_Time[5] = 59;}
	}
}

**注意:**由于之前定义的DS1302_Time数组是unsigned char类型的,而数组元素从0再减1时变为255,而不是-1,所以这里需要将DS1302_Time数组改为char类型的

char DS1302_Time[] = {23,7,13,23,59,10,4};
5、模式

创建一个变量mode用于表明是哪个模式,mode=0是显示时间模式,mode=1是设置时间模式

unsigned char mode;

按键1用于改变模式。主函数如下:

void main()
{
	LCD_Init();
	DS1302_Init();
	Timer0Init();
	
	LCD_ShowString(1,1,"  -  -");
	LCD_ShowString(2,1,"  :  :");
	DS1302_SetTime();
	while(1)
	{
		keyNum = GetKeyNum();
		if(keyNum == 1)//按键1按下
		{
			if(mode==0)
			{
				mode=1;
				timeSet_select=0;//让每次设置时间都从年份开始
			}
			else
			{
				mode=0;
				DS1302_SetTime();//将设置的时间保存
			}
		}
		mode == 1?TimeSet():TimeShow();
	}
}
6、设置闪烁功能

通过定时器0实现,每隔一秒对应的时间位置显示为空白,这样就实现了每隔一秒闪烁一次的功能

创建一个变量用于表明是否闪烁的标志

unsigned char timeSet_flashFlag;

定时器0的中断处理函数如下:

//定时器0的中断处理函数
void Timer0_Routine() interrupt 1
{
	static unsigned int count = 0;
	//重新赋值计数器,因为计数器溢出后会变为0,要1ms产生一次中断,需要重新给计数器赋值为64535
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	//1ms产生一次中断,每次中断count+1,1000次后再进行处理,此时处理的时间间隔就为1s
	count++;
	if(count >= 1000)
	{
		count = 0;
		timeSet_flashFlag = !timeSet_flashFlag;
	}
	
}

在TimeSet函数添加如下代码:

如果闪烁标志为1,则显示空格,否则显示原时间

//更新显示,根据timeSet_select和timeSet_flashFlag判断可完成闪烁功能
	if(timeSet_select==0 && timeSet_flashFlag==1){LCD_ShowString(1,1,"  ");}
	else {LCD_ShowNum(1,1,DS1302_Time[0],2);}
	if(timeSet_select==1 && timeSet_flashFlag==1){LCD_ShowString(1,4,"  ");}
	else {LCD_ShowNum(1,4,DS1302_Time[1],2);}
	if(timeSet_select==2 && timeSet_flashFlag==1){LCD_ShowString(1,7,"  ");}
	else {LCD_ShowNum(1,7,DS1302_Time[2],2);}
	if(timeSet_select==3 && timeSet_flashFlag==1){LCD_ShowString(2,1,"  ");}
	else {LCD_ShowNum(2,1,DS1302_Time[3],2);}
	if(timeSet_select==4 && timeSet_flashFlag==1){LCD_ShowString(2,4,"  ");}
	else {LCD_ShowNum(2,4,DS1302_Time[4],2);}
	if(timeSet_select==5 && timeSet_flashFlag==1){LCD_ShowString(2,7,"  ");}
	else {LCD_ShowNum(2,7,DS1302_Time[5],2);}
7、总结

main.c

#include <REGX52.H>
#include "LCD1602.h"
#include "DS1302.h"
#include "Key.h"
#include "Timer.h"

unsigned char keyNum, timeSet_select, mode, timeSet_flashFlag;
unsigned char month_day[]={31,28,31,30,31,30,31,31,30,31,30,31};

void TimeShow()
{
	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);
}

void TimeSet()
{
	if(keyNum == 2)//按键2按下
	{
		timeSet_select++;
		timeSet_select %= 6;//越界清零
	}
	if(keyNum == 3)//按键3按下
	{
		DS1302_Time[timeSet_select]++;//时间设置位数值加1
		//越界判断
		//年份越界
		DS1302_Time[0] %= 100;//或 if(DS1302_Time[0]>99){DS1302_Time[0]=0;}
		//判断是否是闰年,若是,则2月为29天
		month_day[1] = DS1302_Time[0] % 4 == 0 ? 29 : 28;
		//月份越界
		DS1302_Time[1] = DS1302_Time[1] > 12 ? 1 : DS1302_Time[1];//或 if(DS1302_Time[1]>12){DS1302_Time[1]=1;}
		//日期越界
		if(DS1302_Time[2] > month_day[DS1302_Time[1] - 1]){DS1302_Time[2] = 1;}
		//时
		if(DS1302_Time[3] > 23){DS1302_Time[3] = 0;}
		//分
		if(DS1302_Time[4] > 59){DS1302_Time[4] = 0;}
		//秒
		if(DS1302_Time[5] > 59){DS1302_Time[5] = 0;}
	}
	if(keyNum == 4)
	{
		DS1302_Time[timeSet_select]--;
		//年
		if(DS1302_Time[0] < 0){DS1302_Time[0] = 99;}
		month_day[1] = DS1302_Time[0] % 4 == 0 ? 29 : 28;
		//月
		if(DS1302_Time[1] < 0){DS1302_Time[1] = 12;}
		//日
		if(DS1302_Time[2] < 1){DS1302_Time[2] = month_day[DS1302_Time[1] - 1];}
		//时
		if(DS1302_Time[3] < 0){DS1302_Time[3] = 23;}
		//分
		if(DS1302_Time[4] < 0){DS1302_Time[4] = 59;}
		//秒
		if(DS1302_Time[5] < 0){DS1302_Time[5] = 59;}
	}
	//更新显示,根据TimeSetSelect和TimeSetFlashFlag判断可完成闪烁功能
	if(timeSet_select==0 && timeSet_flashFlag==1){LCD_ShowString(1,1,"  ");}
	else {LCD_ShowNum(1,1,DS1302_Time[0],2);}
	if(timeSet_select==1 && timeSet_flashFlag==1){LCD_ShowString(1,4,"  ");}
	else {LCD_ShowNum(1,4,DS1302_Time[1],2);}
	if(timeSet_select==2 && timeSet_flashFlag==1){LCD_ShowString(1,7,"  ");}
	else {LCD_ShowNum(1,7,DS1302_Time[2],2);}
	if(timeSet_select==3 && timeSet_flashFlag==1){LCD_ShowString(2,1,"  ");}
	else {LCD_ShowNum(2,1,DS1302_Time[3],2);}
	if(timeSet_select==4 && timeSet_flashFlag==1){LCD_ShowString(2,4,"  ");}
	else {LCD_ShowNum(2,4,DS1302_Time[4],2);}
	if(timeSet_select==5 && timeSet_flashFlag==1){LCD_ShowString(2,7,"  ");}
	else {LCD_ShowNum(2,7,DS1302_Time[5],2);}
}
void main()
{
	LCD_Init();
	DS1302_Init();
	Timer0Init();
	
	LCD_ShowString(1,1,"  -  -");
	LCD_ShowString(2,1,"  :  :");
	DS1302_SetTime();
	while(1)
	{
		keyNum = GetKeyNum();
		if(keyNum == 1)//按键1按下
		{
			if(mode==0)
			{
				mode=1;
				timeSet_select=0;//让每次设置时间都从年份开始
			}
			else
			{
				mode=0;
				DS1302_SetTime();//将设置的时间保存
			}
		}
		mode == 1?TimeSet():TimeShow();
	}
}

//定时器0的中断处理函数
void Timer0_Routine() interrupt 1
{
	static unsigned int count = 0;
	//重新赋值计数器,因为计数器溢出后会变为0,要1ms产生一次中断,需要重新给计数器赋值为64535
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	//1ms产生一次中断,每次中断count+1,1000次后再进行处理,此时处理的时间间隔就为1s
	count++;
	if(count >= 1000)
	{
		count = 0;
		timeSet_flashFlag = !timeSet_flashFlag;
	}
}

DS1302.h

#ifndef __DS1302_H__
#define __DS1302_H__

extern char DS1302_Time[];

void DS1302_Init();
void DS1302_WriteByte(unsigned char command, myData);
unsigned char DS1302_ReadByte(unsigned char command);
void DS1302_SetTime();
void DS1302_ReadTime();

#endif

DS1302.c

#include <REGX52.H>

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

//寄存器写入地址/指令定义
#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

char DS1302_Time[] = {23,7,13,23,59,10,4};

void DS1302_Init()//系统上电时,IO口为高电平
{
	DS1302_CE = 0;
	DS1302_SCLK = 0;
}

void DS1302_WriteByte(unsigned char command, myData)
{
	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 = myData & (0x01 << i);
		//产生下降沿
		DS1302_SCLK = 1;
		DS1302_SCLK = 0;
	}
	DS1302_CE = 0;
}

unsigned char DS1302_ReadByte(unsigned char command)
{
	unsigned char i;
	unsigned char Data = 0x00;
	DS1302_CE = 1;
	//读命令与写命令只是最后一位不同,将command最后一位或上一个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;	//读取后将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);//十进制转BCD码后写入
	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,0x00);//打开写保护
}

void DS1302_ReadTime()
{
	unsigned char Temp;//用于临时存储读出结果
	
	Temp=DS1302_ReadByte(DS1302_YEAR);
	DS1302_Time[0]=Temp/16*10+Temp%16;//BCD码转十进制后读取
	
	Temp=DS1302_ReadByte(DS1302_MONTH);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_DATE);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_HOUR);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_MINUTE);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_SECOND);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	
	Temp=DS1302_ReadByte(DS1302_DAY);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}

更多51单片机笔记见主页

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值