打印
[AT32F421]

AT32F421硬件I2C官方库驱动异常

[复制链接]
901|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 tanganrong 于 2021-3-21 18:50 编辑

因为ST身价太贵,最近尝试国产替代,使用AT32F421测试发现硬件I2C在从机有响应的情况下,并没有置位ADDRF标志(见代码31行),造成I2C一直超时停止,请问哪 位大神能指导一下。
I2C_StatusType I2C_Mem_Read(I2C_Type* I2Cx, uint8_t SlaAddr, uint32_t ReadAddr, uint8_t ReadAddrSize, uint8_t *pBuffer, uint16_t NumByteToRead, uint32_t Timeout)
{
  /* Wait until BUSY flag is reset */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BUSYF, SET, I2C_EVT_CHECK_NONE, I2C_TIMEOUT_BUSY_FLAG) != I2C_OK)
  {
    return I2C_ERROR_STEP_1;
  }

  /* Disable Pos */
  I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);

  /* Enable Acknowledge */
  I2C_AcknowledgeConfig(I2Cx, ENABLE);

  /* Send START condition */
  I2C_GenerateSTART(I2Cx, ENABLE);

  /* Wait until SB flag is set */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  {
    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return I2C_ERROR_STEP_2;
  }

  /* Send slave address for write */
  I2C_Send7bitAddress(I2Cx, SlaAddr, I2C_Direction_Transmit);

/* Wait until ADDR flag is set */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  {
    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return I2C_ERROR_STEP_3;
  }

  /* Clear ADDR flag */
  I2C_ClearADDRFlag(I2Cx);

  /* Wait until TDE flag is set */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  {
    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return I2C_ERROR_STEP_4;
  }

  if(ReadAddrSize == I2C_MEMADD_SIZE_32BIT)
  {
          I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 24));

          if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
          {
            I2C_GenerateSTOP(I2Cx, ENABLE);
            return I2C_ERROR_STEP_5;
          }

          ReadAddrSize -= 1;
  }

  if(ReadAddrSize == I2C_MEMADD_SIZE_24BIT)
  {
          I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 16));

          if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
          {
            I2C_GenerateSTOP(I2Cx, ENABLE);
            return I2C_ERROR_STEP_5;
          }

          ReadAddrSize -= 1;
  }

  if(ReadAddrSize == I2C_MEMADD_SIZE_16BIT)
  {
          I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 8));

          if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
          {
            I2C_GenerateSTOP(I2Cx, ENABLE);
            return I2C_ERROR_STEP_5;
          }
  }

  /* Send Memory Address */
  I2C_SendData(I2Cx, ReadAddr);

  /* Wait until TDE flag is set */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  {
    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return I2C_ERROR_STEP_5;
  }

  /* Send START condition */
  I2C_GenerateSTART(I2Cx, ENABLE);

  /* Wait until SB flag is set */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  {
    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return I2C_ERROR_STEP_6;
  }

  /* Send slave address for read */
  I2C_Send7bitAddress(I2Cx, SlaAddr, I2C_Direction_Receive);

  /* Wait until ADDR flag is set */
  if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  {
    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);

    return I2C_ERROR_STEP_7;
  }

  if(NumByteToRead == 1)
  {
    /* Disable Acknowledge */
    I2C_AcknowledgeConfig(I2Cx, DISABLE);

    /* Clear ADDR flag */
    I2C_ClearADDRFlag(I2Cx);

    /* Send STOP Condition */
    I2C_GenerateSTOP(I2Cx, ENABLE);
  }
  else if(NumByteToRead == 2)
  {
    /* Enable Pos */
    I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);

    /* Clear ADDR flag */
    I2C_ClearADDRFlag(I2Cx);

    /* Disable Acknowledge */
    I2C_AcknowledgeConfig(I2Cx, DISABLE);
  }
  else
  {
    /* Enable Acknowledge */
    I2C_AcknowledgeConfig(I2Cx, ENABLE);

    /* Clear ADDR flag */
    I2C_ClearADDRFlag(I2Cx);
  }

  while(NumByteToRead > 0)
  {
    if(NumByteToRead <= 3)
    {
      /* One byte */
      if(NumByteToRead == 1)
      {
        /* Wait until RXNE flag is set */
        if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
        {
          /* Send STOP Condition */
          I2C_GenerateSTOP(I2Cx, ENABLE);

          return I2C_ERROR_STEP_8;
        }

        /* Read data from DR */
        (*pBuffer++) = I2C_ReceiveData(I2Cx);
        NumByteToRead--;
      }
      /* Two bytes */
      else if(NumByteToRead == 2)
      {
        /* Wait until BTF flag is set */
        if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
        {
          /* Send STOP Condition */
          I2C_GenerateSTOP(I2Cx, ENABLE);

          return I2C_ERROR_STEP_9;
        }

        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);

        /* Read data from DR */
        (*pBuffer++) = I2C_ReceiveData(I2Cx);
        NumByteToRead--;

        /* Read data from DR */
        (*pBuffer++) = I2C_ReceiveData(I2Cx);
        NumByteToRead--;
      }
      /* 3 Last bytes */
      else
      {
        /* Wait until BTF flag is set */
        if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
        {
          /* Send STOP Condition */
          I2C_GenerateSTOP(I2Cx, ENABLE);

          return I2C_ERROR_STEP_10;
        }

        /* Disable Acknowledge */
        I2C_AcknowledgeConfig(I2Cx, DISABLE);

        /* Read data from DR */
        (*pBuffer++) = I2C_ReceiveData(I2Cx);
        NumByteToRead--;

        /* Wait until BTF flag is set */
        if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
        {
          /* Send STOP Condition */
          I2C_GenerateSTOP(I2Cx, ENABLE);

          return I2C_ERROR_STEP_11;
        }

        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);

        /* Read data from DR */
        (*pBuffer++) = I2C_ReceiveData(I2Cx);
        NumByteToRead--;

        /* Read data from DR */
        (*pBuffer++) = I2C_ReceiveData(I2Cx);
        NumByteToRead--;
      }
    }
    else
    {
      /* Wait until RXNE flag is set */
      if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
      {
        /* Send STOP Condition */
        I2C_GenerateSTOP(I2Cx, ENABLE);

        return I2C_ERROR_STEP_12;
      }

      /* Read data from DR */
      (*pBuffer++) = I2C_ReceiveData(I2Cx);
      NumByteToRead--;
    }
  }

  return I2C_OK;
}



eeror_1.png (111.77 KB )

eeror_1.png

eeror.png (104.17 KB )

eeror.png

使用特权

评论回复
沙发
ArterySW| | 2021-3-23 10:22 | 只看该作者
能否请你调试一下程序,把断点打在116行,运行到此处之后再打开寄存器窗口,把此时的寄存器窗口截图出来看一下,注意要先停到116行后再打开寄存器窗口,不然ADDR标志会被清除。

使用特权

评论回复
板凳
骑着蜗牛狂奔O| | 2021-3-23 13:14 | 只看该作者
不知楼主解决了没,建议可以先DEBUG找出出问题的地方,然后查看状态寄存器的状态,看看是不是有啥错误事件产生,一段程序也不太好分析,我也用了一段时间421的I2C没出现楼主说的问题,

使用特权

评论回复
地板
tanganrong|  楼主 | 2021-3-23 23:49 | 只看该作者
本帖最后由 tanganrong 于 2021-3-24 00:14 编辑
ArterySW 发表于 2021-3-23 10:22
能否请你调试一下程序,把断点打在116行,运行到此处之后再打开寄存器窗口,把此时的寄存器窗口截图出来看 ...

我在debug模式下一直没有测试到这个现象,后面反复测试发现这个问题是在产品重新上电的时候随机性出现,后面只能通过log来输出I2C_GetLastEvent()返回值,看到是BUSYF被置位了,但通过I2C_SoftwareResetCmd()复位I2C也不正常。

QQ截图20210324001321.png (27.46 KB )

QQ截图20210324001321.png

使用特权

评论回复
5
tanganrong|  楼主 | 2021-3-23 23:50 | 只看该作者
骑着蜗牛狂奔O 发表于 2021-3-23 13:14
不知楼主解决了没,建议可以先DEBUG找出出问题的地方,然后查看状态寄存器的状态,看看是不是有啥错误事件 ...

谢谢提供的建议,我这个情况在DEBUG情况下没有出现,需要产品重新上电才有机会出现。

使用特权

评论回复
6
tanganrong|  楼主 | 2021-3-24 00:26 | 只看该作者
ArterySW 发表于 2021-3-23 10:22
能否请你调试一下程序,把断点打在116行,运行到此处之后再打开寄存器窗口,把此时的寄存器窗口截图出来看 ...

经过反复测试,发现在产品重新上电开机的情况下偶尔出现异常,在debug模式下未发现异常,后来通过log输出I2C_GetLastEvent()返回值,看到开机BUSYF置位了,使用I2C_SoftwareResetCmd()复位I2C,但也不能恢复正常。


QQ截图20210324001321.png (27.46 KB )

QQ截图20210324001321.png

使用特权

评论回复
评论
骑着蜗牛狂奔O 2021-3-24 09:22 回复TA
BUSYF位置起来,并不能产生你截的那个波形,并不是这个原因,从你的波形看,不能确定是单片机这边的问题,从机接受到地址之后拉住SCL线也会存在此波形,那要看你从机是个什么设备了 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

68

帖子

3

粉丝