STM32 как выйти из блокировки
Я пытаюсь установить связь с батареей SMBus. У него 2 раздела, поэтому я использую 2 модуля I2C. После того, как первый модуль I2C установил успешную связь, второй модуль зависает. И он застревает в состоянии "Занят". В этом случае я подумал, что мне нужно сбросить этот модуль I2C. Однако я не смог этого сделать.
Я пробовал следующие способы:
1) Используя деиницирование библиотеки HAL и затем снова запустив модуль:
HAL_I2C_DeInit(&hi2c1);
HAL_I2C_Init(&hi2c1);
2) Добавление строк Swrst в первый метод:
//Set Swrst bit
I2C2->CR1 |= I2C_CR1_SWRST;
//Clear Swrst bit
I2C2->CR1 &= ~(I2C_CR1_SWRST);
HAL_I2C_DeInit(&hi2c1);
HAL_I2C_Init(&hi2c1);
3)
__HAL_RCC_I2C1_CLK_ENABLE();
__HAL_RCC_I2C1_FORCE_RESET();
__HAL_RCC_I2C1_RELEASE_RESET();
4) Используя документ об ошибках и эту строку кодов:
void I2C_Errate_Workaround(int module){
if(module==1){
//Disable The I2C's
I2C1 -> CR1 &= ~(I2C_CR1_PE);
//Pins are general purpose output open-drain
GPIOB->CRL |= 0b01<<24; //I2C1 SCL Open Drain
GPIOB->CRL |= 0b01<<28; //I2C1 SDA Open Drain
//Make SCL/SDA High
GPIOB-> ODR |= GPIO_ODR_ODR6;
GPIOB -> ODR |= GPIO_ODR_ODR7;
//Check whether pins are high
if((GPIOB->IDR & GPIO_PIN_6) == GPIO_PIN_RESET || (GPIOB ->IDR & GPIO_PIN_7) == GPIO_PIN_RESET)
{
for(;;){}
}
//SDA Low Level
GPIOB->ODR &= ~(GPIO_ODR_ODR7);
// Check if SDA pins are really low
if((GPIOB->IDR & GPIO_PIN_7)== GPIO_PIN_SET){
for(;;){}
}
// SCL Pin to Low
GPIOB -> ODR &= ~(GPIO_ODR_ODR6);
// Check whether SCL pins are cleared
if((GPIOB->IDR & GPIO_PIN_6)== GPIO_PIN_SET){
for(;;){}
}
//Configure SCL to High
GPIOB->ODR |= GPIO_ODR_ODR6;
//Check if SCL High
if((GPIOB->IDR & GPIO_PIN_6)== GPIO_PIN_RESET)
{
for(;;){}
}
//Set SDA High
GPIOB->ODR |=GPIO_ODR_ODR7;
//Check if SDA high
if((GPIOB->IDR & GPIO_PIN_7)== GPIO_PIN_RESET)
{
for(;;){}
}
//Set all to alternate function open drain
GPIOB->CRL |= 0b11<<24; //I2C1 SCL Open Drain
GPIOB->CRL |= 0b11<<28; //I2C1 SDA Open Drain
//Set Swrst bit
I2C1->CR1 |= I2C_CR1_SWRST;
//Clear Swrst bit
I2C1->CR1 &= ~(I2C_CR1_SWRST);
//Enable I2C modules
I2C1->CR1 |= I2C_CR1_PE;
} else if (module ==2){
//Disable The I2C's
I2C2 -> CR1 &= ~( I2C_CR1_PE);
// Pins are general purpose output open-drain
GPIOB->CRH |= 0b01<<8;
GPIOB->CRH |= 0b01<<10;
//Set pins as outputs
GPIOB -> ODR |= GPIO_ODR_ODR10;
GPIOB -> ODR |= GPIO_ODR_ODR11;
//Check whether pins are high
if((GPIOB ->IDR & GPIO_PIN_11) == GPIO_PIN_RESET || (GPIOB -> IDR & GPIO_PIN_10)== GPIO_PIN_RESET)
{
for(;;){}
}
//SDA Low Level
GPIOB ->ODR &= ~(GPIO_ODR_ODR11);
// Check if SDA pins are really low
if((GPIOB->IDR & GPIO_PIN_11)== GPIO_PIN_SET)
{
for(;;){}
}
// SCL Pins to Low
GPIOB -> ODR &= ~(GPIO_ODR_ODR10);
// Check whether SCL pins are cleared
if((GPIOB->IDR & GPIO_PIN_10)== GPIO_PIN_SET)
{
for(;;){}
}
//Configure SCL to High
GPIOB->ODR |= GPIO_ODR_ODR10;
//Check if SCL High
if((GPIOB-> IDR & GPIO_PIN_10)== GPIO_PIN_RESET)
{
for(;;){}
}
//Set SDA High
GPIOB->ODR |= GPIO_ODR_ODR11;
//Check if SDA high
if((GPIOB->IDR & GPIO_PIN_11)== GPIO_PIN_RESET)
{
for(;;){}
}
//Set all to alternate function open drain
GPIOB->CRH |= 0b11<<8; // I2C2 SCL Open Drain
GPIOB->CRH |= 0b11<<10; //I2C2 SDA Open Drain
//Set Swrst bit
I2C2->CR1 |= I2C_CR1_SWRST;
//Clear Swrst bit
I2C2->CR1 &= ~(I2C_CR1_SWRST);
//Enable I2C modules
I2C2->CR1 |= I2C_CR1_PE;
}
}
Есть ли правильный способ сбросить модуль I2C в STM32? Как я могу выйти из тупика?
Изменить: я использую STM32F103C8. Теперь я добавил функцию MX_GPIO_Init и могу сбросить модули:
HAL_I2C_DeInit(&hi2c2);
osDelay(50);
MX_GPIO_Init();
HAL_I2C_Init(&hi2c2);
Но второй модуль в трансмиссии всегда выходит из строя. Если я сначала использую hi2c1, затем hi2c2, тогда hi2c2 не сработает. Если я сначала использую hi2c2, то наоборот. Я попытался отключить первый модуль, а затем попытался связаться со вторым, но это тоже не сработало.