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, то наоборот. Я попытался отключить первый модуль, а затем попытался связаться со вторым, но это тоже не сработало.

0 ответов

Другие вопросы по тегам