bias 发表于 2014-7-22 14:58:04

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

下面是程序,从电容触摸屏中读取坐标,问题是如果我每次只读一个地址的数据就没问题,连续读取的话就会都是第一个地址的数据,
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的不会出现任何错误
请帮忙看一下.

void i2c_delay(void)
{
        u8 i=5;
        while(i--);
}

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

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

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

u8 i2c_master_recv_ACK(void)
{
        u8 ACK=0;
        SCL = 1;
        i2c_delay();
       
        ACK |= SDA;
        i2c_delay();
       
        SCL = 0;
        i2c_delay();
        return ACK;
}

u8 i2c_master_send_byte(u8 Byte)
{
        u8 i,ACK;
        for(i=0;i<8;i++)
        {
                SDA = Byte>>(7-i)&0x01;
                i2c_delay();
                SCL = 1;
                i2c_delay();
                SCL = 0;
                i2c_delay();
        }
        ACK = i2c_master_recv_ACK();
        return ACK;                        //ACK=1=失败,ACK=0=成功
}

u8 i2c_master_recv_byte( void )
{
        u8 i,temp;
        for(i=0;i<8;i++)
        {
                temp=temp<<1;
                SCL = 1;
                i2c_delay();
                temp |= SDA;
                SCL = 0;
                i2c_delay();
        }
        return temp;
}

//i2c数据传输,每次传输一个数据包
int i2c_transfer_msg(u8 SlaveAddr_and_RorW , u8 *msg , u8 length)
{
        int ret;
        u8 i;
        i2c_start();
        ret = i2c_master_send_byte(SlaveAddr_and_RorW);
        if(SlaveAddr_and_RorW&0x01)                        //RorW=1=Read
        {
                for(i=0;i<length;i++)
                {
                        msg=i2c_master_recv_byte();
                        i2c_master_send_ACK();
                }
        }
        else        //RorW=0=Write
        {
                for(i=0;i<length;i++)
                {
                        ret += i2c_master_send_byte(msg);
                }
        }
        i2c_stop();
        return ret;                //=0表示没任何错误
}

//master从ft5x06中读数据,数据缓冲区第一个字节为起始读地址
static int ft5x06_i2c_rxdata(u8 *rxdata,u8 length)
{
        int ret;
        u8 SlaveAddr_and_RorW;
        SlaveAddr_and_RorW = (ft5x06_I2C_SLAVE_ADDRESS<<1) + 0;        //Write
        ret = i2c_transfer_msg(SlaveAddr_and_RorW,rxdata,1);
               
        SlaveAddr_and_RorW = (ft5x06_I2C_SLAVE_ADDRESS<<1) + 1;        //Read
        ret += i2c_transfer_msg(SlaveAddr_and_RorW,rxdata,length);
        if(ret)
                printf("msg i2c read error: %d\n",ret);
        return ret;                //=0表示没任何错误
}

david1234 发表于 2014-7-22 15:10:25

I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

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



bias 发表于 2014-7-22 15:38:37

david1234 发表于 2014-7-22 15:10
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

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

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

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

wxty 发表于 2014-7-22 16:52:00

david1234 发表于 2014-7-22 15:10
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

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

弄个超时,重发。

laoshuhunya 发表于 2014-7-22 20:17:24

楼主,你的i2c_master_send_ACK、i2c_master_recv_ACK 、i2c_master_recv_byte 这些函数是错误的。
接收每个位之前,SDA应该先置1,这样才能接收到正确的数据位。

huaidan1628 发表于 2014-7-22 20:48:28

主机先发送应答

david1234 发表于 2014-7-22 21:14:07

受5楼提示,在sendack中, sda=0。recack中,sda =1。你程序中刚好都反了。

bias 发表于 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错误提示那里字符串狂出

bias 发表于 2014-7-22 22:17:56

可是我程序目前读写一个字节的时候都正常的呢...
我要另外找个i2c器件来验证一下i2c

laoshuhunya 发表于 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

ghostxdy 发表于 2014-7-23 01:18:23

david1234 发表于 2014-7-22 15:10
I2C read的最后一个字节,主机不能发送ACK,否者总线可能死锁。

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

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

david1234 发表于 2014-7-23 07:03:11

本帖最后由 david1234 于 2014-7-23 08:03 编辑

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

david1234 发表于 2014-7-23 07:05:50

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

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

david1234 发表于 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;
}
页: [1]
查看完整版本: I2C连续读的时候发送应答型号应该是怎样的?