我正在使用STM32和EEPROM 512KB,我使用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接地
答案 0 :(得分:0)
尝试一下。首先致电设备准备检查,并确保设备已准备就绪。
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
答案 1 :(得分:0)
好的!第一次是“ true”,但是在写入eeprom之后,您需要确保记录已完成并且eeprom准备好进行下一步。您在最后一行的hi2c1之前还没有过&。 而且,也许对于512kb的EEPROM,您需要指定“ I2C_MEMADD_SIZE_16BIT”而不是“ I2C_MEMADD_SIZE_8BIT”?
答案 2 :(得分:0)
根据处理器的标准,如何确定需要大量时间的记录已完成?为此,需要执行以下过程HAL_I2C_IsDevitseReady。
答案 3 :(得分:0)
在致电HAL_I2C_MspInit(&hi2c1)
之后,您需要立即检查i2c的状态
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的errata,发生在我STM32F10xx8系列的stm32f103c8t6上(如果您的设备不属于该系列,您仍然可以尝试下面列出的第二种解决方案)。
解决方案已在勘误表中列出,并且是这样:
解决方法:分别在SCL和SDA线上发生转换后,将更新SCL和SDA模拟滤波器的输出。可以通过软件在输出模式下配置I2C I / O来强制进行SCL和SDA转换。然后,一旦模拟滤波器被解锁并输出SCL和SDA线电平,就可以通过软件复位来复位BUSY标志,并且I2C可以进入主模式。因此,必须遵循以下顺序:
另一种解决方案是添加
__HAL_RCC_I2C1_FORCE_RESET();
HAL_Delay(2);
__HAL_RCC_I2C1_RELEASE_RESET();
在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推荐的解决方案,但就我而言,尽管我不相信产品中的这种解决方案,但许多others还是可行的,这取决于型号如果2个时钟不起作用,您可以在微控制器中播放延迟,这实际上取决于您所使用的微控制器。
答案 4 :(得分:0)
我开发了一个EEPROM库,您可以对其进行检查并将其用于项目。
功能: