Вторник, 22 ноября 2022 16:39

Зависание шины i2c

Шина I2C очень удобна тем, что всего по двум проводам (не считая питания) можно подключить много датчиков и устройств одновременно. При этом она проста в реализации и модуль I2C есть практически во всех микроконтроллерах. Есть даже реализация "ногодрыгом". Но иногда бывает ситуация когда шина зависает. Датчик может захватить шину до выключения прибора или сброса. В этой статье расскажу как легко оживить зависшую шину.

Первый раз я столкнулся с этой проблемой когда делал прибор Измеритель УФ-индекса. Было удобно подключать к нему различные внешние датчики. Но когда я это делал, то прибор зависал. Позже, когда я делал квадрокоптер, то увидел код сброса шины и попробовал его - работало все отлично!

Итак, как же правильно сбросить шину до рабочего состояния. Оказалось - очень легко. Нужно установить линию данных SDA на вход (то есть не прижимать ее к LOW) - это будет сигнал NACK для датчика. И сделать 9 импульсов подряд на линии SCL. Для этого выводы нужно переключить в режим "ногодрыга", подать эти сигналы и вернуть шину в режим работы с перефирией. Вот нужный код на си:

  //выключаем модуль
  i2c_peripheral_disable(i2c);

  //SCL на выход , SDA на вход PUSH PULL
  gpio_setup_output(I2C1_GPIO_PORT, I2C1_GPIO_SCL);
  gpio_setup_input(I2C1_GPIO_PORT, I2C1_GPIO_SDA);

  //10 сигналов клок
  for (int i=0; i<10;i++) {
    i2c_scl_toggle(i2c);
    delay(10);//10us мкс
  }

  //выключаем клок на LOW
  i2c_scl_set(i2c);

  //включаем ноги на управление модулем
  i2c_setup_gpio(i2c);

  //сброс модуля МК
  i2c_reset(i2c);

  //включаем все обратно
  i2c_peripheral_enable(i2c);

Теперь, если шина часто зависает или прибор должен надежно отрабатывать все зависания, ты знаешь что делать.

Read 709 times