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