Главная chevron_right Функции chevron_right Связь chevron_right Wire.setWireTimeout()

Wire.setWireTimeout()

Wire.setWireTimeout() задаёт предельное время ожидания I²C-операции в режиме контроллера — если шина зависла, библиотека прервёт передачу и вернёт ошибку вместо бесконечного ожидания.

Полная статья

Описание

setWireTimeout() устанавливает предельное время ожидания для I²C-передачи в режиме контроллера. Если за это время операция не завершается, библиотека прерывает её и возвращает код ошибки — скетч продолжает работу вместо того, чтобы зависнуть навсегда.

Если вызвать функцию без аргументов, будет применено значение тайм-аута по умолчанию, которого достаточно для большинства конфигураций с одним контроллером на шине.

Функция входит в состав библиотеки Wire.

Синтаксис

  • Wire.setWireTimeout(timeout, reset_on_timeout)
  • Wire.setWireTimeout()

Параметры

  • timeout — максимальное время ожидания в микросекундах. Значение 0 полностью отключает проверку тайм-аута. Тип данных: uint32_t.
  • reset_on_timeout — если передать true, аппаратный модуль Wire будет автоматически сброшен при срабатывании тайм-аута. Тип данных: bool.

Возвращает

Ничего.

Пример кода

#include <Wire.h>

void setup() {
  Wire.begin();  // Подключиться к шине I2C (адрес необязателен для контроллера)
  #if defined(WIRE_HAS_TIMEOUT)
    Wire.setWireTimeout(3000 /* us */, true /* reset_on_timeout */);
  #endif
}

void loop() {
  // Отправить команду периферийному устройству
  Wire.beginTransmission(8);
  Wire.write(123);
  byte error = Wire.endTransmission();
  if (error) {
    Serial.println("Error occurred when writing");
    if (error == 5)
      Serial.println("It was a timeout");
  }

  delay(100);

  // Прочитать результат
  #if defined(WIRE_HAS_TIMEOUT)
    Wire.clearWireTimeoutFlag();
  #endif
  byte len = Wire.requestFrom(8, 1);
  if (len == 0) {
    Serial.println("Error occurred when reading");
    #if defined(WIRE_HAS_TIMEOUT)
      if (Wire.getWireTimeoutFlag())
        Serial.println("It was a timeout");
    #endif
  }

  delay(100);
}

Где применяется

  • Устройства с несколькими I²C-периферийными модулями, один из которых может «зависнуть» и удерживать шину.
  • Промышленные или встраиваемые системы, где надёжность важнее скорости реакции на ошибку.
  • Прототипы с длинными проводами или нестабильным питанием периферии.
  • Конфигурации с несколькими контроллерами на одной шине, где арбитраж может затянуться.

Практические замечания

  • Тайм-аут — это симптом, а не лечение. Если тайм-ауты срабатывают регулярно, ищите первопричину: отсутствие подтягивающих резисторов, слишком длинные провода, помехи, неправильный адрес устройства или его некорректное поведение. Тайм-аут лишь не даёт скетчу зависнуть, но не восстанавливает повреждённые данные.
  • Рекомендуемое значение — 25 мс (25 000 мкс). Это максимальное время растяжения тактового сигнала, допустимое протоколом SMBus. Для более высоких тактовых частот или конфигураций с несколькими контроллерами значение можно уменьшить.
  • Флаг тайм-аута нужно сбрасывать вручную. После срабатывания проверяйте состояние через getWireTimeoutFlag(), а сбрасывайте через clearWireTimeoutFlag(). Флаг также сбрасывается при вызове setWireTimeout().
  • Аппаратный сброс (reset_on_timeout = true) полезен, когда сам модуль Wire попадает в некорректное состояние. Если платформа поддерживает эту возможность, сброс помогает восстановить шину без перезагрузки всего устройства.
  • Переносимость: функция появилась позже исходной версии библиотеки Wire и может отсутствовать на некоторых платформах. Для переносимого кода используйте макрос WIRE_HAS_TIMEOUT — он определён только тогда, когда доступны Wire.setWireTimeout(), Wire.getWireTimeoutFlag() и Wire.clearWireTimeoutFlag().
  • Явное отключение тайм-аута лучше выполнять через setWireTimeout(0), а не полагаться на то, что он отключён по умолчанию — поведение по умолчанию может измениться в будущих версиях библиотеки.
  • Значения по умолчанию хранятся в макросах WIRE_DEFAULT_TIMEOUT и WIRE_DEFAULT_RESET_WITH_TIMEOUT — их можно использовать для восстановления исходных настроек после изменения.

Как читать результат

Функция ничего не возвращает, но её эффект виден косвенно:

  • endTransmission() вернёт ненулевой код ошибки, если операция была прервана по тайм-ауту.
  • requestFrom() вернёт 0 (нулевое количество байт) при тайм-ауте.
  • getWireTimeoutFlag() вернёт true, если тайм-аут сработал хотя бы раз с момента последней очистки флага.

Если getWireTimeoutFlag() постоянно возвращает true — это сигнал, что на шине есть проблема, требующая диагностики.