打印
[STM32F4]

I2C读数据地址无应答,而写数据地址有应答,正常命令有应答?

[复制链接]
3346|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
xueyanqin|  楼主 | 2015-7-16 17:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请问有没有遇到过这种情形:
写操作地址有应答,而读数据时按照时序输入读地址(写地址加1),却没有应答,这是为什么?
求教,谢谢。
沙发
airwill| | 2015-7-16 18:11 | 只看该作者
从设备器件应该是就绪的.
我想写相对于读, 设备端存在需要数据准备的过程, 所以可能会需要一定的延迟时间

使用特权

评论回复
板凳
xueyanqin|  楼主 | 2015-7-16 18:15 | 只看该作者
谢谢您
我是从示波器上看,发送完读的地址后,SDA就一直是高电平
而写的地址和命令后,SDA确实变成低电平,有应答

使用特权

评论回复
地板
xueyanqin|  楼主 | 2015-7-16 18:31 | 只看该作者
我用的是STM32F405,I2C从设备是气压传感器MS5611,它的地址是0XEE
//启动
void I2C_Start(void)
{
  
  delay_us(10);
  I2C1_SDA_SET();
  I2C1_SCL_SET();
  
  delay_us(10);
  I2C1_SDA_RESET();
  delay_us(10);
  I2C1_SCL_RESET();
  
}
//***************停止**********************
void I2C_Stop(void)
{
  //I2C1_SDA_OUT();
  delay_us(10);
  I2C1_SDA_RESET();
  I2C1_SCL_RESET();
  delay_us(10);
  I2C1_SCL_SET();
  delay_us(10);
  I2C1_SDA_SET();
}
//********************获取ACK************************
uint8_t I2C_Wait_ACK(void)
{
  I2C1_SDA_IN();
  delay_us(10);
  uint32_t sur_error;
  //I2C1_SDA_SET();
  delay_us(10);
  sur_error = 0;
  while(I2C1_READ_ACK() == 1)
  {
    sur_error++;
    if(sur_error>500000)
    {
      I2C_Stop();
      return 1;
    }
    delay_us(10);
  }
  return 0;
}
//**********************发送ACK***************************     
void I2C_Send_ACK(uint8_t ack)
{
  I2C1_SDA_OUT();
  delay_us(10);
  I2C1_SCL_RESET();
  I2C1_SDA_SET();
  delay_us(10);
  if(ack == 0)
    I2C1_SDA_RESET();
  else
    I2C1_SDA_SET();
  I2C1_SCL_SET();
  delay_us(10);
  I2C1_SCL_RESET();
}



//*******************发送字节*******************
void I2C_Send_Byte(uint8_t Tdata)
{
  I2C1_SCL_RESET();
  delay_us(10);
  for(uint8_t i=0;i<8;i++)
  {
   
    delay_us(10);
    if((Tdata&0x80) == 0x80)
    {
      I2C1_SDA_SET();
    }
    else
    {
      I2C1_SDA_RESET();
    }
   
    delay_us(10);
    I2C1_SCL_SET();
    delay_us(10);
    I2C1_SCL_RESET();
    Tdata <<= 1;
  }
}


我的主程序中还在用示波器调试,为了看每个波形,所以延时较长
//**********************主程序运行I2C******************
void I2C_Init(void)
{
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  I2C1_SDA_SET();
  I2C1_SCL_SET();
  
//MS5611复位(这一部分很好,均有应答)
  I2C_Start();
  I2C_Send_Byte(MS5611_ADDRESS);
  delay_us(10);
  while(I2C1_READ_ACK()==1);
  
  delay_us(10);
  I2C_Send_Byte(MS5611_RESET);
  delay_us(10);
  while(I2C1_READ_ACK()==1);  
  I2C_Stop();
  delay_us(10);
//*****************************************  
  
//***********开始读取PROM值(还没做具体读数据,因为读地址没有应答)***************  
  I2C_Start();
  I2C_Send_Byte(0xee);
  delay_us(10);
  while(I2C1_READ_ACK()==1);  
  HAL_Delay(1000);
  I2C_Send_Byte(MS5611_PROM_READ);
  HAL_Delay(1000);
  I2C_Stop();
  delay_us(1000);

  I2C_Start();
  I2C_Send_Byte(0xef);
  delay_us(10);
  while(I2C1_READ_ACK()==1);  //*最后死在该处?????????????
  HAL_Delay(1000);
  I2C_Stop();
  delay_us(10);
}

使用特权

评论回复
5
xuxuemin123123| | 2019-10-24 09:28 | 只看该作者
I2C的读数据帧比写数据帧内容多,写成功不能保证读就能成功。写操作地址有应答,说明I2C从设备已经准备就绪了(可以干活了)。而读数据时按照时序输入读地址(写地址加1),没有应答,可能是I2C的写时序帧不符合从设备的需求,所以从设备就不理你了。I2C的读/写帧,不同的I2C外设(从设备),可能存在区别,需要具体看相应的I2C手册(每个I2C外设都有详细的I2C通讯时序图),把正确的时序帧配置好,才能有正确的读应答。不要认为我的I2C驱动以前在其他外设用成功过,今天换了新的I2C外设,老的驱动套上去就一定能成功。

使用特权

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

本版积分规则

17

主题

84

帖子

0

粉丝