DS1302的一个问题
本帖最后由 fjlonng 于 2011-12-19 10:59:54 编辑 以下代码在串口调试助手上显示:
······(省略一部分)
11-12-17 00:35:57
11-12-17 00:35:57
11-12-17 00:35:58
11-12-17 00:35:58
11-12-17 00:35:58
······(省略一部分)
以上是正确的读出数据
但是,假如下面那行红色的代码去掉,就会变成:
······(省略一部分)
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-?? 00:??:02
11-12-17 ??:00:03
11-12-17 ??:00:03
11-12-17 ??:00:03
11-12-17 ??:00:03
11-12-17 ??:00:03
······(省略)
该显示部分居然出现问号
请大神帮帮忙解决下,就一句代码不理解,3Q,代码如下:
# include <reg52.h>
# define WRITE_ADDRESS 0x80
# define READ_ADDRESS 0x81
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit SDA = P3^4;
sbit SCK = P3^5;
sbit RST = P1^7;
uint8 Time[] = {0,0,0,17,12,7,11}; //设置DS1302的初始值,分别为:秒,分,时,日,月,周,年
void delay(uint16 counter)
{
while(--counter);
}
void DS1302_Initial()
{
RST = 0;
SCK = 0;
RST = 1;
}
void DS1302_InputByte(uint8 BYTE) //写一个字节
{
uint8 i;
for(i = 0;i < 8;i++)
{
BYTE >>= 1;
SDA = CY;
SCK = 1;
SCK = 0;
}
}
void Write_DS1302(uint8 ADDRESS,uint8 BYTE)
{
DS1302_Initial();
DS1302_InputByte(ADDRESS);
DS1302_InputByte(BYTE);
RST = 0; //该句前面不用对SDA进行处理,不懂!!
}
uint8 DS1302_OutputByte() //读一个字节
{
uint8 i;
for(i = 0;i < 8;i++)
{
ACC >>= 1;
if(SDA)
ACC |= 0x80;
SCK = 1;
SCK = 0;
}
return ACC;
}
uint8 Read_DS1302(ADDRESS) //读时间子函数
{
DS1302_Initial();
DS1302_InputByte(ADDRESS);
ACC = DS1302_OutputByte();
SDA = 0; //罪魁祸首,就这句如果删了就出现错误了,大大们看看为什么?
RST = 0;
return ACC;
}
void Read_Time() //读时间
{
uint8 i,addr;
addr = READ_ADDRESS;
for(i = 0;i < 7;i++) //读7次,存入Time数组
{
Time = Read_DS1302(addr);
addr += 2;
}
}
void DS1302_If_Protece(bit Flag) //设置写保护或者清写保护
{
if(Flag)
{
Write_DS1302(0x8e,0x80);
}
else
{
Write_DS1302(0x8e,0);
}
}
void DS1302_SetTime() //设置初始时间
{
uint8 i,temp;
for(i = 0;i < 7;i++) //转换成BCD码
{
temp = Time/10;
Time = Time%10;
Time = Time + temp * 16;
}
temp = WRITE_ADDRESS;
DS1302_If_Protece(0);
for(i = 0;i < 7;i++) //写入DS1302
{
Write_DS1302(temp,Time);
temp += 2;
}
DS1302_If_Protece(1);
}
void Serial_Initial() //串口初始化
{
TMOD = 0x20;
SCON = 0x40;
TH1 = 0xfd;
TL1 = TH1;
TR1 = 1;
}
void Serial_OutputByte(uint8 Byte)
{
SBUF = Byte;
while(!TI);
TI = 0;
}
void Serial_OutputTime(uint8 Data)
{
Serial_OutputByte(Data/16+'0'); //读回来的数据转换成字符送调试助手显示
Serial_OutputByte(Data%16+'0');
}
void main()
{
Serial_Initial();
DS1302_SetTime();
while(1)
{
Read_Time();
Serial_OutputTime(Time[6]);
Serial_OutputByte('-');
Serial_OutputTime(Time[4]);
Serial_OutputByte('-');
Serial_OutputTime(Time[3]);
Serial_OutputByte(' ');
Serial_OutputTime(Time[2]);
Serial_OutputByte(':');
Serial_OutputTime(Time[1]);
Serial_OutputByte(':');
Serial_OutputTime(Time[0]);
Serial_OutputByte('\r');
Serial_OutputByte('\n');
delay(10000);
}
}
[最优解释]
= 0x80;
SCK = 1;
SCK = 0;
}
return ACC;
}
这个我认为有问题,首先读取数据是下降沿有效,然而你读取第一位时候没有给出一个下降沿 导致的错误,而红色那个SDA=0纯属侥幸 刚好正确。
建议改成
uint8 DS1302_OutputByte() //读一个字节
{
uint8 i;
for(i = 0;i < 8;i++)
{
ACC >>= 1;
SCK = 1;
SCK = 0;
if(SDA)
ACC
[其他解释]
高手都去吃饭了。- -
[其他解释]
这个具体什么原因,偶也不清楚
印象中在用DS1302的时候,读完全部数据后,总线还要求拉高
否则,之后读出来的数据会出错
当时,是为什么我也不知道。。。
不知道能不能归到硬件特性上
[其他解释]