打印

I2C总线应答信号问题

[复制链接]
9280|15
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
beckham|  楼主 | 2009-5-30 21:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
读了些教材关于I2C总线时序的资料,“接收器每接受一个正确的数据字节后,都要在数据线上发送一个应答信号。低电平为确认,高电平为不确认”,比如单片机发送数据给AT24C02,每发送一个数据,应该调用如下程序:CACK: CLR C
SETB SDA
     SETB SCK
    WAIT: MOV C,SDA
    JC WAIT
      CLR SCK
       RET    ,如此编写,调试通过。
后来看了别人编的例子,每次调用如下子程序: CLR   SDA
           SETB  SCL
      CLR   SCL
      RET  ;这就糊涂了,单片机每发一个数据,自己把数据线拉低?低电平信号不是接收器给的吗?
    调试竟然也通过,不明白!

相关帖子

沙发
ningling_21| | 2009-5-31 10:05 | 只看该作者

应答分主器件应答和从器件应答

主器件写数据后要检查从器件是否正确应答
主器件读数据后,要发送应答信号给从器件的
多字节读完之后,要发送非应答信号给从器件,表示读结束了

使用特权

评论回复
板凳
lyjian| | 2009-5-31 20:21 | 只看该作者

你看的什么资料

“接收器每接受一个正确的数据字节后,都要在数据线上发送一个应答信号。高电平为确认,低电平为不确认”

*********************
把这个资料扔垃圾桶吧

使用特权

评论回复
地板
ayb_ice| | 2009-5-31 21:41 | 只看该作者

搞反了

是低电平确认,高电平非确认...

使用特权

评论回复
5
beckham|  楼主 | 2009-6-2 18:19 | 只看该作者

高低电平确认是我一时写错了,我关心的不是这一点

下面是一段调试成功的源程序。看看它的应答CACK子程序吧,CPU发一个数据就调用CACK,而CACK是把数据线拉低,真奇怪。

SLA       DATA  50H
SUBA      DATA  51H
NUMBYTE   DATA  52H
SDA       BIT   P3.1
SCL       BIT   P3.0
MTD       EQU   30H
MRD       EQU   40H
      ORG    00H
          AJMP  MAIN
          ORG   80H

IWRNBYTE: MOV   R3,NUMBYTE
          LCALL START
      MOV   A,SLA
      LCALL WRBYTE
      LCALL CACK      
      MOV   A,SUBA
      LCALL WRBYTE
      LCALL CACK
      MOV   R1,#MTD
WRDA:     MOV   A,@R1
          LCALL WRBYTE
      LCALL CACK      
      INC   R1
      DJNZ  R3,WRDA
RETWRN:   LCALL STOP
          RET

IRDNBYTE: MOV   R3,NUMBYTE
          LCALL START
      MOV   A,SLA
      LCALL WRBYTE
      LCALL CACK     
      MOV   A,SUBA
      LCALL WRBYTE
      LCALL CACK
      LCALL    START
      MOV   A,SLA
      INC   A
      LCALL WRBYTE
      LCALL CACK
      MOV   R1,#MRD
RON1:     LCALL RDBYTE
          MOV   @R1,A
      MOV    P2,A
      LCALL    DELAY
      DJNZ  R3,SACK
      LCALL MNACK
RETRDN:      LCALL STOP
          RET
SACK:      LCALL MACK
      INC   R1
      SJMP  RON1
START:    SETB  SDA
          NOP
      SETB  SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR   SDA
      NOP
      NOP
      NOP
      NOP
      CLR   SCL
      NOP
      RET
STOP:     CLR   SDA
          NOP
      NOP
      SETB  SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      SETB  SDA
      NOP
      NOP
      NOP
      NOP
      NOP
      RET
MACK:     CLR   SDA
          NOP
      NOP
      SETB  SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR   SCL
      NOP
      NOP
      RET
MNACK:    SETB  SDA
          NOP
          NOP
          SETB  SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR   SCL
      NOP
      NOP
      RET
CACK:     CLR  SDA
          NOP
      NOP
      SETB  SCL
      NOP
      NOP     
      NOP
      CLR   SCL
      NOP
      NOP
      NOP
      RET
WRBYTE:   MOV   R0,#08H
WLP:      RLC   A
          JC    WRI
      SJMP  WRO
WLP1:      DJNZ  R0,WLP
      NOP
      RET
WRI:      SETB  SDA
          NOP
      SETB  SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR   SCL
      SJMP  WLP1
WRO:      CLR   SDA
          NOP
      SETB  SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR   SCL
      SJMP  WLP1

RDBYTE:   MOV   R0,#08H
RLP:      SETB  SDA
      NOP
      NOP
      SETB  SCL
      NOP
      NOP
      NOP
      MOV   C,SDA
      MOV   A,R2
      CLR   SCL
      RLC   A
      MOV   R2,A
      NOP
      NOP
      NOP
      DJNZ  R0,RLP
      RET

MAIN:     MOV   R4,#0F0H
          DJNZ  R4,$
      MOV   A,#00H
      MOV   R0,#30H
S1:      MOV   @R0,A
      INC   R0
      INC   A
      CJNE  R0,#40H,S1
      MOV   SLA,#0A0H
      MOV   SUBA,#30H
      MOV   NUMBYTE,#16
      LCALL IWRNBYTE
      NOP
      MOV   SLA,#0A0H
      MOV   SUBA,#30H
      MOV   NUMBYTE,#16
      LCALL IRDNBYTE
      AJMP    MAIN

DELAY:      MOV   R5,#10
D1:      MOV   R6,#200
D2:      MOV   R7,#200
      DJNZ  R7,$
      DJNZ  R6,D2
      DJNZ  R5,D1
      RET
      END

程序很长,哪位仁兄给看看,先谢了。


使用特权

评论回复
6
NE5532| | 2009-6-2 21:13 | 只看该作者

谁收数据,谁确认。

不想看你的长篇大论,就上面这一句话,自己检查吧。

使用特权

评论回复
7
zyboy| | 2009-6-3 10:17 | 只看该作者

如果按你说的没什么奇怪的

别人编的例子

单片机每发一个数据,自己把数据线拉低?低电平信号不是接收器给的吗?


那就说明别人程序有问题,相当于根本没检测ACK信号。而之所以不出问题,是应该每次从设备都能正确回应,所以不影响。如果从设备有问题的话,他的代码就够他喝一壶的

使用特权

评论回复
8
dengm| | 2009-6-3 10:24 | 只看该作者

用其他数据检验方法, 就可不检测ACK信号

使用特权

评论回复
9
zyboy| | 2009-6-3 11:08 | 只看该作者

i2c通信的一大优点就是可靠性

你不遵循协议标准当然可以,不判断ACK,可靠性降低了,数据校验是通信基本要求,不能因为有这个校验就可以偷懒,就像山寨手机一样,还不是可以用

使用特权

评论回复
10
善解人意| | 2012-7-13 10:16 | 只看该作者
按协议就可以了,汇编现在看起还有点头痛,

使用特权

评论回复
11
joyme| | 2012-7-13 10:34 | 只看该作者
正确的做法是,主设备发送8个位之后,将SDA设置为输入(高阻状态便于从设备应答),主设备在第9个clk里读取SDA的状态来判断从设备是否给了ACK信号(拉低为正常ACK响应)。一般情况I2C通信不会出错,所以很多代码省略了ACK检测,程序也能正常运行,但稳定性肯定不是最好的

使用特权

评论回复
12
wukunshan| | 2012-7-13 11:31 | 只看该作者
那么老的帖子还翻出来?

使用特权

评论回复
13
dlyt_test001| | 2012-7-13 15:29 | 只看该作者
按协议就可以了,汇编现在看起还有点头痛,
善解人意 发表于 2012-7-13 10:16

还是用C看得比较清楚啊!

使用特权

评论回复
14
fjzzclc| | 2012-7-13 16:23 | 只看该作者
写入1个字节(8位数据)后,检测一次应答

使用特权

评论回复
15
nextgtx| | 2013-4-18 14:46 | 只看该作者
很多人小瞧这个问题 不愿意解答  有必要去中伤别人么  都你们这思想  太可悲了

使用特权

评论回复
16
韦斯克拉| | 2014-3-15 11:46 | 只看该作者
mark!!!!!!!

使用特权

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

本版积分规则

81

主题

238

帖子

1

粉丝