[AT32F415] 关于F415硬件I2C

[复制链接]
4601|16
 楼主| ccxzjz 发表于 2021-11-9 09:03 | 显示全部楼层 |阅读模式
本帖最后由 ccxzjz 于 2021-11-9 09:37 编辑

AT32F415使用I2C与另一个芯片通信,主要实现读寄存器和写寄存器功能,代码参考的是下面这个例子
1.png

刚开始读取数据通信是正常,但是一旦有一次传输不正常(比如人为断开i2c的线再接回去),后面一直读取失败,一直陷入到这个,  只有复位芯片i2c才能读取成功。请教大家,怎么处理  ,完整代码如下 3.png

1.png
  1. static I2C_StatusType I2C_WaitOnFlagUntilTimeout(I2C_Type *I2Cx, uint32_t Flag, FlagStatus Status, uint32_t EventCheck, uint32_t Timeout)
  2. {
  3.     /* delay 10 us = ms * 100 */
  4.     Timeout *= 100;
  5.     while (I2C_GetFlagStatus(I2Cx, Flag) == Status)
  6.     {
  7.         if (EventCheck & I2C_EVT_CHECK_ACKFAIL)
  8.         {
  9.             if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ACKFAIL) == SET)
  10.             {
  11.                 I2C_GenerateSTOP(I2Cx, ENABLE);
  12.                 I2C_ClearFlag(I2Cx, I2C_FLAG_ACKFAIL);
  13.                 return I2C_ERROR;
  14.             }
  15.         }
  16.         if (EventCheck & I2C_EVT_CHECK_STOP)
  17.         {
  18.             if (I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF) == SET)
  19.             {
  20.                 I2C_ClearSTOPFlag(I2Cx);
  21.                 return I2C_ERROR;
  22.             }
  23.         }
  24.         I2C_Delay(10);
  25.         if ((Timeout--) == 0)
  26.         {
  27.             return I2C_TIMEOUT;
  28.         }
  29.     }
  30.     return I2C_OK;
  31. }

  32. I2C_StatusType hw_i2c_read_reg(I2C_Type *I2Cx, uint8_t slave_addr, uint8_t reg, uint8_t *rd_value, uint32_t Timeout)
  33. {
  34.     /* Wait until BUSY flag is reset */
  35.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_BUSYF, SET, I2C_EVT_CHECK_NONE, I2C_TIMEOUT_BUSY_FLAG) != I2C_OK)
  36.     {
  37.         return I2C_ERROR_STEP_1;
  38.     }

  39.     /* Disable Pos */
  40.     I2C_NACKPositionConfig(I2Cx, I2C_NACKPosition_Current);

  41.     /* Enable Acknowledge */
  42.     I2C_AcknowledgeConfig(I2Cx, ENABLE);

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

  45.     /* Wait until SB flag is set */
  46.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  47.     {
  48.         /* Send STOP Condition */
  49.         I2C_GenerateSTOP(I2Cx, ENABLE);
  50.         return I2C_ERROR_STEP_2;
  51.     }

  52.     /* Send slave address for write */
  53.     I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Transmit);

  54.     /* Wait until ADDR flag is set */
  55.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  56.     {
  57.         /* Send STOP Condition */
  58.         I2C_GenerateSTOP(I2Cx, ENABLE);
  59.         return I2C_ERROR_STEP_3;
  60.     }

  61.     /* Clear ADDR flag */
  62.     I2C_ClearADDRFlag(I2Cx);

  63.     /* Wait until TDE flag is set */
  64.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  65.     {
  66.         /* Send STOP Condition  */
  67.         I2C_GenerateSTOP(I2Cx, ENABLE);
  68.         return I2C_ERROR_STEP_4;
  69.     }

  70.     /* Send Memory Address */
  71.     I2C_SendData(I2Cx, reg);

  72.     /* Wait until TDE flag is set */
  73.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_TDE, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  74.     {
  75.         /* Send STOP Condition */
  76.         I2C_GenerateSTOP(I2Cx, ENABLE);
  77.         return I2C_ERROR_STEP_5;
  78.     }

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

  81.     /* Wait until SB flag is set */
  82.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_STARTF, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  83.     {
  84.         /* Send STOP Condition */
  85.         I2C_GenerateSTOP(I2Cx, ENABLE);
  86.         return I2C_ERROR_STEP_6;
  87.     }

  88.     /* Send slave address for read */
  89.     I2C_Send7bitAddress(I2Cx, slave_addr, I2C_Direction_Receive);

  90.     /* Wait until ADDR flag is set */
  91.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_ADDRF, RESET, I2C_EVT_CHECK_ACKFAIL, Timeout) != I2C_OK)
  92.     {
  93.         /* Send STOP Condition */
  94.         I2C_GenerateSTOP(I2Cx, ENABLE);
  95.         return I2C_ERROR_STEP_7;
  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.     /* Wait until RXNE flag is set */
  104.     if (I2C_WaitOnFlagUntilTimeout(I2Cx, I2C_FLAG_RDNE, RESET, I2C_EVT_CHECK_NONE, Timeout) != I2C_OK)
  105.     {
  106.         /* Send STOP Condition */
  107.         I2C_GenerateSTOP(I2Cx, ENABLE);
  108.         return I2C_ERROR_STEP_8;
  109.     }

  110.     /* Read data from DR */
  111.     (*rd_value) = I2C_ReceiveData(I2Cx);

  112.     return I2C_OK;
  113. }



cehuafan 发表于 2021-11-10 22:06 | 显示全部楼层
不太喜欢硬件iic。        
wengh2016 发表于 2021-11-10 22:06 | 显示全部楼层
推荐模拟iic吧。         
qiufengsd 发表于 2021-11-10 22:07 | 显示全部楼层
F415硬件I2C有坑吗?     
kmzuaz 发表于 2021-11-10 22:07 | 显示全部楼层
F415硬件I2C读写速度怎么样?   
plsbackup 发表于 2021-11-10 22:07 | 显示全部楼层
就是读取超时了吧。         
mnynt121 发表于 2021-11-10 22:07 | 显示全部楼层
硬件I2C不好调试。              
aspoke 发表于 2021-11-10 22:07 | 显示全部楼层
为什么不使用IO模拟呢?         
232321122 发表于 2021-11-10 22:07 | 显示全部楼层
这个是官网的代码吗?      
ghuca 发表于 2021-11-10 22:08 | 显示全部楼层
可能读写速度太快了。         
soodesyt 发表于 2021-11-10 22:08 | 显示全部楼层
芯片没有响应吗?        
yangxiaor520 发表于 2021-11-11 07:44 来自手机 | 显示全部楼层
这算是bug吗?
 楼主| ccxzjz 发表于 2021-11-12 15:20 | 显示全部楼层
改用模拟的了,硬件确实繁琐
muyichuan2012 发表于 2021-11-12 15:34 | 显示全部楼层
本帖最后由 muyichuan2012 于 2021-11-12 15:39 编辑

官方代码都是测试通过的,不会有问题的。
不过,官方的代码一般不会去考虑 “一旦有一次传输不正常(比如人为断开i2c的线再接回去)”这种应用情形,所以需要使用者根据自己的应用去调整,毕竟官方提供的仅仅是demo。



vt2017 发表于 2021-11-14 10:50 | 显示全部楼层
“传输不正常”有很多种情况,硬件I2C是有提供一部分的错误处理的,比如应答失败、欠载/过载、仲裁丢失等,但你提到的人为断开I2C线再接回去不是硬件I2C所能处理的错误。遇到此类的错误很可能会导致I2C内部的状态标志出现异常,你可以做下面几个尝试:
1、设定函数的超时时间,如果长时间无法通讯就退出函数,并返回相应的你自己定义的标志位
2、根据你自己定义的标志位来选择是否要复位硬件I2C
3、调用I2C_DeInit函数,将时钟复位,清除所有的I2C状态
4、重新初始化I2C配置
骑着蜗牛狂奔O 发表于 2021-11-14 17:50 | 显示全部楼层
SCL SDA总线任意一根拉低就会出现此标志,在收到Stop时,硬件会自动清除,出现这种情况一般是你整个通信流程未完成,此时软件复位I2C就行,不用芯片复位
6552918 发表于 2021-11-15 09:41 | 显示全部楼层
需要人为判断异常处理,原厂例程一般不会考虑这些,只有产品及的代码才会处理异常
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

41

帖子

1

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