51单片机DS1302

目录

前言

一、工作原理

二、代码

总结



前言


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

 

一、工作原理


        下面是其在普中51单片机开发板上的原理图:

        简单介绍一下,右边是一个晶振电路,虽然是它时钟芯片,但依然需要独立外接晶振电路,晶体振荡器Y1可以产生晶振频率为其提供时钟信号,C2和C3为起振电容,这是晶振电路的典型画法,VCC2为主电源,VCC1为备用电源,接电池后可以在主电源断开后保持计时状态。SCLK为串行时钟引脚接单片机P3^6,I/O为数据输入输出引脚接单片机P3^5,CE为片选引脚接单片机P3^4,这里的通信使用的是该芯片专用的协议。

        上图是DS1302的内部结构框图,还是简单介绍下,左上角是电源控制模块,对输入的电源进行分配,为整个芯片供电。右上角为时钟分频模块,对输入的32.768KHz的时钟信号进行处理后得到1Hz的标准时钟信号,左边片选引脚CE在芯片内部下拉,,也就是说只能检测到高电平,也就是高电平触发,当CE输入高电平,芯片内部命令控制逻辑区才能接通并开始工作,类似于总开关的作用。I/O数据引脚收发数据会受串行时钟信号的控制,数据引脚和时钟引脚的变化要严格遵循它的通信时序。

         如下图所示是寄存器定义表:

         从上到下分别是秒、分、时、日、月、周、年最后两个寄存器是写保护和备用电源控制,左边两列寄存器的值代表读和写,例如,81为读“秒”寄存器,82为写“分”寄存器。

         上图为读写寄存器的时序图,它的时序也很简单哈,串行时钟信号的上升沿为写数据,下降沿为读数据当检测到时钟信号的上升沿时对I/O引脚的电平采样,当检测到时钟信号的下降沿时向I/O引脚输出电平信息。前8位为固定写,写入的这个字节为命令字,对某个寄存器进行读或写的操作,也就是上面的81h、82h...,后8位为写入或读出的数据,通过移位寄存器进行传递(低位先行),如此这般反复执行这一过程,通信也就随之产生了,数据存入到寄存器中上电后便开始走时。

二、代码


        先对引脚和寄存器地址及命令字进行定义

#include <REGX52.H>
//引脚定义
sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;
//寄存器写入地址/指令定义
#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

        DS1302读写数据函数

void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;
	for(i=0;i<8;i++)                //先写入8位命令字
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	for(i=0;i<8;i++)                //写8位数据
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;
}

unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	Command|=0x01;	                //最低为置1,将指令转换为读指令
	DS1302_CE=1;
	for(i=0;i<8;i++)                //写8位命令字
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)                //读8位数据
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);}
	}
	DS1302_CE=0;
	DS1302_IO=0;                    //读取后将IO设置为0,否则读出的数据会出错
	return Data;
}

        其实读写函数可以合并,大致思路就是判断命令字是奇数还是偶数,奇数就是读偶数就是写

        根据上面写的通信层代码实现功能,对秒、分、时...进行解析,注意这里涉及到BCD码与十进制的转化。

//时间数组,索引0~6分别为年、月、日、时、分、秒、星期
unsigned char DS1302_Time[]={19,11,16,12,59,55,6};

void DS1302_SetTime(void)
{
	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,0x80);
}

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

总结


        数字信号可以分配格式地输出显示到LCD1602上

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

且看林地几华里

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

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

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

打赏作者

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

抵扣说明:

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

余额充值