我正在尝试与 SMBus 电池通信。那有 2 个部分,所以我使用 2 个 I2C 模块。在第一个 I2C 模块成功通信后,第二个模块卡住了。它卡在忙碌中。在那种情况下,我认为我需要重置该 I2C 模块。但是,我做不到。
我尝试了以下方法:
1)通过使用HAL库deiniting然后再次初始化模块:
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;
}
}
STM32中的I2C模块有没有合适的方法复位?如何从锁定中恢复?
编辑:我正在使用 STM32F103C8。现在我添加了 MX_GPIO_Init 函数,我可以重置模块:
HAL_I2C_DeInit(&hi2c2);
osDelay(50);
MX_GPIO_Init();
HAL_I2C_Init(&hi2c2);
但是传输中的第二个模块总是失败。如果我先使用 hi2c1 然后 hi2c2 然后 hi2c2 失败。如果我先使用 hi2c2 则反之亦然。我试图禁用第一个模块,然后尝试与第二个模块通信,但这也不起作用。