|
由于本人手中和网上的源程序实在是太多,“看上去”也挺完美,就是因为这个“看上去完美”让我花费了好长时间。来读别人的代码,程序怎么条就是不通,后来看了一位网友的文章写的是关于DS1302调试过程中应注意的事项,指出了ds1302的datasheet中的一些错误,这才使我恍然大悟,原来读数据的时间要求是非常严格的。要求在命令字之后的第一个下降沿就要读数据,否则读出的数据就是错误的,也不能说完全错误,那就必须作必要的调整。本来读数据手册时已经注意到这个问题,但就是再看别人的程序时没引起注意。害得我浪费了几天的时间。
下次一定要注意:别人程序很可能有缺陷,能参考,但不能够完全照抄,数据手册一定要细读。时间是浪费了,但也值,这几天告诉我,自己的c语言功夫还不够,具体地说差得好远。提醒自己要努力。一定要学会应用汇编,汇编与c的相互调用。
下面是我的原程序,写得不好,如果有哪位高手看见了一定要指教,小弟不胜感激。其中最想改的就是write()和read()函数,每个函数大概编译后都是63字节,肯定能再少,就是不用ACC而用变量移位来完成。试了几次调不通呀!
/******************************************************************/
/* 文件名:DS1302.c
/* 库 名:DS1302.h
/* 功 能:此文件中的函数可用于对DS1302的时间进行设置和读取DS1302内部的时间
/* 缺 点:此文件中的函数没有用到DS1302的所有功能,如:连续的读写操作、RAM的应用,充电部分的应用,写保护、抗干扰等
/* 但是可以根据DS1302的datasheet和此文件中的部分函数组合可以实现上述功能
/******************************************************************/
#i nclude <at89x51.h>
#define uchar unsigned char
/******************************************************************/
uchar code time_set[7]={0x15,0x30,0x13,0x04,0x12,0x07,0x05}; file://设置时间初始值数组
// 秒 分 时 号 月份 星期 年
uchar data timercur[7]; file://用于存放从DS1302读回的时间数据
uchar data timerint[14]; file://用于存放将BCD码型数据转换成INT型后的数据
uchar data *pTimerInt; file://指向存放转换后时间数据的指针
/******************************************************************/
sbit CLK=P1^0; file://与硬件相关的连线 clk为DS1302的时钟信号线
sbit DAT=P1^1; file://DAT为DS1302的I/O数据线
sbit RST=P1^2; file://RST为DS1302的RST信号线
sbit ACC0=ACC^0;
sbit ACC1=ACC^1;
sbit ACC2=ACC^2;
sbit ACC3=ACC^3;
sbit ACC4=ACC^4;
sbit ACC5=ACC^5;
sbit ACC6=ACC^6;
sbit ACC7=ACC^7;
/****************************函数定义**************************************/
/******************************************************************/
/* 函数名:write(address);
/* 参 数:地址/数据字节
/* 功 能:用于向DS1302输入地址或数据信息
/******************************************************************/
void write(uchar address)
{
ACC=address;
CLK=0;
DAT=ACC0;
CLK=1;CLK=0;
DAT=ACC1;
CLK=1;CLK=0;
DAT=ACC2;
CLK=1;CLK=0;
DAT=ACC3;
CLK=1;CLK=0;
DAT=ACC4;
CLK=1;CLK=0;
DAT=ACC5;
CLK=1;CLK=0;
DAT=ACC6;
CLK=1;CLK=0;
DAT=ACC7;
CLK=1;
}
/******************************************************************/
/* 函数名:read();
/* 参 数:无
/* 功 能:用于从DS1302读出时间数据信息
/******************************************************************/
void read()
{
// DAT=1; /*注意在进行读操作之前DAT应置1*/
CLK=0;
ACC0=DAT;
CLK=1;CLK=0;
ACC1=DAT;
CLK=1;CLK=0;
ACC2=DAT;
CLK=1;CLK=0;
ACC3=DAT;
CLK=1;CLK=0;
ACC4=DAT;
CLK=1;CLK=0;
ACC5=DAT;
CLK=1;CLK=0;
ACC6=DAT;
CLK=1;CLK=0;
ACC7=DAT;
CLK=1
return(ACC);
}
/******************************************************************/
/* 函数名:W_Byte(address, byte);
/* 参 数:地址,数据
/* 功 能:用于向DS1302指定的地址address输入数据byte
/******************************************************************/
void W_Byte(uchar address,uchar byte)
{
RST=0;
CLK=0;
RST=1;
write(address);
write(byte);
RST=0;
}
/******************************************************************/
/* 函数名:R_Byte(address);
/* 参 数:地址
/* 功 能:用于从DS1302指定地址address处读出数据,并将数据存放到ACC中
/******************************************************************/
uchar R_Byte(uchar address)
{
RST=0;
CLK=0;
RST=1;
write(address);
DAT=1;
read();
RST=0;
return(ACC);
}
/******************************************************************/
/* 函数名:timeset() ;
/* 参 数:无
/* 功 能:用于设置DS1302的时间,具体时间值存放在time_set[7]数组中
/******************************************************************/
void timeset()
{ uchar i;
W_Byte(0x8e,0x00);
for(i=0;i<7;i++)
W_Byte(0x80+i+i,time_set);
}
/******************************************************************/
/* 函数名:readtime() ;
/* 参 数:无
/* 功 能:用于读取DS1302的当前时间,具体时间值存放在timecur[7]数组中
/******************************************************************/
void readtime()
{ uchar i;
for(i=0;i<7;i++)
timercur=R_Byte(0x81+i+i);
}
/******************************************************************/
/* 函数名:unsigned char * bcd_int(unsigned char i)
/* 参 数:BCD型数据
/* 功 能:因为从DS1302读回的数据是BCD码,所以要将其转换为十进制整形数据
/******************************************************************/
unsigned char * bcd_int(unsigned char i)
{
uchar j;
*(pTimerInt++)=(i&0x0f);
j=i>>4;
*(pTimerInt++)= j&0x0f;
return(*pTimerInt);
}
/******************************************************************/
/* 函数名:BCD_to_INT();
/* 参 数:无
/* 功 能:用于将时间BCD码转换为十进制码
/******************************************************************/
void BCD_to_INT()
{ uchar i;
for(i=0;i<7;i++)
bcd_int(timercur);
}