9815|14

60

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

关于DS1302的读数据时序 [复制链接]

   遇到一个奇怪的事情,开发板上的读取DS1302的时序与datasheet上的不一致,却能正常读写;我按照我的理解改写后,确不能读写。具体如下:

   1.  该图是DS1302的读时序,可以看到数据是下降沿后输出。也就是在SCLK下降沿后,I/O上输出串行数据,该数据需要单片机对其接收。对于这种方式,用一种不太恰当的说法就是“10D10D10D......”,其中1、0表示SCLK的输出,D表示单片机接收数据

   2.  开发板上的程序如下:

 

     Write_Ds1302_Byte(address);   //写入“读”控制命令
     for (i=0;i<8;i++)   //循环8次 读取数据
       {  
        if(SDA)
            temp|=0x80;   //每次传输低字节
        SCK=0;
        temp>>=1;   //右移一位
        SCK=1;
        _nop_();
       }

 

      同样用上述表达方式,这个程序的流程是“D01D01D01......”,这显然是与datasheet上的说法不同。

 

 3.  用2的程序,可以正常读写;若把它的流程改为与datasheet一致,即“10D10D......”,显示却不能正常读写。

       改程序只需改for循环内部,改后如下:  

 

       SCK=0;        //上一个函数已将SCK给1,故给0即产生下降沿  
        if(SDA)
            temp|=0x80;   //每次传输低字节
         temp>>=1;   //右移一位
         SCK=1;
        _nop_();

 

是我理解错了,还是datasheet上的图有误?求指教!

 

读时序.jpg (1.15 MB, 下载次数: 62)

读时序.jpg
此帖出自51单片机论坛

最新回复

楼主提供的开发板程序 我 的和你一样。我认为 读数据时是这样的: 1.刚开始的SDA会被8次移位移出去,对结果无影响。 2.第一次产生的下降沿所释放的数据被下一次for循环给捕捉,共进行了7次有效捕捉。 3.在for循环结束后应该加上语句:if(SDA)             temp|=0x80; 对1302的最高位进行捕获。 4.程序不修改能正常运行 我认为是:每次移位最高位被0代替,1302的各时间寄存器最高位内部永远达不到1,因为59对应01011001(BCD)。阴差阳错。 以上是我的见解。请指正。 改正的程序: for (i=0;i>=1;                        SCK=1;                 _nop_();                 _nop_();                                //此处才开始产生下降沿,产生的数据会在下一次循环中被接受                 SCK=0;                                                                                _nop_();            _nop_();                        //右移一位                 }         if(SDA)temp|=0x80;    // 对最后释放的数据 进行采集 [ 本帖最后由 bvcbvc 于 2012-8-14 20:40 编辑 ]  详情 回复 发表于 2012-8-14 10:12
点赞 关注(1)
 

回复
举报

315

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 

2的程序能正确?除非Write_Ds1302_Byte(address);结尾有sck=0

3的程序,会多移一位。

     Write_Ds1302_Byte(address);   //写入“读”控制命令
     for (i=0;i<8;i++)   //循环8次 读取数据
       {

        temp>>=1;   //右移一位

        SCK=0; 
        if(SDA)
            temp|=0x80;   //每次传输低字节
        SCK=1;
        _nop_();
       }

还是这么写的好吧

[ 本帖最后由 孤獨の快樂 于 2011-11-22 18:13 编辑 ]
此帖出自51单片机论坛
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(中级)

板凳
 

回复 沙发 孤獨の快樂 的帖子

对于2的程序,下载到板子上是能够正常读写的。并且Write_Ds1302_Byte(address)的结尾是SCK=1,这样下面给0后就构成下降沿,这个没问题,你可以再看下时序图。顺便把Write_Ds1302_Byte(address)的代码也贴出来:
      
     void Write_Ds1302_Byte(unsigned  char temp1)
           {
              unsigned char i;
                 for (i=0;i<8;i++)             //循环8次 写入数据
          {
                      SCK=0;
                     SDA=temp1&0x01;             //每次传输低字节
           temp1>>=1;                  //右移一位
           SCK=1;
                     }
             }  

   对于你的写法,产生的时序与2是一样的,只是SCK高点平维持的时间长一点而已。下载到板子上验证与2的效果一样。
此帖出自51单片机论坛
 
 
 

回复

315

帖子

0

TA的资源

五彩晶圆(初级)

4
 

很奇怪,if(SDA)  temp|=0x80;  是在SCK=0;之后,那第一次的循环的数据就没取吧?

此帖出自51单片机论坛
 
 
 

回复

56

帖子

0

TA的资源

一粒金砂(高级)

5
 
不能理解这个语句 temp|=0x80;   //每次传输低字节   
要传输低字节不是应该 temp&=0x01么
不知道是不是定义的不一样还是怎么
既然是右移,比较的应该是最低位啊。。。
能力有限。。越来越糊涂了。。。。
此帖出自51单片机论坛
 
 
 

回复

315

帖子

0

TA的资源

五彩晶圆(初级)

6
 

原帖由 abo6016 于 2011-11-23 16:21 发表 不能理解这个语句 temp|=0x80;   //每次传输低字节 要传输低字节不是应该 temp&=0x01么不知道是不是定义的不一样还是怎么既然是右移,比较的应该是最低位啊。。。能力有限。。越来越糊涂了 ...

传输低字节是指DS1302传输数据给单片机。

if(SDA)

  temp|=0x80;

是将收到的数据按位保存起来的。

SDA为1时,temp最高位置1,SDA为0时,temp最高位保持0

每收到一个数据就右移一位,所以最先收到的数据就是最低位。

[ 本帖最后由 孤獨の快樂 于 2011-11-26 03:02 编辑 ]
此帖出自51单片机论坛
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(中级)

7
 

弄清楚了!非常感谢 孤獨の快樂的指教!具体如下:

  1. 孤獨の快樂 的程序是对的,我上面说错了,他的程序与程序2的读写流程不同,与程序3的循环移位不同。

        我在上面轻易断定他的程序无用,是大错特错, 孤獨の快樂,不好意思了,

 

  2. 程序3的错误如孤獨の快樂所说,移位丢失了一位。

      程序2不仅循环移位错了,而且读写时序也错了。但为什么下载到板子上现象正常呢?请往下看

      为方便说明,挂了张图如下,画得很丑,见谅!

    

    先说读写时序错误 

     正常的读数据时机应该是I/O线上的后面的那8个六边形,如图中“1、2、。。8”

     程序2读数据的时机在SCLK的高电平期间,并且比正常的时机提前大约半个SCLK脉冲周期,

     如图中SCLK后8个高电平上的长方形所示。

 

     在图中可以看到,第1个长方形出现时,SCLK还没有下降沿,故I/O上也还没有正常输出,此时读取的数据无效,用“?”表示。

     在第2个长方形到第8个长方形间,如果I/O的输出数据在两个下降沿间均有效,那么这期间就能读到数据,

     但是,读到的数据是前一个下降沿触发输出的。

 

     这样,第1个长方形被浪费,后面7个依次读取数据“1、2、3、。。。7”,第8位数据没有长方形来读,被丢弃。

     在这种时序下,“87654321”会被读成“7654321?”。(?表示无效数据)

   

     由于程序2又犯了移位错误,“7654321?”又变成了“07654321”   

    

     这就是个很大的漏洞了。如果正确的数据最高位为0,那么将会一切正常;否则,才会出现错误!

     比如:设定09年04月15日,读出来显示的是正常的;

                设定99年04月15日,读出来显示的是19年04月15日,此时错误才显现。    

 

  3.  我用程序2下载,现象正常,原因即如上所述。同时也反证了上面红色字体的假设是成立的,

         那么,datasheet上的I/O数据六边形应该拉长,即图中比特1的维持长度应是所画两条直竖线之间。    

 

 

读时序.jpg (1.15 MB, 下载次数: 20)

读时序.jpg
此帖出自51单片机论坛

赞赏

1

查看全部赞赏

 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(中级)

8
 
谢谢版主小小白,自己顶个~
此帖出自51单片机论坛
 
 
 

回复

56

帖子

0

TA的资源

一粒金砂(高级)

9
 

回复 6楼 孤獨の快樂 的帖子

是我没看仔细,我晕= = 下次会注意,我看成是写指令了= =还在纳闷。。
此帖出自51单片机论坛
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(中级)

10
 

这个帖子不错,也帮助我解决了问题。

    我说下我的想法吧 ,进入for循环后,先右移一次,再读取数据 。假设原来是00000000 右移后,低位0溢出,高位补0,也就是说开始的最低位是没有意义的。我们再想一下这个问题,第一次读取的数据放在最高位,把他移到最低位只需要七次,如果先读取数据再右移的话,那么第一次读取的数据会被溢出,而且最高位会补0.所以会出错。

    也就是说我们希望的是读取八次,但是只需要移动七次。

 

此帖出自51单片机论坛
 
 
 

回复

60

帖子

0

TA的资源

一粒金砂(中级)

11
 

回复 10楼 zdl133447567 的帖子

"我们希望的是读取八次,但是只需要移动七次"
  精辟!
此帖出自51单片机论坛
 
 
 

回复

7173

帖子

195

TA的资源

五彩晶圆(高级)

12
 
很不错的讲解 适合初学者 顶顶
此帖出自51单片机论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

13
 
嗯,,这个说明两方面的知识,
1.时序问题
2.移位问题,
都是有一点小纠结,但是都是很经典,这个移位以及他应该放的位置 与前个控制字的scl是否制0,有关,,
此帖出自51单片机论坛
 
 
 

回复

38

帖子

0

TA的资源

一粒金砂(中级)

14
 
这个帖子不错,以前没注意到,学习了,呵呵
此帖出自51单片机论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(中级)

15
 

关于DS1302的读数据时序

楼主提供的开发板程序 我 的和你一样。我认为 读数据时是这样的:
1.刚开始的SDA会被8次移位移出去,对结果无影响。
2.第一次产生的下降沿所释放的数据被下一次for循环给捕捉,共进行了7次有效捕捉。
3.在for循环结束后应该加上语句:if(SDA)
            temp|=0x80; 对1302的最高位进行捕获。
4.程序不修改能正常运行 我认为是:每次移位最高位被0代替,1302的各时间寄存器最高位内部永远达不到1,因为59对应01011001(BCD)。阴差阳错。
以上是我的见解。请指正。
改正的程序:
for (i=0;i<8;i++)                 //循环8次 读取数据
        {        
                if(SDA)            //注意到第一次sda的数据是随机的,最终会被8次移位移出去  
                temp|=0x80;                        //每次传输低字节
                temp>>=1;       
                SCK=1;
                _nop_();
                _nop_();                                //此处才开始产生下降沿,产生的数据会在下一次循环中被接受
                SCK=0;                                                               
                _nop_();
           _nop_();                        //右移一位
       
        }
        if(SDA)temp|=0x80;    // 对最后释放的数据 进行采集

[ 本帖最后由 bvcbvc 于 2012-8-14 20:40 编辑 ]
此帖出自51单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表