Сразу после вызова 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
, очень вероятно, что выиспользуя микроконтроллер с аппаратной ошибкой, вы можете проверить ошибки stm32f10xx8 на стр. 26, это произошло со мной с stm32f103c8t6 семейства STM32F10xx8 (если ваше устройство не принадлежит этому семейству, вы можетепопробуйте второе решение, указанное ниже).
решение перечислено с ошибками и является следующим:
Обходной путь Выход аналогового фильтра SCL и SDA обновляется послеПереход происходит по линии SCL и SDA соответственно.Переход SCL и SDA может быть вызван программным обеспечением, конфигурирующим входы / выходы I2C в режиме вывода.Затем, когда аналоговые фильтры разблокированы и выводят уровень линий SCL и SDA, флаг BUSY может быть сброшен с программным сбросом, и I2C может войти в основной режим.Поэтому необходимо применить следующую последовательность:
- Отключить периферийное устройство I2C, очистив бит PE в регистре I2Cx_CR1.
- Сконфигурируйте входы / выходы SCL и SDA как открытый выход общего назначения-Drain, High level (запись 1 в GPIOx_ODR)
- Проверка высокого уровня SCL и SDA в GPIOx_IDR.
- Конфигурирование ввода-вывода SDA в качестве выходного сигнала общего назначения с открытым стоком, низкий уровень (записьОт 0 до GPIOx_ODR).
- Проверка низкого уровня SDA в GPIOx_IDR.
- Сконфигурируйте вход / выход SCL как выход общего назначения с открытым стоком, низким уровнем (запись 0 в GPIOx_ODR).
- Проверка низкого уровня SCL в GPIOx_IDR.
- Настройка ввода / вывода SCL в качестве выходного сигнала общего назначения, открытый уровень, высокий уровень (запись 1 в GPIOx_ODR).
- Проверка высокого уровня SCL вGPIOx_IDR.
- Сконфигурируйте ввод / вывод SDA как выход общего назначения, открытый слив, высокий уровень (запись 1 в GPIOx_ODR).
- Проверка высокого уровня SDA в GPIOx_IDR.
- Настройте входы / выходы SCL и SDA в качестве альтернативной функции Open-Drain.
- Установить бит SWRST в регистре I2Cx_CR1.
- Очистить бит SWRST в регистре I2Cx_CR1.
- Включить периферийное устройство I2C, установив бит PE в регистре I2Cx_CR1.
другое решение добавляет
__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, но в моем случае и многие другие работают, хотя я бы не стал доверять это решение в продукте, это зависит от модели вашего микро, вы можете играть с задержкой, если2 не работает, это зависит от того, какой микроконтроллер вы используете.