[英]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.