完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
这两天测试过程中发现读取eeprom偶尔会报错,定位过程发现IIC总线上经常会有时钟总线为低的情况,开始不解,经查阅资料发现这是正常现象,从MCU手册上得知,当移位寄存器里8位数据接收完成后,如果这时接收寄存器里有未取走的数据,那么IIC外设会在本次发送ACK前拉低总线,防止从设备继续回数据导致数据丢失。因此在读取EEPROM的过程中如果被中断或其它线程打断,就会出现这种情况,如果被打断的持续时间超过了一次II2读取的超时时间就会报错。根据这个,修改了每次读取EEPROM的超时时间,再测试发现故障率降低了,但是又偶发过一次,继续定位,突发奇想,如果在一次读取EEPROM的过程中我在读取接收寄存器前加个断点,总线会是什么表现。奇怪的事情发生了,如下图,总线上竟然传回了3个字节的数据,紧跟着写地址读操作后是2个字节的数据,之后时钟总线一直为低,但是过了150ms后总线上竟然又传回一个字节的数据。理论上分析当第一个字节传输完成时接收寄存器为空,数据从移位寄存器送到接收寄存器,紧接着第二字节数据到达,因为此时第一个字节还占着接收寄存器,所以第二个字节存在移位寄存器里,在ACK前时钟总线被IIC外设拉低,现象和手册吻合,但是150MS后总线上又传输了一个字节,这期间MCU一直是停在断点( 下图if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK)处),于是第一个字节被成功覆盖了,最终第一个字节丢失,其它数据往前窜一个字节,最后一个字节直接超时,因为早在上一次总线就传输完了。设想,如果一次读取EEPROM的过程被打断超过150ms是不是就有可能出现这种错误。
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout) { uint32_t tickstart = 0U; /* Check the parameters */ assert_param(IS_I2C_MEMADD_SIZE(MemAddSize)); if(hi2c->State == HAL_I2C_STATE_READY) { if((pData == NULL) || (Size == 0U)) { return HAL_ERROR; } /* Process Locked */ __HAL_LOCK(hi2c); /* Init tickstart for timeout management*/ tickstart = HAL_GetTick(); if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY, tickstart) != HAL_OK) { return HAL_TIMEOUT; } hi2c->State = HAL_I2C_STATE_BUSY_RX; hi2c->Mode = HAL_I2C_MODE_MEM; hi2c->ErrorCode = HAL_I2C_ERROR_NONE; /* Prepare transfer parameters */ hi2c->pBuffPtr = pData; hi2c->XferCount = Size; hi2c->XferISR = NULL; /* Send Slave Address and Memory Address */ if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_ERROR; } else { /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_TIMEOUT; } } /* Send Slave Address */ /* Set NBYTES to write and reload if hi2c->XferCount > MAX_NBYTE_SIZE and generate RESTART */ if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_GENERATE_START_READ); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); } do { /* Wait until RXNE flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_RXNE, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } /* Read data from RXDR */ (*hi2c->pBuffPtr++) = hi2c->Instance->RXDR; hi2c->XferSize--; hi2c->XferCount--; if((hi2c->XferSize == 0U) (hi2c->XferCount != 0U)) { /* Wait until TCR flag is set */ if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_TCR, RESET, Timeout, tickstart) != HAL_OK) { return HAL_TIMEOUT; } if(hi2c->XferCount > MAX_NBYTE_SIZE) { hi2c->XferSize = MAX_NBYTE_SIZE; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_RELOAD_MODE, I2C_NO_STARTSTOP); } else { hi2c->XferSize = hi2c->XferCount; I2C_TransferConfig(hi2c, DevAddress, hi2c->XferSize, I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); } } }while(hi2c->XferCount > 0U); /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */ /* Wait until STOPF flag is reset */ if(I2C_WaitOnSTOPFlagUntilTimeout(hi2c, Timeout, tickstart) != HAL_OK) { if(hi2c->ErrorCode == HAL_I2C_ERROR_AF) { return HAL_ERROR; } else { return HAL_TIMEOUT; } } /* Clear STOP Flag */ __HAL_I2C_CLEAR_FLAG(hi2c, I2C_FLAG_STOPF); /* Clear Configuration Register 2 */ I2C_RESET_CR2(hi2c); hi2c->State = HAL_I2C_STATE_READY; hi2c->Mode = HAL_I2C_MODE_NONE; /* Process Unlocked */ __HAL_UNLOCK(hi2c); return HAL_OK; } else { return HAL_BUSY; } } |
|
相关推荐
1个回答
|
|
|
要解决STM32F767IGTB使用IIC过程中遇到的读超时和总线忙的问题,你可以尝试以下几个步骤:
1. 检查硬件连接:确保IIC线路的连接正常,检查相关引脚的接线、电源供应和电平转换。 2. 检查时钟频率:确保IIC总线的时钟频率设置正确,不要设置得过高。 3. 修改IIC读取超时时间:根据你的描述,你已经尝试过这个步骤,可以继续调整超时时间,看是否能进一步降低故障率。 4. 增加错误处理机制:当发生读超时或总线忙的情况时,实现错误处理机制,例如重试读取、重新初始化IIC等。 5. 禁用中断和其他线程:为了避免中断或其他线程的干扰,可以考虑在读取EEPROM期间禁用中断或临时挂起其他线程。 6. 增加延时:在进行IIC操作时,添加适当的延时以确保完整的数据传输,例如在IIC读取操作之前添加适当的延时。 7. 调试和排除故障:通过使用调试工具,如示波器或逻辑分析仪,监测IIC总线的信号波形,以进一步分析和排除故障。 |
|
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
4130 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
3221 浏览 1 评论
2747 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
2175 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
14939 浏览 2 评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
3084浏览 4评论
stm32f4下spi+dma读取数据不对是什么原因导致的?
1892浏览 3评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
2064浏览 3评论
1976浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
2165浏览 3评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-1 20:36 , Processed in 0.690656 second(s), Total 75, Slave 57 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1912