【蓝桥杯】DS1302时钟芯片学习笔记

目录

1、DS1302简介

1.1功能

DS1302滴充电计时芯片包含实时时钟/日历和31字节的静态RAM。它通过一个简单的串行接口与一个微处理器进行通信。实时时钟/日历提供秒、分钟、小时、天、日期、月和年的信息。月底日期会自动对不足31天的月份进行调整,包括对闰年的修正。该时钟以24小时或12小时的形式运行,并具有AM/PM指示器。

1.2通信方式

通过使用同步串行通信,简化了将DS1302与微处理器的接口。只需要三根线就可以与时钟/RAM通信:CE(RST)、I/O(SDA)和SCLK(SCK)。数据可以在一次或多达31字节的突发传输到时钟/RAM1字节。DS1302被设计为在非常低的功率下工作,并保留小于1μW的数据和时钟信息。

1.3电路连接图

典型的操作电路图:
【蓝桥杯】DS1302时钟芯片学习笔记
蓝桥杯CT107D单片机连接图:
【蓝桥杯】DS1302时钟芯片学习笔记
SCK=P1^7;
SDA=P2^3; //进行同步串行通信
RST = P1^3; // DS1302复位

2、DS1302通信时序

1.1单字节写入时序
【蓝桥杯】DS1302时钟芯片学习笔记
1.2单字节写入
【蓝桥杯】DS1302时钟芯片学习笔记

可以看到写入操作和读取操作都是CE拉高电平,然后在在SCLK的16个时钟周期完成的,数据线I/0发送了两个字节的数据,第一个是命令字节,用于告诉DS1302接下来的操作,在每个时钟上升沿由低位到高位地传输8个数据位,第二个字节是数据字节,从低位到高位逐位传输。拉低CE结束传输
因此我们可以据此编写程序:(这里参考蓝桥杯官方代码,对着看一手,比赛也是直接用这个代码)

void Write_Ds1302(unsigned  char temp) //单字节写入,这里未拉高CE,下个函数执行
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;//给低电平
		SDA=temp&0x01;//将数据放到SDA(IO)数据线上,当上升沿产生时发送
		temp>>=1; //下一个数据
		SCK=1;//给高电平,从低电平变到高电平将产生一个上升沿!
	}
}   
void Write_Ds1302_Byte( unsigned char address,unsigned char dat ) //写入操作,命令和数据两个字节    
{
 	RST=0;	_nop_();//复位CE,短暂延迟消除可能存在的下降沿
 	SCK=0;	_nop_();//复位SCK,短暂延迟消除可能存在的下降沿
 	RST=1; 	_nop_();  //拉高CE,打开数据通道,短暂延迟消除上升沿
 	Write_Ds1302(address);	//写入命令
 	Write_Ds1302(dat);		//写入数据
 	RST=0; //拉低CE,关闭数据通道
}
unsigned char Read_Ds1302_Byte ( unsigned char address )//写入读取命令
{
 	unsigned char i,temp=0x00;//保存数据
 	RST=0;	_nop_();///复位CE,短暂延迟消除可能存在的下降沿
 	SCK=0;	_nop_();//复位SCK,短暂延迟消除可能存在的下降沿
 	RST=1;	_nop_();//拉高CE,打开数据通道,短暂延迟消除上升沿
 	Write_Ds1302(address);//写入命令
 	for (i=0;i<8;i++) //开始接收数据	
 	{	
 	  //产生上升沿,接收数据	
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();//拉低CE,关闭数据通道
 	
 	//最后这一段,多产生了一个周期,将SCK、SDA置为高电平,以便下次读写
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}
//顺手把读写月份日期也写了

void ReadTime(u8 *GetTime)//读取时钟值,存入数组GetTime中,时:分:秒形式
{
   u8 temp;//BCD码转换为十进制

   temp = Read_Ds1302_Byte(0x85);//读出小时值
   GetTime[0] = (temp>>4)*10+(temp&0xf);  

   temp = Read_Ds1302_Byte(0x83);//读出分钟值
   GetTime[1] = (temp>>4)*10+(temp&0xf);
				   
   temp = Read_Ds1302_Byte(0x81);//读出秒值
   GetTime[2] = (temp>>4)*10+(temp&0xf);
}
void SetTime(u8 *WriteTime)//{00:00:00}
{
    u8 temp;
  	Write_Ds1302_Byte(0x8E,0X00);//允许写操作

	temp = ((WriteTime[0]/10)<<4)+WriteTime[0]%10;//写入时
	Write_Ds1302_Byte(0x84,temp);

	temp = ((WriteTime[1]/10)<<4)+WriteTime[1]%10;//写入分
	Write_Ds1302_Byte(0x82,temp);

	temp = ((WriteTime[2]/10)<<4)+WriteTime[2]%10;//写入秒
	Write_Ds1302_Byte(0x80,temp);

	Write_Ds1302_Byte(0x8E,0X80);//禁止写操作
}

3、编写读取函数

3.1地址

【蓝桥杯】DS1302时钟芯片学习笔记
从上图可以看出,读写的地址以及功能,
需要注意的是地址(81H)的BIT7是CH,该位是时钟暂停标志,CH=0,计时结束;CH=1,计时开始。
特别特别需要记住的是,控制寄存器(8EH)的BIT7,该位是写入的控制位,WP=0,允许写入;WP=1,禁止写入
Write_Ds1302_Byte(0x8E,0X00);//允许写操作
Write_Ds1302_Byte(0x8E,0X80);//禁止写操作

3.2BCD码与十进制互换

DS1302是以BCD码进行数据的存储读取的,
BCD码即用4位二进制数值 来表示一个0-9中的数字,
比如11(BCD)=0001 0001(2)=17;
也就是说,BCD码每一位都是4个二进制数组成的,据此可以转化为将BCD码全部转为二进制,再转化为十进制,即将BCD码每个数字分离出来,例如上面的11,将十位的1分离出来然后左移4位乘上一个10 在加上 个位的数字即可
下面直接列出公式:
BCD码转十进制:
X=(X(BCD)<<4)*10+(X(BCD)&0XF);
十进制转BCD码:
X(BCD)=((X/10)<<4)+X%10;

3.2代码

代码见上面个代码
第八届实时电子时钟是该模块的具体运用和考法,需要了解的,可以看我另外一篇博客,有详细代码第八届实时电子时钟

上一篇:LeetCode简单题之反转字符串中的单词 III


下一篇:php两种上传文件进度条显示方案