[英]STM32 - I2C Write Failure
我正在使用带有 512KB EEPROM 的 STM32,我使用 STM32CubeMX 初始化了项目
PB7 作为 I2C_SDA PB6 作为 I2C_SCL
生成的函数
I2C_HandleTypeDef hi2c1;
/* I2C1 init function */
void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, I2C_SCL_Pin|I2C_SDA_Pin);
/* I2C1 interrupt Deinit */
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
}
在主要我调用MX_I2C1_Init()
然后HAL_I2C_MspInit(&hi2c1)
,但是当我调用
while(HAL_I2C_Mem_Write(hi2c,(uint16_t)DevAddress,(uint16_t)MemAddress,I2C_MEMADD_SIZE_8BIT,pData,(uint16_t)16-MemAddress,1000)!= HAL_OK && 1);
这个while循环永远不会返回HAL_OK,所以我无法处理读取写入的数据进行验证。 我的 EEPROM 是
CAT24C512WI-GT3OSCT-ND和A0->A2,WP接地
尝试这个。 首先调用设备就绪检查并确保设备已就绪。
while(HAL_I2C_IsDeviceReady(&hi2c1, I2C_EEPROM_ADDRESS, 64, HAL_MAX_DELAY)!= HAL_OK);
进而
while(HAL_I2C_Mem_Write(&hi2c1, I2C_EEPROM_ADDRESS, eeStart, I2C_MEMADD_SIZE_8BIT, pRamStart, num, HAL_MAX_DELAY)!= HAL_OK);
“HAL_I2C_IsDeviceReady”中的 64 - 尝试次数。 有时一次或多次是不够的。 查看。 需要 &hi2c1,而不是 hi2c1
好的! 第一次会是“true”,但是在写入 eeprom 之后,您需要确保录制完成并且 eeprom 已准备好进行下一步。 在最后一行的 hi2c1 之前,您没有去过 & 。 而且,也许对于 EEPROM 512kb,您需要指定“I2C_MEMADD_SIZE_16BIT”而不是“I2C_MEMADD_SIZE_8BIT”?
您如何确定按照处理器的标准需要大量时间的录制已完成? 为此,有此过程 HAL_I2C_IsDevitseReady。
在调用HAL_I2C_MspInit(&hi2c1)
您需要立即检查 i2c whit 的状态
while(HAL_I2C_Mem_Write(
&hi2c1,
I2C_EEPROM_ADDRESS,
eeStart,
I2C_MEMADD_SIZE_8BIT,
pRamStart,
num,
HAL_MAX_DELAY) == HAL_BUSY);
如果程序卡在 while 循环中总是返回HAL_BUSY
很可能您使用的是带有硬件错误的微控制器,您可以检查第 26 页中 stm32f10xx8 的勘误表,这发生在我身上,stm32f103c8t6 属于 STM32F10xx8系列(如果您的设备不属于该系列,您仍然可以尝试下面列出的第二种解决方案)。
解决方案列在勘误表中,是这样的:
解决方法SCL 和 SDA 模拟滤波器输出分别在 SCL 和 SDA 线上发生转换后更新。 SCL 和 SDA 转换可以通过软件在输出模式下配置 I2C I/O 来强制。 然后,一旦模拟滤波器解锁并输出 SCL 和 SDA 线电平,BUSY 标志可以通过软件复位来复位,I2C 可以进入主模式。 因此,必须应用以下顺序:
另一个解决方案是添加
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(2);
__HAL_RCC_I2C1_RELEASE_RESET();
HAL_I2C_MspInit(...)
之后到HAL_I2C_MspInit(...)
__HAL_RCC_I2C1_CLK_ENABLE();
所以最终的解决方案是
void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(i2cHandle->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
/**I2C1 GPIO Configuration
PB6 ------> I2C1_SCL
PB7 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = I2C_SCL_Pin|I2C_SDA_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* I2C1 clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
//--------------added code :D -----------------------------------
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(2);
__HAL_RCC_I2C1_RELEASE_RESET();
//-------------end of added code---------------------------------
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
}
第二种解决方案可能适用也可能不适用于您,因为它不是 ST 推荐的解决方案,但在我的情况下和许多其他解决方案有效,尽管我不相信产品中的此解决方案,这取决于您可以玩的微型模型如果 2 不起作用,则延迟实际上取决于您使用的微控制器。
我开发了一个 EEPROM 库,您可以检查它并将其用于项目。
特征:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.