搜索
bottom↓
回复: 13

I2C连续读的时候发送应答型号应该是怎样的?

[复制链接]

出0入10汤圆

发表于 2014-7-22 14:58:04 | 显示全部楼层 |阅读模式
下面是程序,从电容触摸屏中读取坐标,问题是如果我每次只读一个地址的数据就没问题,连续读取的话就会都是第一个地址的数据,
void i2c_master_send_ACK( void)
{
        SDA = 1;
        i2c_delay();
        SCL = 1;
        i2c_delay();
        SCL = 0;
        i2c_delay();
}
这里发送应答应该是将SDA=0才感觉是对的,要拉低SDA给对方应答信号,但是如果这里发送SDA=0的话,
后面就连读一次的数据都会出现这个错误printf("msg i2c read error: %d\n",ret);
现在的程序至少执行ft5x06_i2c_rxdata(u8 *rxdata,u8 length)的length长度=1的不会出现任何错误
请帮忙看一下.

  1. void i2c_delay(void)
  2. {
  3.         u8 i=5;
  4.         while(i--);
  5. }

  6. void i2c_start(void)
  7. {
  8.         SDA = 1;
  9.         SCL = 1;
  10.         i2c_delay();
  11.         SDA = 0;
  12.         i2c_delay();
  13.         SCL = 0;
  14.         i2c_delay();
  15. }

  16. void i2c_stop(void)
  17. {
  18.         SDA = 0;
  19.         SCL = 1;
  20.         i2c_delay();
  21.         SDA = 1;
  22.         i2c_delay();
  23. }

  24. void i2c_master_send_ACK( void)
  25. {
  26.         SDA = 1;
  27.         i2c_delay();
  28.         SCL = 1;
  29.         i2c_delay();
  30.         SCL = 0;
  31.         i2c_delay();
  32. }

  33. u8 i2c_master_recv_ACK(void)
  34. {
  35.         u8 ACK=0;
  36.         SCL = 1;
  37.         i2c_delay();
  38.        
  39.         ACK |= SDA;
  40.         i2c_delay();
  41.        
  42.         SCL = 0;
  43.         i2c_delay();
  44.         return ACK;
  45. }

  46. u8 i2c_master_send_byte(u8 Byte)
  47. {
  48.         u8 i,ACK;
  49.         for(i=0;i<8;i++)
  50.         {
  51.                 SDA = Byte>>(7-i)&0x01;
  52.                 i2c_delay();
  53.                 SCL = 1;
  54.                 i2c_delay();
  55.                 SCL = 0;
  56.                 i2c_delay();
  57.         }
  58.         ACK = i2c_master_recv_ACK();
  59.         return ACK;                        //ACK=1=失败,ACK=0=成功
  60. }

  61. u8 i2c_master_recv_byte( void )
  62. {
  63.         u8 i,temp;
  64.         for(i=0;i<8;i++)
  65.         {
  66.                 temp=temp<<1;
  67.                 SCL = 1;
  68.                 i2c_delay();
  69.                 temp |= SDA;
  70.                 SCL = 0;
  71.                 i2c_delay();
  72.         }
  73.         return temp;
  74. }

  75. //i2c数据传输,每次传输一个数据包
  76. int i2c_transfer_msg(u8 SlaveAddr_and_RorW , u8 *msg , u8 length)
  77. {
  78.         int ret;
  79.         u8 i;
  80.         i2c_start();
  81.         ret = i2c_master_send_byte(SlaveAddr_and_RorW);
  82.         if(SlaveAddr_and_RorW&0x01)                        //RorW=1=Read
  83.         {
  84.                 for(i=0;i<length;i++)
  85.                 {
  86.                         msg[i]=i2c_master_recv_byte();
  87.                         i2c_master_send_ACK();
  88.                 }
  89.         }
  90.         else        //RorW=0=Write
  91.         {
  92.                 for(i=0;i<length;i++)
  93.                 {
  94.                         ret += i2c_master_send_byte(msg[i]);
  95.                 }
  96.         }
  97.         i2c_stop();
  98.         return ret;                //=0表示没任何错误
  99. }

  100. //master从ft5x06中读数据,数据缓冲区第一个字节为起始读地址
  101. static int ft5x06_i2c_rxdata(u8 *rxdata,u8 length)
  102. {
  103.         int ret;
  104.         u8 SlaveAddr_and_RorW;
  105.         SlaveAddr_and_RorW = (ft5x06_I2C_SLAVE_ADDRESS<<1) + 0;        //Write
  106.         ret = i2c_transfer_msg(SlaveAddr_and_RorW,rxdata,1);
  107.                
  108.         SlaveAddr_and_RorW = (ft5x06_I2C_SLAVE_ADDRESS<<1) + 1;        //Read
  109.         ret += i2c_transfer_msg(SlaveAddr_and_RorW,rxdata,length);
  110.         if(ret)
  111.                 printf("msg i2c read error: %d\n",ret);
  112.         return ret;                //=0表示没任何错误
  113. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出1000入0汤圆

发表于 2014-7-22 15:10:25 | 显示全部楼层
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

I2CREAD最后一个字节后(从机不知何为最后字节),若主机回应ACK,从机会自动将下一字节准备好,并将其高位输出到SDA上。若高位为0(SDA=0),主机发不出STOP信号(SDA不能由低变高),总线进入死锁态。



出0入10汤圆

 楼主| 发表于 2014-7-22 15:38:37 | 显示全部楼层
david1234 发表于 2014-7-22 15:10
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

I2CREAD最后一个字节后(从机不知何为最后 ...

谢谢,这个问题我没注意到,要发送一个noack后再stop

但是现在还没到这个错误这里,连续读取的第二个字节就已经出错了,和第一个字节内容一样,感觉是应答没发好,从机没有把第二个字节准备好给我。

出0入0汤圆

发表于 2014-7-22 16:52:00 | 显示全部楼层
david1234 发表于 2014-7-22 15:10
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

I2CREAD最后一个字节后(从机不知何为最后 ...

弄个超时,重发。

出0入0汤圆

发表于 2014-7-22 20:17:24 | 显示全部楼层
楼主,你的i2c_master_send_ACK、i2c_master_recv_ACK 、i2c_master_recv_byte 这些函数是错误的。
接收每个位之前,SDA应该先置1,这样才能接收到正确的数据位。

出0入0汤圆

发表于 2014-7-22 20:48:28 | 显示全部楼层
主机先发送应答

出1000入0汤圆

发表于 2014-7-22 21:14:07 来自手机 | 显示全部楼层
受5楼提示,在sendack中, sda=0。recack中,sda =1。你程序中刚好都反了。

出0入10汤圆

 楼主| 发表于 2014-7-22 22:16:28 | 显示全部楼层
laoshuhunya 发表于 2014-7-22 20:17
楼主,你的i2c_master_send_ACK、i2c_master_recv_ACK 、i2c_master_recv_byte 这些函数是错误的。
接收每 ...

先SDA=1的话,ret错误提示那里字符串狂出

出0入10汤圆

 楼主| 发表于 2014-7-22 22:17:56 | 显示全部楼层
可是我程序目前读写一个字节的时候都正常的呢...
我要另外找个i2c器件来验证一下i2c

出0入0汤圆

发表于 2014-7-23 01:04:46 | 显示全部楼层
bias 发表于 2014-7-22 22:17
可是我程序目前读写一个字节的时候都正常的呢...
我要另外找个i2c器件来验证一下i2c ...

可以参考下这个帖子:
http://www.amobbs.com/forum.php?mod=viewthread&tid=5587231&page=1#pid7701082
  

出0入0汤圆

发表于 2014-7-23 01:18:23 来自手机 | 显示全部楼层
david1234 发表于 2014-7-22 15:10
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

I2CREAD最后一个字节后(从机不知何为最后 ...

如不幸出现此情况,该如何处理?做个超时对i2c从设备重新加电?

出1000入0汤圆

发表于 2014-7-23 07:03:11 来自手机 | 显示全部楼层
本帖最后由 david1234 于 2014-7-23 08:03 编辑

首先,最后一次读不发ACK就不死锁。若死锁,可连发9个时钟信号,再发STOP   

出1000入0汤圆

发表于 2014-7-23 07:05:50 来自手机 | 显示全部楼层
bias 发表于 2014-7-22 22:17
可是我程序目前读写一个字节的时候都正常的呢...
我要另外找个i2c器件来验证一下i2c ...

因为你的ACK 不对,所以后续通信都不正确

出1000入0汤圆

发表于 2014-7-23 08:03:13 | 显示全部楼层
楼主,用下面函数,应该就好了:

void i2c_master_send_ACK( void)
{
        SDA = 0;
        i2c_delay();
        SCL = 1;
        i2c_delay();
        SCL = 0;
        i2c_delay();
}

void i2c_master_send_NAK( void)
{
        SDA = 1;
        i2c_delay();
        SCL = 1;
        i2c_delay();
        SCL = 0;
        i2c_delay();
}


u8 i2c_master_recv_ACK(void)
{
        SDA=1
       u8 ACK=0;
        SCL = 1;
        i2c_delay();
      
        ACK |= SDA;
        i2c_delay();
      
        SCL = 0;
        i2c_delay();
        return ACK;
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 02:09

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表