欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

毕业设计之时钟模块设计DS1302

程序员文章站 2022-07-01 15:18:57
...

该模块使用的芯片是:DS1302芯片,DS1302芯片是一个自动计时的时钟模块,有6个时钟寄存器,秒,分,时,日,月,年(其实不止,其它的暂且不管了)
使用不同的命令字来控制相应的寄存器:
0x80 ~ 0x8c ,分别控制秒到年寄存器的读和写
毕业设计之时钟模块设计DS1302
上表中,如果想读当前是多少秒,直接将0x81给read_DS1302()函数作为参数,该函数返回值对应的就是当前的秒
unsigned int current_second = read_DS1302(0x81);current_second 就是返回的秒

DS1302和单片机通过I/0口进行连接:
具体实现两种通信:
单片机通过发送指令,让时钟寄存器获得初始化时间
单片机从DS1302芯片获取时钟信息

DS1302封装图:
毕业设计之时钟模块设计DS1302
下面介绍从DS1302读取时钟的过程:
首先请看时序图:
毕业设计之时钟模块设计DS1302

/*
	dat是需要读入命令字,函数返回该命令字要求返回的寄存器的数据
*/
u8 Read_DS1302(u8 dat) // 
{
	u8 i,temp,dat1,dat2;

	DS1302_CE   = 0;
	DS1302_SCLK = 0;
	DS1302_CE   = 1;

	for(i = 8;i>0;i--)	 //用8个上升沿把dat中的8位bit送到IO种选择读取的地址
	{
		DS1302_SCLK = 0; 
		temp  =  dat;
		DS1302_IO   =  (bit)(temp&0x01);// temp的最右边一位送到IO上
		dat >>=1;  //dat右移一位 
		DS1302_SCLK   = 1; //上升沿触发
	}

	for(i =8 ;i>0 ; i--)	   //采用先接收IO口数据,再用下降沿触发,循环结束后ACC获得读取数据
	{
		ACC_7   =   DS1302_IO;	//从最高位接收
		DS1302_SCLK  =  1;
		ACC >>= 1; //ACC为累加器
		DS1302_SCLK  =  0;
	}
	DS1302_SCLK  = 1;
	DS1302_CE    =  0;
	dat1 = ACC;
	dat2 = dat1 /16;
	dat1 = dat1 %16;
	dat1 = dat1+dat2*10;
	 
	return (dat1);
}

往DS1302写数据:
写时序如图:(RST = CE)
毕业设计之时钟模块设计DS1302

/*
addr写入命令字,dat根据写入的命令字把dat数据放入相应的寄存器
*/
void Write_DS1302(u8 addr,u8 dat)
{
	u8 i,temp;
	DS1302_CE   = 0;
	DS1302_SCLK = 0;
	
	DS1302_CE   = 1;
	for(i=8 ; i>0 ; i--)
	{
		DS1302_SCLK = 0;
		temp = addr;
		DS1302_IO = (bit)(temp&0x01);
		addr >>= 1;
		DS1302_SCLK = 1;
	}
	for(i=8;i>0;i--)
	{
		DS1302_SCLK = 0;
		temp  = dat;
		DS1302_IO = (bit)(temp&0x01);
		dat >>= 1;
		DS1302_SCLK = 1;
	}
	DS1302_SCLK = 1;	
	DS1302_CE   = 0;
}

下面是使用DS1302已经封装完成的头文件:
DS1302.h

#ifndef    _DS1302_H_
#define	   _DS1302_H_
#include   <reg52.h>

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

#define WRITE_SECOND  0x80	   、
#define WRITE_MINUTE  0X82		
#define WRITE_HOUR    0X84		
#define WRITE_DATE    0X86	    
#define WRITE_MONTH   0X88	    
#define WRITE_WEEK    0X8A  	 
#define WRITE_YEAR    0X8C		 

#define  READ_SECOND  0X81		 //读秒
#define  READ_MINUTE  0X83		 //读分
#define  READ_HOUR    0X85		 //读时
#define  READ_DATE    0X87		 //读日
#define  READ_MONTH   0X89		 // 读月
#define  READ_WEEK    0X8B		 //	读星期
#define  READ_YEAR    0x8D		 //  读年

#define WRITE_PROTECT           0x8E

sbit     ACC_7 = ACC^7;

u8 Read_DS1302(u8 dat);
void Write_DS1302(u8 addr,u8 dat);
u8 data time[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00};//秒,分,时,日,月、星期、年

u8 Read_DS1302(u8 dat)
{
	u8 i,temp,dat1,dat2;

	DS1302_CE   = 0;
	DS1302_SCLK = 0;
	DS1302_CE   = 1;

	for(i = 8;i>0;i--)	 //写入需要读入数据对应的地址	采用先接受IO口数据,再用
	{
		DS1302_SCLK = 0;
		temp  =  dat;
		DS1302_IO   =  (bit)(temp&0x01);
		dat >>=1;
		DS1302_SCLK   = 1;
	}

	for(i =8 ;i>0 ; i--)	   //采用先接收IO口数据,再用下降沿触发
	{
		ACC_7   =   DS1302_IO;	
		DS1302_SCLK  =  1;
		ACC >>= 1;
		DS1302_SCLK  =  0;
	}
	DS1302_SCLK  = 1;
	DS1302_CE    =  0;
	dat1 = ACC;
	dat2 = dat1 /16;
	dat1 = dat1 %16;
	dat1 = dat1+dat2*10;
	 
	return (dat1);
}

void Write_DS1302(u8 addr,u8 dat)
{
	u8 i,temp;
	DS1302_CE   = 0;
	DS1302_SCLK = 0;
	DS1302_CE   = 1;
	for(i=8 ; i>0 ; i--) //这个循环用于向DS1302写入addr命令字
	{
		DS1302_SCLK = 0;
		temp = addr;
		DS1302_IO = (bit)(temp&0x01);
		addr >>= 1;
		DS1302_SCLK = 1;
	}
	for(i=8;i>0;i--)//这个循环用于向DS1302对应的命令字中写dat
	{
		DS1302_SCLK = 0;
		temp  = dat;
		DS1302_IO = (bit)(temp&0x01);
		dat >>= 1;
		DS1302_SCLK = 1;
	}
	DS1302_SCLK = 1;	
	DS1302_CE   = 0;
}
  void DS1302_init()	
//给DS1302初始化,其中0x46是当时做闭塞是当时做毕设的时间,DS1302内部接收的是16进制,所	  	//以直接输入16进制就好了,	 
 { 
	Write_DS1302(WRITE_MINUTE,0x46);
	Write_DS1302(WRITE_HOUR,0x18);
	Write_DS1302(WRITE_DATE,0x13);
	Write_DS1302(WRITE_MONTH,4);
	Write_DS1302(WRITE_YEAR,0x19);
	Write_DS1302(WRITE_WEEK,6);
	Write_DS1302(0x80,0);			
 }
void Read_time()
{
	time[0]  =  Read_DS1302(0x81);
	time[1]	 =  Read_DS1302(0x83);
	time[2]	 =  Read_DS1302(0x85);
	time[3]	 =  Read_DS1302(0x87);
	time[4]	 =  Read_DS1302(0x89);
	time[5]	 =  Read_DS1302(0x8b);
	time[6]	 =  Read_DS1302(0x8d);

}
#endif
相关标签: 毕业设计总结