ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-01-31 15:03:11  阅读:188  来源: 互联网

标签:Ds1302 temp SCK BCD DS1302 蓝桥 nop 时钟


目录

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电路连接图

典型的操作电路图:
在这里插入图片描述
蓝桥杯CT107D单片机连接图:
在这里插入图片描述
SCK=P1^7;
SDA=P2^3; //进行同步串行通信
RST = P1^3; // DS1302复位

2、DS1302通信时序

1.1单字节写入时序
在这里插入图片描述
1.2单字节写入
在这里插入图片描述

可以看到写入操作和读取操作都是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地址

在这里插入图片描述
从上图可以看出,读写的地址以及功能,
需要注意的是地址(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代码

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

标签:Ds1302,temp,SCK,BCD,DS1302,蓝桥,nop,时钟
来源: https://blog.csdn.net/C_white_llj/article/details/122738884

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有