这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 给I2C查询模式添加NACK响应

共2条 1/1 1 跳转至

给I2C查询模式添加NACK响应

院士
2025-12-28 17:31:34     打赏

抽时间研究了一下从地址输入错误等未接收到从设备地址ACK响应的处理。想来想去,也就是查询一下NACK的flag这一条途径。今天写了代码验证了一下。

int i2c_xfer(uint8_t dev_addr, uint16_t reg_addr, uint8_t reg_len, uint8_t *buf, uint16_t len)
{
  int ret = 0;
  uint16_t i;
  while (I2C_ReadStatusFlag(I2C2, I2C_FLAG_BUSY) == SET)
  {
    ;
  }
  I2C_HandlingTransfer(I2C2, dev_addr, reg_len, I2C_RELOAD_MODE_SOFTEND, I2C_GENERATE_START_WRITE);
  if (reg_len == 1)
  {
    I2C_TxData(I2C2, (uint8_t)(reg_addr & 0x00FF));
    while (I2C_ReadStatusFlag(I2C2, I2C_FLAG_TXBE) == RESET)
    {
      if (I2C_ReadStatusFlag(I2C2, I2C_FLAG_NACK) == SET)
      {
        goto i2c_xfer_end;
      }
    }
  }
  else if (reg_len == 2)
  {
    I2C_TxData(I2C2, (uint8_t)(reg_addr & 0x00FF));
    while (I2C_ReadStatusFlag(I2C2, I2C_FLAG_TXBE) == RESET)
    {
      if (I2C_ReadStatusFlag(I2C2, I2C_FLAG_NACK) == SET)
      {
        goto i2c_xfer_end;
      }
    }
    I2C_TxData(I2C2, (uint8_t)(reg_addr & 0x00FF));
    while (I2C_ReadStatusFlag(I2C2, I2C_FLAG_TXBE) == RESET)
    {
      if (I2C_ReadStatusFlag(I2C2, I2C_FLAG_NACK) == SET)
      {
        goto i2c_xfer_end;
      }
    }
  }
  else
  {
    /* something wrong */
  }
  I2C_HandlingTransfer(I2C2, dev_addr, len, I2C_RELOAD_MODE_AUTOEND, I2C_GENERATE_START_READ);
  for (i = 0; i < len; i++)
  {
    while (I2C_ReadStatusFlag(I2C2, I2C_FLAG_RXBNE) == RESET)
    {
      if (I2C_ReadStatusFlag(I2C2, I2C_FLAG_NACK) == SET)
      {
        goto i2c_xfer_end;
      }
    }
    buf[i] = (uint8_t)I2C_RxData(I2C2);
  }
i2c_xfer_end:
  I2C_EnableGenerateStop(I2C2);
  while (I2C_ReadStatusFlag(I2C2, I2C_FLAG_STOP) == RESET)
  {
    ;
  }
  return (ret);
}

在Keil中运行一下,并将之前的从设备地址由0xA0修改为0xA2,并添加断点。果然,E030停留在了断点处。

APM32E030的I2C外设NACK测试.jpg


NACK的标志位也确实适用从地址,可以看到APM32E030并没有像其它MCU有一个单独的从设备地址响应标志。把从地址当作一个数据来处理,其实也没有啥不同!



专家
2025-12-29 17:14:46     打赏
2楼

I2C扫描处理也是基于ACK/NACK判定的。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]