大家在使用MCU IIC通信時,若碰到設備復位或者總線干擾等情況,可能會導致IIC總線卡死,表現上總線上SDA或者SCL其中一根線為低電平,IIC總線一直處于busy狀態。此時若代碼上一直等待總線空閑,則可能導致軟件死機,為解決該問題,本視頻提供了軟件配置釋放IIC總線的方法。
首先為大家介紹發生IIC總線卡死的兩種情況:(1)主機在發送 START 信號后, 控制 SCL 產生 8 個時鐘脈沖,然后拉低 SCL 信號為低電平,在這個時候,從設備輸出應答信號,將 SDA 信號拉為低電平。如果這個時候主機異常復位, SCL 就會被釋放為高電平。此時,如果從機沒有復位,就會繼續 I2C 的應答,將 SDA一直拉為低電平,直到 SCL 變為低電平,才會結束應答信號。 而由于 I2C 主機復位后檢測總線的狀態,如果 SDA 信號為低電平,則 I2C 總線被占用,會一直等待 SCL 和 SDA信號變為高電平,因此,在 I2C 主機等待從機釋放 SDA 信號時, I2C 從機又在等待主機將 SCL 信號拉低以釋放應答信號,兩者相互等待, I2C 總線進入死鎖狀態 ;(2)主機在發送 START 信號后, 控制 SCL 產生 8 個時鐘脈沖,然后拉低 SCL 信號為低電平,在這個時候,從設備輸出應答信號,將 SDA 信號拉為低電平。如果這個時候主機異常復位, SCL 就會被釋放為高電平。此時,如果從機沒有復位,就會繼續 I2C 的應答,將 SDA一直拉為低電平,直到 SCL 變為低電平,才會結束應答信號。 而由于 I2C 主機復位后檢測總線的狀態,如果 SDA 信號為低電平,則 I2C 總線被占用,會一直等待 SCL 和 SDA信號變為高電平。因此,在 I2C 主機等待從機釋放 SDA 信號時, I2C 從機又在等待主機將 SCL 信號拉低以釋放應答信號,兩者相互等待, I2C 總線進入死鎖狀態 。
以下為兩種復位IIC總線卡死的軟件方法,大家可以嘗試使用:
(1)將SDA和SCL配置為推挽輸出,強制輸出stop信號
在 I2C 主機復位后,主機檢測 I2C 總線一直為 BUSY 狀態,且超過設定的時間,則總線被鎖死。可通過將 I2C 的 SCL 和 SDA 引腳初始化成普通 GPIO 功能,配置成推挽輸出。 先拉高SCL 信號,在拉高 SDA 信號,模擬產生一個 STOP 信號,然后再配置為 I2C 的引腳復用功能。配置代碼如下所示。
/*! brief reset i2c bus param[in] none param[out] none retval none */ void i2c_bus_reset() { GPIO_BC(GPIOB) |= GPIO_PIN_6 | GPIO_PIN_7; gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6|GPIO_PIN_7); __nop(); __nop(); __nop(); __nop(); __nop(); GPIO_BOP(GPIOB) |= GPIO_PIN_6; __nop(); __nop(); __nop(); __nop(); __nop(); GPIO_BOP(GPIOB) |= GPIO_PIN_7; gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); } /*! brief check the I2C is or not busy param[in] none param[out] none retval none */ void check_bus_status(void) { while(i2c_flag_get(I2C0,I2C_FLAG_I2CBSY)) { if(--time_out == 0){ i2c_bus_reset(); } } }
(2)將SCL配置為推挽輸出,強制輸出9個clk
在 I2C 主機中增加 I2C 總線恢復程序。每次 I2C 主設備復位后,如果檢測到 SDA 數據線被拉低,則控制 I2C 中的 SCL 時鐘線產生 9 個時鐘脈沖(針對 8 位數據的情況),這樣 I2C 從設備就可以完成被掛起的操作,從死鎖狀態中恢復過來。
I2C 主機通過將 SCL 引腳初始化為普通 GPIO 功能,配置成推挽輸出。保證連續發送 9 個時鐘脈沖,為保證后續 I2C 正常通信,先將 I2C 模塊復位,再置位,最后再配置為 I2C 的引腳復用功能。配置代碼如下所示。
/*! brief reset i2c bus param[in] none param[out] none retval none */ void i2c_bus_reset() { uint8_t I = 0; gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); /* SCL output clock signal */ for(I = 0; I < 10; i++){ gpio_bit_reset(GPIOB, GPIO_PIN_6); delay_1us(2); gpio_bit_set(GPIOB, GPIO_PIN_6); delay_1us(2); } /* reset I2C */ i2c_software_reset_config(I2C0, I2C_SRESET_RESET); i2c_software_reset_config(I2C0, I2C_SRESET_SET); gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); } /*! brief check the I2C is or not busy param[in] none param[out] none retval none */ void check_bus_status(void) { while(i2c_flag_get(I2C0,I2C_FLAG_I2CBSY)) { if(--time_out == 0){ i2c_bus_reset(); } } }
上一篇:GD32 FATFS+FTL Nand解決方案
下一篇:基于GD32驅動BLDC電機(1)定時器和PWM
推薦閱讀最新更新時間:2025-03-31 17:34





設計資源 培訓 開發板 精華推薦
- 雙極性輸入 24 位 A/D 轉換器接受 2.5V 輸入
- LTC2634-HMI8 四路、8 位數模轉換器的典型應用
- LTC3355 的典型應用 - 具有集成 SCAP 充電器和備用穩壓器的 20V 1A 降壓型 DC/DC
- STM32C8T6遙控船天線主控系統
- REF194 低壓差開關輸出電壓基準的典型應用電路
- 使用 LT1054IN8 3.5V 至 5V 穩壓器的典型應用
- ADA4637-1ARZ-R7帶保護同相放大器典型應用電路
- 套件STDES-IDS003V1和STDES-IDS002V1的電源監控板
- NCP1060BUCKGEVB:用于低功率離線 SMPS 評估板的高壓開關
- L7818C 分體式穩壓器的典型應用 (± 15 V - 1 A)