打印

请教一下,i2c能读、写单个数据,可读数据块时出错。

[复制链接]
5345|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jiuri|  楼主 | 2012-5-16 22:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如题。通过i2c读单个地址时能正确读出,写单个数据也能正确写入(写入再读出)。可是在读数据块时就只能读第一个字节,其后的要不是ff就是00。主机回复ack信号可能出错,搞了一天也没好。
“主控设备接收到数据后,发送ACK应答信号表示继续传送数据”。数据从ad7746出来,读是读默认值。
局部程序如下。请路过的大侠帮忙看看错在哪。谢谢
smbus_dubyte:;读数据  ,这是读单个数据子程序,是单个读时没问题的。
    mov r4,#8h
    clr a
readrepx:
    rl a  ;左移1位   
    clr p0.7                     ;scl      
    nop
    nop
    setb p0.7                   ;scl   
    nop     
    nop
   jnb p0.6,readrepx_a     ;sda      
   inc a   
readrepx_a:
    nop
    djnz r4,readrepx;     
     ret
;下面是读数据块程序,回复ack那里有问题,搞不明白、
;按照手册,在scl第9个时钟脉冲为高时单片机把sda拉为底就行嘛,为什么在接收第二个数据时就出错了呢?期待回复


;
;
;
;

      mov r0,#40h
      mov r2,#00h    ;读ad7746的地址
smbus_read_cap_a:
      acall smbus_dubyte;读数据 ;数据到a内
       clr p0.6           ;sda
       clr p0.7             ;scl
    nop
    nop
    nop
      setb p0.7          ;scl   
nop
nop
nop  
     clr p0.7                ;scl  
    setb p0.6               ;为输入时,要拉为高才行     
    mov @r0,a
    inc r0
    inc r2
    cjne r2,#10h, smbus_read_cap_a  ;取10h个数  
    acall smbus_stop  ;发送停止位  
    ret

相关帖子

沙发
NE5532| | 2012-5-16 22:42 | 只看该作者
你应答在什么地方写的?

使用特权

评论回复
板凳
jiuri|  楼主 | 2012-5-16 22:49 | 只看该作者
在调用接收数据之后呀,下面就是嘛。我也认为这有问题,不知道应该怎么改
    clr p0.6           ;sda
       clr p0.7             ;scl
    nop
    nop
    nop
      setb p0.7          ;scl   
nop
nop
nop  
     clr p0.7                ;scl  
    setb p0.6               ;为输入时,要拉为高才行

使用特权

评论回复
地板
ningling_21| | 2012-5-16 23:01 | 只看该作者
有些器件对块写的字节数是有限制的...
另,应答信号又分,接收应答和发送应答.

使用特权

评论回复
5
NE5532| | 2012-5-16 23:10 | 只看该作者
楼主啊,我看得懂你的程序,我是故意问你的,你没有动脑经。

你写的那个根本不叫注释,看程序的人(包括你自己)不能从里面得到任何信息。

clr     p0.6     ;拉低SDA,开始应答过程
setb p0.7      ;发送应答位时钟
clr     p0.7

就是这一点差别,鉴别出我们之间的差距。你早这样写,早就看出来了。你的读函数退出的时候SCL是停留在高电平状态的,而你的应答部分开始就动了SDA,I2C协议在SCL为高期间动SDA的,只有启动和停止两个动作,所以你做的不是应答,是“重启动”~!

使用特权

评论回复
6
NE5532| | 2012-5-16 23:11 | 只看该作者
还有你发完应答,SDA凭什么要置为输入?输入应该是在需要输入的函数自己来设置的,楼主对程序模块化还有问题。推荐本版精华帖《程序调试黑宝书》

使用特权

评论回复
7
jiuri|  楼主 | 2012-5-16 23:12 | 只看该作者
我是读数据,应该是接收数据,主机发应答···,数据块接收时,从机数据第二个数据出来应该与scl时钟一致吧

使用特权

评论回复
8
NE5532| | 2012-5-16 23:26 | 只看该作者
没错,是应该这样发啊,只是你没有注意函数之间接口时SCL应该处于的状态,把应答发成了启动位,所以从机当然不会再发送后续数据咯。

使用特权

评论回复
9
jiuri|  楼主 | 2012-5-16 23:27 | 只看该作者
看看别人写的程序才发觉自己写的很乱,改写后明天重新试机。时序可能有问题。应该每次读完或是写完都把scl拉底。先应答(sda=0)再置高scl,延时后拉底scl,再让sda为输入状态。是吧。明天再试试
谢谢大侠们的支持指点。但愿找到问题所在

使用特权

评论回复
10
sxhgll521| | 2012-5-16 23:32 | 只看该作者
大家都很厉害

使用特权

评论回复
11
jiuri|  楼主 | 2012-5-17 08:48 | 只看该作者
今天好好理了一下,ok了。算是搞清楚了。谢谢各位指点。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

306

帖子

0

粉丝