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

SPI.usingInterrupt()

usingInterrupt() сообщает библиотеке SPI, какое прерывание работает с шиной: тогда SPI.beginTransaction() автоматически блокирует его, защищая транзакцию от вмешательства ISR.

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

Описание

usingInterrupt() решает конкретную проблему: что происходит, если ваш код выполняет SPI-транзакцию, и в этот момент срабатывает прерывание, которое тоже хочет работать с шиной SPI? Без какой-либо защиты данные будут повреждены — одна транзакция «влезет» в середину другой.

Когда вы заранее сообщаете библиотеке SPI, какое прерывание использует шину, она берёт управление на себя: SPI.beginTransaction() автоматически блокирует это прерывание перед началом транзакции, а SPI.endTransaction() снова разрешает его после завершения. Таким образом, транзакция всегда выполняется целиком, без вмешательства ISR.

Важно понимать: регистрировать нужно именно то прерывание, ISR которого вызывает SPI.beginTransaction() и SPI.endTransaction(). Если ваша ISR не работает с SPI, регистрировать её не нужно.

Эта функция является частью библиотеки SPI. Подробности см. в разделе SPI.

Синтаксис

SPI.usingInterrupt(interruptNumber)

Параметры

  • interruptNumber: номер прерывания, которое нужно зарегистрировать. Обычно получают через digitalPinToInterrupt(), передав ему номер пина — это самый надёжный и переносимый способ. Можно также использовать именованные константы прерываний, если они известны для вашей платы. Тип данных: int.

Возвращает

Ничего.

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

  • Датчики с прерыванием по готовности данных: датчик сигнализирует о готовности через пин прерывания, ISR считывает данные по SPI — без usingInterrupt() возможна гонка данных.
  • Энкодеры и кнопки с аппаратным прерыванием: если ISR обновляет состояние устройства через SPI, регистрация прерывания защищает целостность передачи.
  • Многозадачные скетчи: когда основной цикл и ISR независимо обращаются к одной SPI-шине.

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

  • Вызывайте usingInterrupt() до начала любых транзакций — лучше всего в setup(), сразу после инициализации SPI.
  • Используйте digitalPinToInterrupt() вместо числовых констант: это делает код переносимым между разными платами Arduino.
  • Если несколько прерываний работают с SPI, вызовите usingInterrupt() для каждого из них отдельно.
  • Функция влияет только на поведение SPI.beginTransaction() и SPI.endTransaction() — она не заменяет и не отменяет attachInterrupt().
  • Если SPI-транзакции происходят только в основном коде, а ISR не обращается к шине, usingInterrupt() не нужна.