相对于DS18B20而言(我写的18B20官方驱动的修改https://blog.csdn.net/weixin_42994525/article/details/88219538)DS1302官方给出的驱动程序修改的地方会比较多一点,原因在于数据的格式问题,关于这个我也写了一篇文章大家可以去看一下https://blog.csdn.net/weixin_42994525/article/details/88111554
下面看一下官方的驱动程序:
/*
程序说明: DS1302驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include
#include
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Write_Ds1302( unsigned char address,unsigned char dat )
{
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
Write_Ds1302_Byte(dat);
RST=0;
}
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();
RST=0;
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
return (temp);
}
从上面的程序我们也能看出来,它没有1302的初始化函数也就是说我们不能向1302写一个我们自己想要或者说题目要求的初值,以及在向1302写数据的时候没有进行数据格式的转变,这样会导致我们的时钟显示会跑飞,就是加到六十之后还在继续往上加,还有就是在读取数据之后也没有进行数据的转换或导致的结果也是会使显示跑飞。
下面来看一下修改之后的代码:
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3;
//DS1302初始化
void DSInit()
{
uchar i;
uchar add=0x80;
Write_Ds1302(0x8e,0x00);//关闭写保护
for(i=0;i<7;i++)
{
Write_Ds1302(add,ds[i]);
add=add+2;
}
Write_Ds1302(0x8e,0x80);//开启写保护
}
//将数据存储到指定数组中
void Read_Time()
{
uchar i;
uchar add=0x81;
Write_Ds1302(0x8e,0x00);//关闭写保护
for(i=0;i<7;i++)
{
shijian[i]=Read_Ds1302(add);
add=add+2;
}
Write_Ds1302(0x8e,0x80);//开启写保护
}
//读取DS1302指定地址中的数据
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
uchar dat_low,dat_high;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();
RST=0;
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
dat_high=temp/16;//将读取的数据进行数据的转换,将寄存器的高四位转化为十进制的十位
dat_low=temp%16;//将读取的数据进行数据的转换,将寄存器的低四位转化为十进制的个位
temp=dat_high*10+dat_low;
return (temp);
}
//向DS1302写地址和数据
void Write_Ds1302( unsigned char address,unsigned char dat )
{
uchar num;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
num=(dat/10<<4)|(dat%10);//将数据的高位移入寄存器的高四位,低位移入寄存器的低四位(数据的格式转换)
Write_Ds1302_Byte(num);
RST=0;
}
//向DS1302写数据
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
上面的代码对官方的程序作出了修改,为了方便显示我们对1302写入了初值,也将读取出来的数据保存在了一个指定的数组当中。我把整个完整的代码贴出来,大家我可以直接上电试试看:
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST = P1^3; // DS1302复位
uchar code ds[]={55,59,23,10,10,1,16};
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar shijian[7];
uchar yi,er,san,si,wu ,liu,qi,ba;
void Init();
void DSInit();
void Delay1ms();
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 Write_Ds1302_Byte(unsigned char temp) ;
void Write_Ds1302( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302 ( unsigned char address );
void Read_Time();
void main()
{
Init();
DSInit();
yi=11;er=11;san=11;si=11;wu=11;liu=11;qi=11;ba=11;
while(1)
{
Read_Time();
yi=shijian[2]/10;er=shijian[2]%10;san=10;
si=shijian[1]/10;wu=shijian[1]%10;liu=10;
qi=shijian[0]/10;ba=shijian[0]%10;
display1(yi,er);
display2(san,si);
display3(wu,liu);
display4(qi,ba);
}
}
//DS1302初始化
void DSInit()
{
uchar i;
uchar add=0x80;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
Write_Ds1302(add,ds[i]);
add=add+2;
}
Write_Ds1302(0x8e,0x80);
}
//将数据存储到指定数组中
void Read_Time()
{
uchar i;
uchar add=0x81;
Write_Ds1302(0x8e,0x00);
for(i=0;i<7;i++)
{
shijian[i]=Read_Ds1302(add);
add=add+2;
}
Write_Ds1302(0x8e,0x80);
}
//读取DS1302指定地址中的数据
unsigned char Read_Ds1302 ( unsigned char address )
{
unsigned char i,temp=0x00;
uchar dat_low,dat_high;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA)
temp|=0x80;
SCK=1;
}
RST=0;
_nop_();
RST=0;
SCK=0;
_nop_();
SCK=1;
_nop_();
SDA=0;
_nop_();
SDA=1;
_nop_();
dat_high=temp/16;
dat_low=temp%16;
temp=dat_high*10+dat_low;
return (temp);
}
//向DS1302写地址和数据
void Write_Ds1302( unsigned char address,unsigned char dat )
{
uchar num;
RST=0;
_nop_();
SCK=0;
_nop_();
RST=1;
_nop_();
Write_Ds1302_Byte(address);
num=(dat/10<<4)|(dat%10);
Write_Ds1302_Byte(num);
RST=0;
}
//向DS1302写数据
void Write_Ds1302_Byte(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0;
SDA=temp&0x01;
temp>>=1;
SCK=1;
}
}
void Init()
{
P2=0XA0;
P0=0X00;//关闭蜂鸣器,继电器
P2=0X80;
P0=0XFF;//关闭LED灯
P2=0XC0;
P0=0XFF;//选择所有数码管
P2=0XFF;
P0=0XFF;//关闭所有数码管段选
}
void display1(uchar yi,uchar er)
{
P2=0XC0;//打开位选573 U8
P0=0X01;//选择第一个数码管
P2=0XFF;//打开段选573 U7
P0=tab[yi];
Delay1ms();Delay1ms();
P2=0XC0;//打开位选573 U8
P0=0X02;//选择第二个数码管
P2=0XFF;//打开段选573 U7
P0=tab[er];
Delay1ms();Delay1ms();
}
void display2(uchar san,uchar si)
{
P2=0XC0;//打开位选573 U8
P0=0X04;//选择第三个数码管
P2=0XFF;//打开段选573 U7
P0=tab[san];
Delay1ms();Delay1ms();
P2=0XC0;//打开位选573 U8
P0=0X08;//选择第四个数码管
P2=0XFF;//打开段选573 U7
P0=tab[si];
Delay1ms();Delay1ms();
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;//打开位选573 U8
P0=0X10;//选择第一个数码管
P2=0XFF;//打开段选573 U7
P0=tab[wu];
Delay1ms();Delay1ms();
P2=0XC0;//打开位选573 U8
P0=0X20;//选择第一个数码管
P2=0XFF;//打开段选573 U7
P0=tab[liu];
Delay1ms();Delay1ms();
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;//打开位选573 U8
P0=0X40;//选择第一个数码管
P2=0XFF;//打开段选573 U7
P0=tab[qi];
Delay1ms();Delay1ms();
P2=0XC0;//打开位选573 U8
P0=0X80;//选择第一个数码管
P2=0XFF;//打开段选573 U7
P0=tab[ba];
Delay1ms();Delay1ms();
}
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}