|
调试时钟芯片DS1302有感 liyang477 发表于 2005-12-4 15:14:00
经过几天的劳累终于可以把时间显示出来啦!真是好兴奋。总结一下吧!
由于本人手中和网上的源程序实在是太多,“看上去”也挺完美,就是因为这个“看上去完美”让我花费了好长时间。来读别人的代码,程序怎么条就是不通,后来看了一位网友的文章写的是关于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[i]); } /******************************************************************/ /* 函数名:readtime() ; /* 参 数:无 /* 功 能:用于读取DS1302的当前时间,具体时间值存放在timecur[7]数组中 /******************************************************************/ void readtime() { uchar i; for(i=0;i<7;i++) timercur[i]=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[i]); }
|