蓝桥杯单片机实时时钟DS1302驱动程序

时间:2024-04-06 17:20:20

DS1302是美国DALLAS公司推出的高性能、低功耗的实时时钟,附加31字节的静态RAM,采用SP三线接口与MCU进行同步通信,并可采用突发方式一次传送多个字节的时钟参数和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小于31天时可以自动调整,并具有润年补偿功能。简单来说,DS1302可以理解为一个电子手表,里面带有一个31字节的内存。当然,基本的使用方法和我们平时使用电子手表差不多,你可以设定时间,也可以读取时间,只不过这些工作是通过SPI接口有MCU去完成而已。
在DS1302中有两块存储器:日历时钟寄存器和今天RAM存储器。前者用于记录实时时间,后者用于记录其他数据。对于基本计时应用,重点关注的是日历时钟寄存器。设定时间参数就是往这些寄存器写入内容,读取实时时间也是从这些寄存器读出数据。
DS1302有关日历和时钟的寄存器有12个,我们最常用的有7个
这里数据格式为BCD码,是用十六进制来表示十进制。
例如,十六进制数0x13的值为整数19,但BCD码表示的是整数13。后续需要转换

蓝桥杯单片机实时时钟DS1302驱动程序
蓝桥杯单片机实时时钟DS1302驱动程序
蓝桥杯单片机实时时钟DS1302驱动程序
蓝桥杯单片机实时时钟DS1302驱动程序

uchar read(uchar add)
{
	    uchar zhi;
    	uchar dat1,dat2;
			CE=0;//初始CE线置0
			SCLK=0;//初始时钟线置0
			CE=1;//CE置1,开始传输
	    writebyte(add);
	    zhi=readbyte();
	
	    IO=0;//读完io置0
	
			dat1=zhi/16; //0xff 1111 1111  ds1302读的是BCD码,需转为16进制
			dat2=zhi%16;
	
			zhi=dat1*10+dat2;//转为10进制
	    return zhi;
}
uchar readbyte()//循环读字节
{ 
  uchar i;
	uchar temp;
	for(i=0;i<8;i++)
	{
		SCLK=0;
		temp>>=1;//temp的各个二进制位右移一位,最高位补0再赋值给temp
		if(IO)//如果io口有数据则读入
		{
		temp|=0x80;	
		}
		SCLK=1;
	}
	return temp;
}

蓝桥杯单片机实时时钟DS1302驱动程序

void writebyte(uchar dat)
{
  uchar i;
	for(i=0;i<8;i++)
	{
		SCLK=0;
	  IO=dat&0x01;
		SCLK=1;
		dat>>=1;	
	}

}

void write(uchar add,uchar dat)
{
	    uchar num;
	
			CE=0;
			SCLK=0;
			CE=1;
			writebyte(add);
	
	    num=(dat/10<<4)|(dat%10);//高四位 10位数  低四位 个位数 分开存,此处合并 10进制转BCD
			writebyte(num);
			CE=0;
	

}

完整代码

/*显示从23-59-30秒开始的自动时钟*/
#include <STC15F2K60S2.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit CE=P1^3;//复位脚
sbit IO=P2^3;
sbit SCLK=P1^7;//时钟线
void allinit();
void delayms(uchar z);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);

void dsinit();
void write(uchar add,uchar dat);
void writebyte(uchar dat);
uchar read(uchar add);
uchar readbyte();
void readtime();


uchar code ds[]={30,59,23,10,10,1,16};
//sec min hour day month week year

uchar time[7];//时间数组

uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar yi,er,san,si,wu,liu,qi,ba;


void delayms(uchar z)		//@12.000MHz
{
	unsigned char i, j;
	uchar k;
  for(k=z;k>0;k--)
	{
	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
	
	}
	
}


	void display1(uchar yi,uchar er)
	{
		P2=0XC0;
		P0=0X01;
		P2=0XFF;
		P0=tab[yi];
		delayms(1);
		
		P2=0XC0;
		P0=0X02;
		P2=0XFF;
		P0=tab[er];
		delayms(1);
	}
	
		void display2(uchar san,uchar si)
	{
		P2=0XC0;
		P0=0X04;
		P2=0XFF;
		P0=tab[san];
		delayms(1);
		
		P2=0XC0;
		P0=0X08;
		P2=0XFF;
		P0=tab[si];
		delayms(1);
	}
		void display3(uchar wu,uchar liu)
	{
		P2=0XC0;
		P0=0X10;
		P2=0XFF;
		P0=tab[wu];
		delayms(1);
		
		P2=0XC0;
		P0=0X20;
		P2=0XFF;
		P0=tab[liu];
		delayms(1);
	}
			void display4(uchar qi,uchar ba)
	{
		P2=0XC0;
		P0=0X40;
		P2=0XFF;
		P0=tab[qi];
		delayms(1);
		
		P2=0XC0;
		P0=0X80;
		P2=0XFF;
		P0=tab[ba];
		delayms(1);
	}
	
	
	
	
void allinit()
{
  P2=0X80;//打开控制数码管的573(u6),3-8译码器为001(ABC)
	P0=0XFF;//关闭所有流水灯
	
	P2=0XC0;//打开控制数码管位选的573,3-8译码器为011
	P0=0XFF;
	P2=0XFF;//打开控制数码管段选573,3-8译码器为111
	P0=0XFF;//关闭所有数码管
	
	P2=0XA0;//打开控制数码管573,3-8译码器为101
	P0=0X00;//关闭继电器和蜂鸣器
}
void main()
{
  allinit();
	dsinit();
  yi=11,er=11,san=11,si=11,wu=11,liu=11,qi=11,ba=11;
	while(1)
	{
      readtime();
			yi=time[2]/10;er=time[3]%10;san=10;
			si=time[1]/10;wu=time[1]%10;liu=10;
			qi=time[0]/10;ba=time[0]%10;
			
			display1(yi,er);
			display2(san,si);
			display3(wu,liu);
			display4(qi,ba);
	}
	
}



uchar readbyte()//循环读字节
{ 
  uchar i;
	uchar temp;
	for(i=0;i<8;i++)
	{
		SCLK=0;
		temp>>=1;//temp的各个二进制位右移一位,最高位补0再赋值给temp
		if(IO)//如果io口有数据则读入
		{
		temp|=0x80;	
		}
		SCLK=1;
	}
	return temp;
}



uchar read(uchar add)
{
	    uchar zhi;
    	uchar dat1,dat2;
			CE=0;
			SCLK=0;
			CE=1;
	    writebyte(add);
	    zhi=readbyte();
	
	    IO=0;//读完io置0
	
			dat1=zhi/16; //0xff 1111 1111  ds1302读的是BCD码,需转为16进制
			dat2=zhi%16;
	
			zhi=dat1*10+dat2;//转为10进制
	    return zhi;
}


void readtime()
{
  uchar i;
	uchar add=0x81;
	write(0x8e,0x00);
	for(i=0;i<7;i++)
	{
	  time[i]=read(add);
		add=add+2;
	}
	write(0x8e,0x80);
}




void writebyte(uchar dat)
{
  uchar i;
	for(i=0;i<8;i++)
	{
		SCLK=0;
	  IO=dat&0x01;
		SCLK=1;
		dat>>=1;	
	}

}

void write(uchar add,uchar dat)
{
	    uchar num;
	
			CE=0;
			SCLK=0;
			CE=1;
			writebyte(add);
	
	    num=(dat/10<<4)|(dat%10);//高四位 10位数  低四位 个位数 分开存,此处合并 10进制转BCD
			writebyte(num);
			CE=0;
	

}

void dsinit()//初始化时间显示
{
  uchar i;
	uchar add=0x80;//初始化首地址 80h开始
	write(0x8e,0x00);// 关掉写保护 打开进行操作
	for(i=0;i<7;i++)
	{
	  write(add,ds[i]);
		add=add+2;
	}
	write(0x8e,0x80);//打开写保护
}