[AT32F421] AT32F421硬件I2C官方库驱动异常

[复制链接]
 楼主| tanganrong 发表于 2021-3-21 18:50 | 显示全部楼层 |阅读模式
本帖最后由 tanganrong 于 2021-3-21 18:50 编辑

因为ST身价太贵,最近尝试国产替代,使用AT32F421测试发现硬件I2C在从机有响应的情况下,并没有置位ADDRF标志(见代码31行),造成I2C一直超时停止,请问哪 位大神能指导一下。
  1. 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)
  2. {
  3.   /* Wait until BUSY flag is reset */
  4.   if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BUSYF, SET, I2C_EVT_CHECK_NONE, I2C_TIMEOUT_BUSY_FLAG) != I2C_OK)
  5.   {
  6.     return I2C_ERROR_STEP_1;
  7.   }

  8.   /* Disable Pos */
  9.   I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);

  10.   /* Enable Acknowledge */
  11.   I2C_AcknowledgeConfig(I2Cx, ENABLE);

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

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

  19.     return I2C_ERROR_STEP_2;
  20.   }

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

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

  28.     return I2C_ERROR_STEP_3;
  29.   }

  30.   /* Clear ADDR flag */
  31.   I2C_ClearADDRFlag(I2Cx);

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

  37.     return I2C_ERROR_STEP_4;
  38.   }

  39.   if(ReadAddrSize == I2C_MEMADD_SIZE_32BIT)
  40.   {
  41.           I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 24));

  42.           if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  43.           {
  44.             I2C_GenerateSTOP(I2Cx, ENABLE);
  45.             return I2C_ERROR_STEP_5;
  46.           }

  47.           ReadAddrSize -= 1;
  48.   }

  49.   if(ReadAddrSize == I2C_MEMADD_SIZE_24BIT)
  50.   {
  51.           I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 16));

  52.           if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  53.           {
  54.             I2C_GenerateSTOP(I2Cx, ENABLE);
  55.             return I2C_ERROR_STEP_5;
  56.           }

  57.           ReadAddrSize -= 1;
  58.   }

  59.   if(ReadAddrSize == I2C_MEMADD_SIZE_16BIT)
  60.   {
  61.           I2C_SendData(I2Cx, (uint8_t)(ReadAddr >> 8));

  62.           if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  63.           {
  64.             I2C_GenerateSTOP(I2Cx, ENABLE);
  65.             return I2C_ERROR_STEP_5;
  66.           }
  67.   }

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

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

  75.     return I2C_ERROR_STEP_5;
  76.   }

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

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

  84.     return I2C_ERROR_STEP_6;
  85.   }

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

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

  93.     return I2C_ERROR_STEP_7;
  94.   }

  95.   if(NumByteToRead == 1)
  96.   {
  97.     /* Disable Acknowledge */
  98.     I2C_AcknowledgeConfig(I2Cx, DISABLE);

  99.     /* Clear ADDR flag */
  100.     I2C_ClearADDRFlag(I2Cx);

  101.     /* Send STOP Condition */
  102.     I2C_GenerateSTOP(I2Cx, ENABLE);
  103.   }
  104.   else if(NumByteToRead == 2)
  105.   {
  106.     /* Enable Pos */
  107.     I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Next);

  108.     /* Clear ADDR flag */
  109.     I2C_ClearADDRFlag(I2Cx);

  110.     /* Disable Acknowledge */
  111.     I2C_AcknowledgeConfig(I2Cx, DISABLE);
  112.   }
  113.   else
  114.   {
  115.     /* Enable Acknowledge */
  116.     I2C_AcknowledgeConfig(I2Cx, ENABLE);

  117.     /* Clear ADDR flag */
  118.     I2C_ClearADDRFlag(I2Cx);
  119.   }

  120.   while(NumByteToRead > 0)
  121.   {
  122.     if(NumByteToRead <= 3)
  123.     {
  124.       /* One byte */
  125.       if(NumByteToRead == 1)
  126.       {
  127.         /* Wait until RXNE flag is set */
  128.         if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  129.         {
  130.           /* Send STOP Condition */
  131.           I2C_GenerateSTOP(I2Cx, ENABLE);

  132.           return I2C_ERROR_STEP_8;
  133.         }

  134.         /* Read data from DR */
  135.         (*pBuffer++) = I2C_ReceiveData(I2Cx);
  136.         NumByteToRead--;
  137.       }
  138.       /* Two bytes */
  139.       else if(NumByteToRead == 2)
  140.       {
  141.         /* Wait until BTF flag is set */
  142.         if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  143.         {
  144.           /* Send STOP Condition */
  145.           I2C_GenerateSTOP(I2Cx, ENABLE);

  146.           return I2C_ERROR_STEP_9;
  147.         }

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

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

  153.         /* Read data from DR */
  154.         (*pBuffer++) = I2C_ReceiveData(I2Cx);
  155.         NumByteToRead--;
  156.       }
  157.       /* 3 Last bytes */
  158.       else
  159.       {
  160.         /* Wait until BTF flag is set */
  161.         if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BTFF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  162.         {
  163.           /* Send STOP Condition */
  164.           I2C_GenerateSTOP(I2Cx, ENABLE);

  165.           return I2C_ERROR_STEP_10;
  166.         }

  167.         /* Disable Acknowledge */
  168.         I2C_AcknowledgeConfig(I2Cx, DISABLE);

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

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

  177.           return I2C_ERROR_STEP_11;
  178.         }

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

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

  184.         /* Read data from DR */
  185.         (*pBuffer++) = I2C_ReceiveData(I2Cx);
  186.         NumByteToRead--;
  187.       }
  188.     }
  189.     else
  190.     {
  191.       /* Wait until RXNE flag is set */
  192.       if(I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  193.       {
  194.         /* Send STOP Condition */
  195.         I2C_GenerateSTOP(I2Cx, ENABLE);

  196.         return I2C_ERROR_STEP_12;
  197.       }

  198.       /* Read data from DR */
  199.       (*pBuffer++) = I2C_ReceiveData(I2Cx);
  200.       NumByteToRead--;
  201.     }
  202.   }

  203.   return I2C_OK;
  204. }



eeror.png
eeror_1.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
 楼主| tanganrong 发表于 2021-3-23 23:50 | 显示全部楼层
骑着蜗牛狂奔O 发表于 2021-3-23 13:14
不知楼主解决了没,建议可以先DEBUG找出出问题的地方,然后查看状态寄存器的状态,看看是不是有啥错误事件 ...

谢谢提供的建议,我这个情况在DEBUG情况下没有出现,需要产品重新上电才有机会出现。
 楼主| tanganrong 发表于 2021-3-24 00:26 | 显示全部楼层
ArterySW 发表于 2021-3-23 10:22
能否请你调试一下程序,把断点打在116行,运行到此处之后再打开寄存器窗口,把此时的寄存器窗口截图出来看 ...

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


QQ截图20210324001321.png

评论

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

本版积分规则

7

主题

68

帖子

3

粉丝
快速回复 返回顶部 返回列表