微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > DS1302读取数据问题

DS1302读取数据问题

时间:10-02 整理:3721RD 点击:

    各位,我用单片机驱动DS1302的时候遇到了一点问题,在读取数据的时候,使用下面的程序时读取的数值总是错误的,
        for(i=0;i<8;i++)
        {
                ds1302_SCLK=1;
                ds1302_SCLK=0;
                if(ds1302_IO==1)
                        date=date|0x80;
                date>>=1;
        }
而使用下面的程序的时候就是正确的
        for(i=0;i<8;i++)
       {
                if(ds1302_IO)
                        date|=0x80;                        //每次传输低字节
               ds1302_SCLK=0;
              date>>=1;                      //右移一位
                 ds1302_SCLK=1;
        }
看资料说是在下降沿读走数据,而这对于这两个函数断,为啥第一个不行,而第二个行,小弟实在是搞不明白,还望哪位大侠指点一下...!         

两个程序有着根本的区别。
要注意读数据时,SCLK的状态。

要是 下降沿时候 芯片送出数据的话,你的程序貌似没有错....


这儿说的很明白,,数据的第一位,是紧接着命令最后一位的下降沿,期间需要保持RST高。
你的第一段代码,进入到循环首先就拉高,然后拉低,产生一个下降沿,但是芯片则会认为这个是外部信号的第二个上升沿,因为芯片认为的第一个下降沿是在你写命令操作的最后一位结束的时候的那个下降沿。因此芯片在你写操作命令完成后,马上就输出了数据的第一位,换言之 ,数据在你进入到循环之前已经发送出来了,但是你去还么有意识到,所以你始终错过了数据的第一bit。

先把数据写到端口上,再通过时钟信号,将这个信号移出

好的,非常感谢...!祝生活愉快

你好,非常感谢...!我看了之后做了修改,还是不行,因为在写完地址的最后一个字节后sclk是处于高电平的状态,进入读状态的时候第一次ds1302_SCLK=1;sclk并没有发生变化,所以应该是没有使sclk错过一个周期。也许是我还没能彻底理解你的意思或者理解错了,以下是修改还是不行的结果(/**/中间被注释掉的是可以正常工作的)
uchar ds1302_read_byte(uchar address)
{
        unsigned char date,i,temp;
        temp=address;
        ds1302_CE=0;
        ds1302_SCLK=0;
        ds1302_IO=0;
        ds1302_CE=1;
        //写地址
        for(i=0;i<8;i++)
        {       
                ds1302_SCLK=0;
                ds1302_IO=temp&0x01;
                temp>>=1;
                ds1302_SCLK=1;
        }
        //读数据
        for(i=0;i<8;i++)
        {
                ds1302_SCLK=0;
                if(ds1302_IO==1)
                        date=date|0x80;
                date>>=1;
                ds1302_SCLK=1;
                /*if(ds1302_IO)
                        date|=0x80;                        //每次传输低字节
                ds1302_SCLK=0;
                date>>=1;                        //右移一位
                ds1302_SCLK=1; */
        }
        ds1302_CE=0;
        return date;
}
也许像版祝所说的,先把数据写到端口上,再通过时钟信号,将这个信号移出。也很有可能是我还没能理解你的意思!
非常谢谢,祝生活愉快...!

非常感谢...!
还是有一点不明白,说是在下降沿送出数据,可为什么写程序是先写下降沿再写读数据就不行,而先写读数据再写下降沿就行...!这点老是想读懂,以下是修改后的程序,/**/注释掉的是可以正常工作的,没有注释掉的读出的数据有误...!
已定义过#define uchar unsigned char
uchar ds1302_read_byte(uchar address)
{
        uchar date,i,temp;
        temp=address;
        ds1302_CE=0;
        ds1302_SCLK=0;
        ds1302_IO=0;
        ds1302_CE=1;
        //写地址
        for(i=0;i<8;i++)
        {        
                ds1302_SCLK=0;
                ds1302_IO=temp&0x01;
                temp>>=1;
                ds1302_SCLK=1;
        }
        //读数据
        for(i=0;i<8;i++)
        {
                ds1302_SCLK=0;
                if(ds1302_IO==1)
                        date=date|0x80;
                date>>=1;
                ds1302_SCLK=1;
                /*if(ds1302_IO)
                        date|=0x80;                        //每次传输低字节
                ds1302_SCLK=0;
                date>>=1;                        //右移一位
                ds1302_SCLK=1; */
        }
        ds1302_CE=0;
        return date;
}
非常感谢,祝生活愉快...!

呵呵,研究中,非常感谢...!祝生活愉快...!

学习学习……………………

时序 是没有问题。
很奇怪,你修改了上面写数据那段代码之后,然后再采用 原来 注释掉的内容可以运行成功么,,,感觉不可以才对啊 。


仔细分析下,两端代码的异同,现在我怀疑是 ds1302芯片的 反应速度不够,所以现在每次下降沿后给一个小的延时,,你再试试。当然延时我只是大概给的,可能会影响速度,你可以试一下减少延时的时间,测一下极限

  1. void delay(unsigned char i)
  2. {
  3.     unsigned char j;
  4.    for( ; i > 0; i--)
  5.    {
  6.        for(j = 50; j > 0; j--)
  7.             ;
  8.    }
  9. }

  10. uchar ds1302_read_byte(uchar address)
  11. {
  12.         unsigned char date,i,temp;
  13.         temp=address;
  14.         ds1302_CE=0;
  15.         ds1302_SCLK=0;
  16.         ds1302_IO=0;
  17.         ds1302_CE=1;
  18.         //写地址
  19.         for(i=0;i<8;i++)
  20.         {        
  21.                 ds1302_SCLK=0;
  22.                 ds1302_IO=temp&0x01;
  23.                 temp>>=1;
  24.                 ds1302_SCLK=1;
  25.         }
  26.         
  27.         ds1302_IO=1;//拉高数据信号,避免影响芯片输出
  28.         //读数据
  29.         for(i=0;i<8;i++)
  30.         {
  31.                 ds1302_SCLK=0;
  32.                 delay(2);//小延时,留给芯片足够的时间
  33.                 if(ds1302_IO==1)
  34.                         date=date|0x80;
  35.                 date>>=1;
  36.                 ds1302_SCLK=1;
  37.                 delay(2);//小延时,留给芯片足够的时间
  38.                 /*if(ds1302_IO)
  39.                         date|=0x80;                        //每次传输低字节
  40.                 ds1302_SCLK=0;
  41.                 date>>=1;                        //右移一位
  42.                 ds1302_SCLK=1; */
  43.         }
  44.         ds1302_CE=0;
  45.         return date;
  46. }

复制代码

我最近也要 用到这款ds1302芯片 ,留个qq一起交流下....

你好,非常谢谢...!
试了你的方法,加了延时,还是和之前一样,可以读出数据,只是读出的数据是错误的...!
程序中那个被注释掉的是可以正常工作的...!
我复制上来一下
#define uchar unsigned char
uchar ds1302_read_byte(uchar address)
{
        uchar date,i,temp;
        temp=address;
        ds1302_CE=0;
        ds1302_SCLK=0;
        ds1302_IO=0;
        ds1302_CE=1;
        //写地址
        for(i=0;i<8;i++)
        {
               
                ds1302_SCLK=0;
                ds1302_IO=temp&0x01;
                temp>>=1;
                ds1302_SCLK=1;
        }
        //读数据
        for(i=0;i<8;i++)
        {
                if(ds1302_IO)
                        date|=0x80;                        //每次传输低字节
                ds1302_SCLK=0;
                date>>=1;                        //右移一位
                ds1302_SCLK=1;         
        }
        ds1302_CE=0;
        return date;
}

656130367

对不起,是我大意了...
先试试这个程序

  1. void delay(unsigned char i)
  2. {
  3.     unsigned char j;
  4.    for( ; i > 0; i--)
  5.    {
  6.        for(j = 50; j > 0; j--)
  7.             ;
  8.    }
  9. }

  10. uchar ds1302_read_byte(uchar address)
  11. {
  12.         unsigned char date,i,temp;
  13.         temp=address;
  14.         ds1302_CE=0;
  15.         ds1302_SCLK=0;
  16.         ds1302_IO=0;
  17.         ds1302_CE=1;
  18.         //写地址
  19.         for(i=0;i<8;i++)
  20.         {        
  21.                 ds1302_SCLK=0;
  22.                 ds1302_IO=temp&0x01;
  23.                 temp>>=1;
  24.                 ds1302_SCLK=1;
  25.         }
  26.         
  27.         ds1302_IO=1;//拉高数据信号,避免影响芯片输出
  28.         //读数据
  29.         for(i=0;i<8;i++)
  30.         {
  31.                 ds1302_SCLK=0;
  32.                 date>>=1;
  33.                 delay(2);//小延时,留给芯片足够的时间
  34.                 if(ds1302_IO==1)
  35.                         date=date|0x80;
  36.                 ds1302_SCLK=1;
  37.                 delay(2);//小延时,留给芯片足够的时间
  38.                 /*if(ds1302_IO)
  39.                         date|=0x80;                        //每次传输低字节
  40.                 ds1302_SCLK=0;
  41.                 date>>=1;                        //右移一位
  42.                 ds1302_SCLK=1; */
  43.         }
  44.         ds1302_CE=0;
  45.         return date;
  46. }

复制代码

以明白,谢谢...!

请问一下加这句 if(ds1302_IO) 判断数据输出是否为高电平是什么意思呢  谢谢

那儿是他原来的程序, 我屏蔽了的哟,没有使用呢

date>>=1写错地方了  
你这样读取的数据最高位永远是0

我最近也遇到了这个问题!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top