DS1302时钟模块

                                                             DS1302结构原理图

DS1302涓流充电计时芯片实时时钟/日历和31字节的静态RAM,通过IO口与微机处理器通讯,该实时时钟/日历提供年月日和时分秒星期,还具备月份闰平年自动校正。其信息与外部的传输由CE、I/O和SCLk(串行时钟)决定。

51单片机中的DS1302模块

注:51单片机中的DS1302模块无备用电源,断电就停止运行,上电便开始运行,复位操作不会影响时钟的运行。

工作原理:

                                                                  工作时序图

CE:读写使能开关,不论对DS1302进行读或写操作都需要将CE置1,若CE置0则相应的读写操作都无效

SCLK:时钟脉冲串

IO:前八位是对读写模式的选择和读写地址的配置(年月日,时分秒,星期都对应不同的地址),其触发方式为上升沿触发,即SCLK由0变为1时触发。

 上图圈内左列自上往下对应的分别对应秒、分、时、日、月、星期、年和读保护,其对应的模式为从DS1302中读出相应数据并送至IO口。右列自上往下对应的分别对应秒、分、时、日、月、星期、年和写保护,其对应的模式为将IO口中的数据写入DS1302中,相当于设置DS1302的初始值。当读写保护开启(置1)时,数据无法写入DS1302或无法从DS1302中读出数据,即若要对相应数据进行操作就得关闭读写保护(令其为0x00)。

后八位(BT0~BT7)为数据位,当为单字节读时其触发方式为下降沿触发,即SCLK由1变为0时触发,当为单字节写时其触发方式为上升沿触发,即SCLK由0变为1时触发。需要注意的是该字节数据为两位BDS编码(两位BDS编码说明DS1302只能输出两位数,最大为99,若要显示年份只能显示后两位),即八个字节被分为前后各四个,前四个表示十位,后四个表示个位,当个位二进制对应的值等于10时需要向前四位进1,即前后四位最大值为均1001。例如 当 0000 1001(十进制为9)加一后变为 0001 0000,0001 0000 在十进制中表示16,但在BDS码中其表示10。 当我们需要写入的数据为十进制时需要先将该数据转为BDS码,再将对应的BDS码写入DS1302,当我们从DS1302中读出数据时得先将数据转化为十进制再进行相应操作,否则我们将无法得到预期数据。

BSD转十进制:DS1302直接读取值/16*10 + DS1302直接读取值%16

十进制转BDS:十进制数值/10*16 + 十进制数值%10

例如:DS1302模块代码

#include <regx52.h>

sbit DS1302_SCLK=P3^6;
sbit DS1302_IO=P3^4;
sbit DS1302_CE=P3^5;

#define DS1302_WSec 0x80        //写秒         注:宏定义末尾不加分号!!!!!
#define DS1302_WMin 0x82        //写分
#define DS1302_WHou 0x84        //写时
#define DS1302_WDat 0x86        //写日
#define DS1302_WMon 0x88        //写月
#define DS1302_WYea 0x8C        //写年
#define DS1302_WDay 0x8A        //写星期
#define DS1302_WP   0x8E        //写保护

#define DS1302_RSec 0x81        //读秒
#define DS1302_RMin 0x83        //读分
#define DS1302_RHou 0x85        //读时
#define DS1302_RDat 0x87        //读日
#define DS1302_RMon 0x89        //读月
#define DS1302_RYea 0x8D        //读年
#define DS1302_RDay 0x8B        //读星期

unsigned int DS1302_Time[]={23,1,31,6,20,45,4};

void DS1302_Init()
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}

void DS1302_WriteByte(unsigned char command,date)    //command用于配置DS1302,选择读或写,并指明位置,date为写入指定位置的值
{
	unsigned char i;
	DS1302_CE=1;                                     //使单片机能够对DS1302芯片进行读写操作
	for(i=0;i<8;i++)                                 //将command通过移位寄存器送入DS1302
	{
		DS1302_IO=command&(0x01<<i);
		DS1302_SCLK=1;                               //触发上升沿,将IO上的值写入DS1302
		DS1302_SCLK=0;                               //将DS1302_SCLK置0,以便下次触发上升沿
	}
	for(i=0;i<8;i++)                                 //按照配置DS1302的方法,将要写入的数据送入DS1302的指定地址
	{
		DS1302_IO=date&(0x01<<i);
		DS1302_SCLK=1;
		DS1302_SCLK=0;
	}
	DS1302_CE=0;                                     //写入完毕后,关闭使能开关
}

unsigned char DS1302_ReadByte(unsigned char command) //输入读取数据的指令后返回读取到的数据
{
	unsigned char i,date=0x00;                       //全局变量默认初始值为0,但局部变量默认初始值不一定为0,因此需要将date先初始时化,由于承接的是一个8为二进制数,所以初始化为0x00;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=command&(0x01<<i);
		DS1302_SCLK=1;
		if(i<7)                                      //第8次触发上升沿后先不将DS1302置0,因为触发下降沿后便会将指定地址的数据送至IO口
		{
			DS1302_SCLK=0;
		}
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=0;                               //触发下降沿,将指定地址的数据送至IO口
		if(i<7)
		{
			DS1302_SCLK=1;                           //第8触发下降沿后不用将DS1302_SCLK置1,让其回到初始位置
		}
		if(DS1302_IO)                                //如果IO口输出的数为1
		{
			date=date>>1;                            //则将date右移1位后,把date的最高位置1
			date|=0x80;
		}
		else                                         //若IO口输出的数位0
		{
			date=date>>1;                            //则只需将date右移一位
		}
	}
	DS1302_IO=0;                                     //将IO口置0,起到初始化作用
	DS1302_CE=0;                                     //关闭使能开关
	return date;                                     //返回date
}



void DS1302_SetTime()       //数组内的值,写入DS1302对应地址,相当于为时钟设置初始值
{
	DS1302_WriteByte(DS1302_WP,0x00);                    //关闭DS1302写保护
	DS1302_WriteByte(DS1302_WYea,DS1302_Time[0]/10*16+DS1302_Time[0]%10);        //设置年初始值DS1302_Time[0]
	DS1302_WriteByte(DS1302_WMon,DS1302_Time[1]/10*16+DS1302_Time[1]%10);        //设置月初始值DS1302_Time[1]
	DS1302_WriteByte(DS1302_WDat,DS1302_Time[2]/10*16+DS1302_Time[2]%10);        //设置日初始值DS1302_Time[2]
	DS1302_WriteByte(DS1302_WHou,DS1302_Time[3]/10*16+DS1302_Time[3]%10);        //设置时初始值DS1302_Time[3]
	DS1302_WriteByte(DS1302_WMin,DS1302_Time[4]/10*16+DS1302_Time[4]%10);        //设置分初始值DS1302_Time[4]
	DS1302_WriteByte(DS1302_WSec,DS1302_Time[5]/10*16+DS1302_Time[5]%10);        //设置秒初始值DS1302_Time[5]
	DS1302_WriteByte(DS1302_WDay,DS1302_Time[6]/10*16+DS1302_Time[6]%10);        //设置星期初始值DS1302_Time[6]
	DS1302_WriteByte(DS1302_WP,0x80);                   //打开DS1302写保护
}


void DS1302_ReadTime(void)  //将DS1302中的年月日时分秒星期读出并存入数组DS1302_Time[],访问数组即可得到相应时间值
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_RYea);    //读出DS1302中的年
	DS1302_Time[0]=Temp/16*10+Temp%16;    //将读出的年存入数组
	Temp=DS1302_ReadByte(DS1302_RMon);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_RDat);
	DS1302_Time[2]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_RHou);
	DS1302_Time[3]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_RMin);
	DS1302_Time[4]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_RSec);
	DS1302_Time[5]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_RDay);
	DS1302_Time[6]=Temp/16*10+Temp%16;
}

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值