蓝桥杯模块DS1302时钟芯片Part_2

本文详细解析了DS1302实时时钟模块的驱动原理及实现,包括同步串行通信、三线通信机制,以及如何通过写时序、写字节、读字节等功能进行数据交互,特别关注时钟设置与读取的操作细节。

   九层妖塔 起于垒土
在这里插入图片描述

一、Notes

 ●同步串行通信
 ●三线通信
 ●内含一个实时时钟/日历和31字节静态RAM
 ●时钟/RAM的读/写数据以一个字节多达31个字节的字符组方式通信。

二、写时序

1、时序图

在这里插入图片描述

2、官方底层驱动代码:

//-------第十届资料包,日期:2011-8-9,应该是针对12T单片机
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
	}
} 
//------2020年国信长天组织的模拟测试-------//
void Write_Ds1302_Byte(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;
		SDA=temp&0x01;
		temp>>=1; 
		SCK=1;
		Delay2ms();        
	}
}   

3、Template:

void DS1302_Write(uchar temp) 
{
	uchar i;
	for (i=0;i<8;i++)     	
	{ 
		SCK=0;   
		SDA=temp&0x01;
		temp>>=1;    //移位兼延时
		SCK=1;     //上升沿写入数据
		Delay1us();//稳定电平 
	}
}  

4、Notes:

 ●在SCLK周期的上升沿输入字节。DS1302每检测到一个SCLK上升沿就从I/O引脚(SDA)接收1位数据。
 ●先将SCK=0;再送数据,因为min( t D C t_{DC} tDC)=50ns,因此将移位temp>>=1;放于此移位兼延时
 ●再使SCK=1;产生上升沿,写入一位数据。
 ●Delay1us();min( t C H t_{CH} tCH)=250ns和min( t C L t_{CL} tCL)=250ns。即串行时钟信号SCK高低电平至少各为250ns。12T单片机12MHz主时钟,一个空指令_nop_();=一个机器周期=1个时钟周期=1/ f o s c f_{osc} fosc=1/12MHz=1/12us,不够250ns,直接延时1us来稳定电平。
 ●至于min( t C L t_{CL} tCL)=250ns,由SCK=0;SCK=1;之间的执行代码充当延时。
 ●2020年国信长天组织的模拟测试中给出延时2ms,似乎有点过分?!

三、写字节

1、官方底层驱动代码:

//------两个版本的驱动除了子函数名不一样外,完全相同----//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

2、Template:

//仅改了函数名,添加了注释
//------------------------------------------------DS1302写字节-----------------//
void DS1302_Write_Byte(uchar address,uchar dat)     
{
 	RST=0;	_nop_();     //复位  
 	SCK=0;	_nop_();    //复位 
 	RST=1;  _nop_();     //开始数据传输 
 	DS1302_Write(address);//地址字节	
 	DS1302_Write(dat);	  //数据字节	
 	RST=0;                //复位,关闭数据传输 
}

四、读字节

1、时序图

在这里插入图片描述

2、官方底层驱动代码:

//-------第十届资料包,日期:2011-8-9,应该是针对12T单片机
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}
//------2020年国信长天组织的模拟测试-------//
unsigned char Read_Ds1302 ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;
	_nop_();
 	SCK=0;
	_nop_();
 	RST=1;
	_nop_();
 	Write_Ds1302_Byte(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;
		Delay2ms();	 
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;
	_nop_();
 	RST=0;
	SCK=0;
	_nop_();
	SCK=1;
	_nop_();
	SDA=0;
	_nop_();
	SDA=1;
	return (temp);			
}

3、Template:

//------------------------------------------------DS1302读字节-----------------//
uchar DS1302_Read_Byte(uchar address)
{
 	uchar i,temp=0x00;
	
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	DS1302_Write(address);  //地址字节	
 	
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;     //开始读数据字节
		temp>>=1;	 //延时+移位
		Delay1us();//延时稳定电平 
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

4、Notes:

 ●Template与官方驱动没有实质性的变化。只是为了便于查找修改了子函数名,增加1us延时来稳定电平。
 ●还有最后的五行操作不知为啥,其他地方也没找到。
 ●2020模拟测试最后比以前多出来一行,写的更乱;其他地方的缩进,函数名都是极具个性的

五、时钟设置

1、RCT寄存器:

在这里插入图片描述

2、Template:

uchar DS1302_Init_time[3]={23,59,50}; //DS1302初始化时间

//------------------------------------------------DS1302时钟设置-----------------//
void DS1302_Set_RCT(uchar *DS1302_Init_time)
{
	uchar RCT;
	DS1302_Write_Byte(0X8E,0);		//WP=0,允许写操作
	
	RCT = ((DS1302_Init_time[0]/10)<<4)+(DS1302_Init_time[0]%10);
	DS1302_Write_Byte(0X84,RCT);    //设置时
	
	RCT = ((DS1302_Init_time[1]/10)<<4)+(DS1302_Init_time[1]%10);
	DS1302_Write_Byte(0X82,RCT);    //设置分
	
	RCT = ((DS1302_Init_time[2]/10)<<4)+(DS1302_Init_time[2]%10);
	DS1302_Write_Byte(0X80,RCT);    //设置秒	
	
	DS1302_Write_Byte(0X8E,0X80);			//WP=1,禁止写操作
}

3、Notes:

 ●数组名是数组首元素的地址。数组表示法其实是在变相地使用指针。
 ●子函数定义了无符号指针型地形参,虽然形参名为数组名,但并不指向数组,形参名只是一个代表。
 ●输入的shi实参为数组名,指向数组首元素的地址,用实参来代替符号式的形参。
 ●允许写操作→写操作→关闭写操作
 ●时钟设置子函数DS1302_Set_RCT()将数据写入RCT寄存器组,来初始化时间,只需执行一遍。
 ●时间信息(秒,分,时,日,月,年)是将十进制的十位和个位分开分别转化为8421BCD码存储在相关寄存器中的。

六、读取时钟

1、Template:

uchar DS1302_time[3];               //从DS1302读取到的实时时间 

//------------------------------------------------DS1302读取时钟-----------------//
void DS1302_Read_RCT(uchar *DS1302_time)
{
	uchar RCT;
	
	RCT = DS1302_Read_Byte(0X85);   //读取时
	DS1302_time[0] = (RCT>>4)*10+(RCT&0X0F);  
	
	RCT = DS1302_Read_Byte(0X83);   //读取分
	DS1302_time[1] = (RCT>>4)*10+(RCT&0X0F);  
	
	RCT = DS1302_Read_Byte(0X81);   //读取秒
	DS1302_time[2] = (RCT>>4)*10+(RCT&0X0F);  
}

七、主函数

void main(void)
{
	All_Init();  //开发板初始化
	DS1302_Set_RCT(DS1302_Init_time);  //设置初始时钟
	while(1)
	{

		DS1302_Read_RCT(DS1302_time);	  //DS1302读取时钟
		
		yi=DS1302_time[0]/10;
		er=DS1302_time[0]%10;
		san=23;
		si=DS1302_time[1]/10;
		wu=DS1302_time[1]%10;
		liu=23;
		qi=DS1302_time[2]/10;
		ba=DS1302_time[2]%10;
		
		SEG_1_2(yi,er);
		SEG_3_4(san,si);
		SEG_5_6(wu,liu);
		SEG_7_8(qi,ba);
		SEG_Init();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

#法外狂徒张三

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

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

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

打赏作者

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

抵扣说明:

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

余额充值