1

我正在尝试与 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 则反之亦然。我试图禁用第一个模块,然后尝试与第二个模块通信,但这也不起作用。

4

0 回答 0