首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 单片机 >

DS1302的一个有关问题

2012-12-16 
DS1302的一个问题本帖最后由 fjlonng 于 2011-12-19 10:59:54 编辑以下代码在串口调试助手上显示:······(

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的时候,读完全部数据后,总线还要求拉高

否则,之后读出来的数据会出错

当时,是为什么我也不知道。。。

不知道能不能归到硬件特性上
[其他解释]

引用:
这个具体什么原因,偶也不清楚

印象中在用DS1302的时候,读完全部数据后,总线还要求拉高

否则,之后读出来的数据会出错

当时,是为什么我也不知道。。。

不知道能不能归到硬件特性上


SDA就是那个IO接口,那句红色的SDA = 0;改成SDA = 1,也会出现这个?号,闷···············
[其他解释]

引用:

SDA就是那个IO接口,那句红色的SDA = 0;改成SDA = 1,也会出现这个?号,闷···············


用其它的串口调试软件观察一下到底?号是什么字符。我记得以前做点阵LED显示时钟的时候出现过BCD码大于9的情况,后来确认是因为手摸到了IC的引脚,导致寄存器数值发生改变,启用写保护就能消除此现象。但我看你的情况应该不同。这程序我时间不够,没法看完,不知道你是在学习改动别人的代码,还是自己写的代码不工作。如果别人的代码原本很可靠就不要改了,直接用吧。
[其他解释]
uint8 DS1302_OutputByte() //读一个字节
{
  uint8 i;
  
  for(i = 0;i < 8;i++)
  {
  ACC >>= 1;
  if(SDA)
  ACC 
[其他解释]
= 0x80;

  }

  return ACC;
}   

参考建议 呵呵不知道对不
[其他解释]
不好意思 上面那个改进方法 错误 见谅啊
给个写入读取数据的方法
在SCLK为高电平时,DATA线是不能变化的;在SCLK为低电平时,DATA线是可以变化的;所以,写数据的时候,先关数据,再给SCLK上升沿;读数据时,在SCLK下降沿之前读
莫怪~~



热点排行