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()не нужна.