Перейти к содержанию

ACK и NACK (подтверждение в I²C)

После каждого байта на шине I²C идёт ещё один, девятый такт. В нём приёмник отвечает передатчику: байт принят, можно продолжать — или нет. Этот ответ называют подтверждением, ACK, а его отсутствие — NACK.

Обновлено Редакция GAW

ACK (acknowledge, подтверждение) и NACK (not acknowledge, отсутствие подтверждения) — бит, которым приёмник на шине I²C отвечает после каждого принятого байта, включая байт адреса. По спецификации NXP UM10204 все такты, включая девятый, формирует контроллер. На девятом такте передатчик отпускает линию SDA, и приёмник:

  • прижимает SDA к нулю, и она остаётся в нуле всю высокую фазу такта — это ACK;
  • оставляет SDA в единице — это NACK.

После NACK контроллер завершает обмен условием STOP или начинает новый повторным START.

Пять причин NACK по UM10204

  1. На шине нет устройства с переданным адресом.
  2. Приёмник занят работой в реальном времени и не готов к обмену.
  3. Приёмник получил данные или команду, которых не понимает.
  4. Приёмник больше не может принимать байты.
  5. Контроллер-приёмник сообщает ведомому, что чтение закончено.

Первые четыре — ошибки или отказ ведомого, пятая — штатная часть каждого чтения: последний прочитанный байт ведущий не подтверждает.

ACK в I²C и SMBus

Спецификация I²C не обязывает устройство всегда подтверждать свой адрес. Поэтому по NACK нельзя отличить отсутствующее устройство от занятого. В SMBus устройство обязано подтверждать адрес (с оговорёнными исключениями), и пропавшее подтверждение там прямо означает отказ или отключение, см. SMBus. Как выглядят ACK и NACK в транзакции записи и чтения регистра, показывает конструктор транзакции I²C.

Не путать с ACK в CAN: там подтверждает кадр любой узел, принявший его без ошибок, доминантным битом в слоте ACK, и отсутствие подтверждения — ошибка передатчика. И с ответами ACK/NACK в протоколах загрузчиков: это байты данных, а не бит на девятом такте.

Частые вопросы

Почему датчик отвечает NACK на свой адрес?

Чаще всего на шине нет устройства с таким адресом: неверный адрес (например, 7-битный адрес перепутан с 8-битной записью вместе с битом R/W), не подано питание, перепутаны SDA и SCL, нет подтяжек. NXP называет ещё случай, когда устройство занято своей работой и не готово к обмену.

Зачем ведущий отвечает NACK при чтении?

Чтобы сказать ведомому, что этот байт последний. Пока ведущий подтверждает байты, ведомый продолжает выдавать данные. NACK на последнем байте заставляет его отпустить SDA, и ведущий может сформировать STOP или повторный START.

Кто формирует такт для бита подтверждения?

Всегда контроллер (ведущий), как и все остальные такты. Подтверждение же выдаёт приёмник: ведомый при записи, ведущий при чтении. Передатчик на этом такте отпускает SDA, чтобы приёмник мог прижать её к нулю.

Источники

  1. NXP Semiconductors. UM10204: I2C-bus specification and user manual (Rev. 7.0, 1 October 2021) — разд. 3.1.6: подтверждение после каждого байта; все такты, включая девятый, формирует контроллер; передатчик отпускает SDA, приёмник прижимает её к нулю, и она стабильна в высокой фазе девятого такта; SDA в единице — NACK, после него контроллер выдаёт STOP или повторный START; пять причин NACK; разд. 3.1.10: контроллер-приёмник отвечает NACK на последний байт перед STOP или повторным START
  2. Texas Instruments. Understanding the I2C Bus (SLVA704A, June 2015, rev. October 2026) — разд. 2.3: за каждым байтом, включая адрес, идёт бит ACK от приёмника; перед ACK передатчик отпускает SDA, приёмник прижимает её в низкой фазе девятого такта; SDA в единице — NACK; контроллер-приёмник сообщает NACK, что закончил чтение
  3. System Management Interface Forum. System Management Bus (SMBus) Specification, Version 3.3.1 (20 Oct 2024) — прил. B.3: спецификация I²C не требует, чтобы устройство всегда подтверждало свой адрес, а SMBus требует (с ограниченными исключениями)
  4. Robert Bosch GmbH. CAN Specification Version 2.0 (1991) — часть A, разд. 3.1.1: поле ACK — слот ACK и разделитель; передатчик шлёт два рецессивных бита, приёмник, правильно принявший кадр, пишет доминантный бит в слот ACK

Нашли ошибку?