[STM32] STM32软件模拟I2C程序中有问题?

[复制链接]
 楼主| huster_tjs 发表于 2015-10-25 14:38 | 显示全部楼层 |阅读模式
我在用软件模拟I2C过程中,写入硬件写地址(address)和数据(data)都是正确的,能够得到waitask响应。在waitask响应后master将SCL电平拉低,SDA电平自动释放(高电平)。这些都正确。

但是当我写入硬件读地址(address+1)的时候,能得到waitask响应,但是响应后我master拉低SCL电平后,SDA电平还是被拉低,即使通过master软件拉高SDA的IO口都不能将之电平拉高。因此可知,写入硬件读地址(address+1)后,能得到正确的的响应,但是slave就是不释放SDA数据端口。这是怎么回事呢,哪里出了问题?

下面是一些代码:
//单字节读取*****************************************
unsigned char I2C_ReadByte(unsigned char REG_Address)
{   
        unsigned char REG_data;            
        if(!I2C_Start())return FALSE;
        I2C_SendByte(SlaveAddress);
    if(!I2C_WaitAck()){I2C_Stop(); return FALSE;}
    I2C_SendByte((u8) REG_Address);   //设置低起始地址      
    I2C_WaitAck();
    I2C_Start();
    I2C_SendByte(SlaveAddress+1);              //就是这里发送读地址
    I2C_WaitAck();                                  //这个waitack里面出问题,最后的scl拉低,slave不释放SDA电平
   REG_data= I2C_ReceiveByte();
    I2C_NoAck();
    I2C_Stop();
    //return TRUE;
        return REG_data;

}               

//这里就是waitack()
bool I2C_WaitAck(void)          //返回为:=1有ACK,=0无ACK
{
        SCL_L;
        I2C_delay();
        SDA_H;                       
        I2C_delay();
        SCL_H;
        I2C_delay();
        if(SDA_read)
        {
      SCL_L;
          I2C_delay();
      return FALSE;
        }
        SCL_L;                            //这里拉低SCL电平,但是slave不释放sda(一直是低电平)
        I2C_delay();
        return TRUE;
}

unsigned char I2C_ReceiveByte(void)  //数据从高位到低位//
{
    u8 i=8;
    u8 ReceiveByte=0;
    SDA_H;                        //slave一直拉低sda,在这master写入SDA高电平都不能将SDA电平拉高
    I2C_delay();                               
    while(i--)
    {
      ReceiveByte<<=1;      
      SCL_L;
      I2C_delay();
          SCL_H;
      I2C_delay();       
      if(SDA_read)
      {
        ReceiveByte|=0x01;
      }
    }
    SCL_L;
    return ReceiveByte;
}


求帮助,这是哪问题呢
 楼主| huster_tjs 发表于 2015-10-25 15:56 | 显示全部楼层
这么有趣的问题为什么没人回答呢:'(
NE5532 发表于 2015-10-25 16:45 | 显示全部楼层
你的意思是你写了addr+R/W以后,在紧随其后的应答位上,从机拉低了SDA线,发出了ACK信号是么?如果是这样描述的,那么从器件就是应该发ACK,因为这帧数据是Master给Slave的,该Slave应答,详见I2C协议,如果不是这样描述的,请楼主继续描述问题。
 楼主| huster_tjs 发表于 2015-10-25 16:56 | 显示全部楼层
NE5532 发表于 2015-10-25 16:45
你的意思是你写了addr+R/W以后,在紧随其后的应答位上,从机拉低了SDA线,发出了ACK信号是么?如果是这样描 ...

是响应了ack信号。是在scl从低电平到高电平的时候,从机将sda线拉低了,这里没问题。但是在从机拉低了sda电平后,我将scl再拉低,从机不释放sda线(还是低电平)。而且此时通过主机将设置sda高电平,sda电平还是低电平。
NE5532 发表于 2015-10-25 17:00 | 显示全部楼层
这个时候应该是从机送出主机所要求读取数据的第一个bit,你怎么保证从机此时不是刚好要输出0呢??他怎么就必须该“释放”啊?
 楼主| huster_tjs 发表于 2015-10-25 17:12 | 显示全部楼层
NE5532 发表于 2015-10-25 16:45
你的意思是你写了addr+R/W以后,在紧随其后的应答位上,从机拉低了SDA线,发出了ACK信号是么?如果是这样描 ...

也就是说,在从写入addr+R后,从机将sda线拉低响应了,但是将scl设置为低电平时,从机不释放sda线(还是低电平)。。。。

而前面写入addr+w后,没出现这种问题。在从机响应拉低了sda后,我将scl设置低电平时,sda将被释放(处于高电平)。。。。

也请您看看我的I2C_ReadByte(), I2C_WaitAck(),I2C_ReceiveByte(),这三个程序,看有没有时序错误的问题。就我目前对照别人的i2c来看,基本没有什么不同,没找出问题点。在此先谢过
 楼主| huster_tjs 发表于 2015-10-25 17:23 | 显示全部楼层
本帖最后由 huster_tjs 于 2015-10-25 17:27 编辑
NE5532 发表于 2015-10-25 17:00
这个时候应该是从机送出主机所要求读取数据的第一个bit,你怎么保证从机此时不是刚好要输出0呢??他怎么就 ...

我读取的是mpu6050的数据,不应该8个位都是0,所以我担心这里出现了错误。

那我们来讨论一下时序问题(请教),照这么来说的话,当发送完addr+r后,slave响应将sda电平拉低。此时master将scl电平拉低时,slave就准备好输出数据的第一位了(将sda电平拉低或为高电平)

但是我觉得应该是 ,当发送完addr+r后,slave响应将sda电平拉低。然后将scl拉低,slave释放sda,然后当scl再次拉高时,slave检测到master电平的变化。slave准备第一位数据,然后master可以读取sda,也就是说,slave只有在检测到scl电平由低到高变化时才准备一个数据。
不知道您怎么看?
NE5532 发表于 2015-10-25 20:21 | 显示全部楼层
你对I2C协议理解错了,sda只能在scl低电平期间送出数据,在scl高电平期间被采样,两个特例是启动位和停止位。你怀疑读得有问题,就多读几个数据,用不会都是0嘛。
欧阳2013 发表于 2015-10-26 10:10 | 显示全部楼层
iic需要共地:)
阿南 发表于 2015-10-26 10:31 | 显示全部楼层
NE5532同志好样的

评论

过奖,过奖  发表于 2015-10-26 19:11
 楼主| huster_tjs 发表于 2015-10-26 11:15 | 显示全部楼层
NE5532 发表于 2015-10-25 20:21
你对I2C协议理解错了,sda只能在scl低电平期间送出数据,在scl高电平期间被采样,两个特例是启动位和停止位 ...

好的,谢谢你,我再换块芯片试试。
 楼主| huster_tjs 发表于 2015-10-26 11:31 | 显示全部楼层

好的,我认真再检查一下
wxl319 发表于 2016-11-2 19:22 | 显示全部楼层
huster_tjs 发表于 2015-10-26 11:15
好的,谢谢你,我再换块芯片试试。

换了芯片也是这样的,我也是同样的问题,求问,你是怎么解决的啊?求指教啊!这个问题困了好久了!
wxl319 发表于 2016-11-2 19:24 | 显示全部楼层
不知楼主有没有发现,换了IO口就没问题了,但是问题在哪呢?我还没找到!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

31

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部