ds1302时钟芯片学习

ds1302是一个实时时钟芯片,我们可以使用单片机写入时间或者读取当前的时间。

1.ds1302的指令字节介绍


如图,ds1302的一条指令一个字节

(1)第7位固定为1
(2)第6位为功能选择的位,这里使用的是时钟的功能,因此固定为0就行
(3)第0位是读写位,读的时候置为1,写的时候置为0
(4)5-1位是地址位

2.ds1302的寄存器介绍

ds1302时钟芯片学习_第1张图片
图里前两列分别是读时的指令字节和写时的指令字节,后面的8列就是对应的寄存器里的数据,下面介绍寄存器0、1、2、7的作用
(1)寄存器0,bit7(CH)为时钟停止标志位,6-4为秒的十位,3-0为秒的个位
(2)寄存器1,bit6-7为分的十位,bit3-0为分的个位
(3)寄存器2,bit7是一个12小时制和24小时制的选择位;bit6固定为零;当bit7为0时,bit5与bit4共同构成小时的十位;当bit7为1时,bit5表示上午或下午,bit4表示小时的十位;bit3-0为小时的个位
(4)寄存器7,最高位一个写保护位,如果这一位是1那么是禁止给任何其它寄存器写数据的。因此在写数据之前,这一位必须先写成0

3.程序

单片机使用的是iap15f2k61s2的51单片机,ds1302.c里的程序是ds1302的驱动程序,直接从蓝桥杯官方例程里得到的,但是该驱动程序好像有问题,在数码管上显示的时候,数字老是一闪一闪的。main.c里的程序是自己通过资料写出来的,这里我使用了两种显示的方式,注释了的这段程序:
//	XBYTE[0xE000]=0xff;
//	XBYTE[0xE000]=tab[dspbuf[dspcom]];
//	XBYTE[0xC000]=1<
为mm的方式,程序中使用的是io方式。

main.c:

#include
#include
#include
#include
sfr AUXR=0x8e;
code unsigned char tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
unsigned char dspbuf[]={10,10,10,10,10,10,10,10},dspcom=0;
unsigned char s,m,h;
void Delay10ms()		//@11.0592MHz
{
	unsigned char i, j;

	i = 108;
	j = 145;
	do
	{
		while (--j);
	} while (--i);
}
void init_ds1302()
{
	Ds1302_Single_Byte_Write(0x8e,0x00);
	Ds1302_Single_Byte_Write(0x80,0x0);//秒
	Ds1302_Single_Byte_Write(0x82,0x14);//分
	Ds1302_Single_Byte_Write(0x84,0x21);	//时
	Ds1302_Single_Byte_Write(0x8e,0x80);
}
void Timer0Init(void)		//1毫秒@11.0592MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初值
	TH0 = 0xD4;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}
void display()
{
//	XBYTE[0xE000]=0xff;
//	XBYTE[0xE000]=tab[dspbuf[dspcom]];
//	XBYTE[0xC000]=1<>4);
		dspbuf[7]=(s&0x0f);
		
		dspbuf[3]=((m&0xf0)>>4);
		dspbuf[4]=(m&0x0f);
		
		dspbuf[0]=((h&0xf0)>>4);
		dspbuf[1]=(h&0x0f);		
	}
}
void f0()interrupt 1
{
//	s=Ds1302_Single_Byte_Read(ds1302_sec_addr);
//	m=Ds1302_Single_Byte_Read(ds1302_min_addr);
//	h=Ds1302_Single_Byte_Read(ds1302_hr_addr);
		display();
}
ds1302.c:

#include "ds1302.h"
/********************************************************************/ 
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	for (i=0;i<8;i++) 
	{ 
		if (dat & 0x01) 	// 等价于if((addr & 0x01) ==1) 
		{
			SDA_SET;		//#define SDA_SET SDA=1 /*电平置高*/
		}
		else 
		{
			SDA_CLR;		//#define SDA_CLR SDA=0 /*电平置低*/
		}		 
		SCK_SET;
		SCK_CLR;		
		dat = dat >> 1; 
	} 
}
/********************************************************************/ 
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void) 
{
	unsigned char i, dat=0;	
	for (i=0;i<8;i++)
	{	
		dat = dat >> 1;
		if (SDA_R) 	  //等价于if(SDA_R==1)    #define SDA_R SDA /*电平读取*/	
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK_SET;
		SCK_CLR;
	}
	return dat;
}

/********************************************************************/ 
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;			/*启动DS1302总线,RST=1电平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
	Write_Ds1302_Byte(dat);	 /*写入数据:dat*/
	RST_CLR;				 /*停止DS1302总线*/
}

/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;	/*启动DS1302总线,RST=1电平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
	temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
	RST_CLR;	/*停止DS1302总线*/
	return temp;
}




你可能感兴趣的:(单片机)