Смена парадигмы: от бесконечного цикла loop() к событийной модели

Материал носит ознакомительный характер. Работа с электроникой и микроконтроллерами требует соблюдения техники безопасности; автор не несет ответственности за возможные повреждения оборудования или иной ущерб, возникший в ходе обучения.

Приветствуем в начале пути по освоению nRF52840! Мы рады, что вы решили расширить горизонты и перейти от Arduino к профессиональной разработке беспроводных устройств. Ваш опыт — отличный фундамент. Мы поможем трансформировать его, чтобы вы создавали энергоэффективные гаджеты по стандартам 2026 года. Пройдем путь от первых строк кода до готового прототипа вместе.

Проблема бесконечного цикла

В Arduino программа обычно строится вокруг функции loop(). Процессор работает на износ, постоянно опрашивая периферию: «Нажата кнопка? Пришли данные?». Это — блокирующий код. Пока выполняется delay(1000), микроконтроллер бесполезно «сжигает» такты и не может реагировать на внешние стимулы.

Для nRF52840 такой подход неприемлем. Чип заточен под Bluetooth, где важна мгновенная реакция. Если процессор застрянет в пустом цикле, связь разорвется. Наша цель — научить устройство спать 99% времени и просыпаться только для реальных задач.

Событийная модель: архитектура отклика

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

Два столпа этой архитектуры:

  • Прерывание (Interrupt) — аппаратный «звонок», который заставляет процессор мгновенно бросить текущие дела ради срочной задачи.
  • Callback-функция — ваш «номер телефона». Вы регистрируете этот фрагмент кода в системе, и она вызывает его строго в момент события.

Различие между линейным подходом Arduino и событийным подходом nRF52840 наглядно представлено на Схеме 1.

Практика: работа с кнопкой

Сравним два способа зажечь светодиод при нажатии кнопки.

Как было раньше (опрос в цикле)

Процессор тратит энергию на миллионы пустых проверок в секунду. Любая задержка в коде делает кнопку «невидимой».

void loop() {
  if (digitalRead(BUTTON_PIN) == LOW) { 
    digitalWrite(LED_PIN, HIGH);
  } else {
    digitalWrite(LED_PIN, LOW);
  }
}

Как будет теперь (событийный подход)

Мы настраиваем прерывание на пине. Процессор физически отдыхает, пока сигнал не изменится.

// Это наша Callback-функция
void button_handler(uint32_t pins, uint32_t action) {
    // Выполнится ТОЛЬКО при нажатии
    toggle_led(); 
}

void main(void) {
    // Регистрируем callback
    setup_button_interrupt(BUTTON_PIN, button_handler);
    
    while (1) {
        // Глубокий сон до следующего прерывания
        k_sleep(K_FOREVER); 
    }
}

Золотое правило: Внутри Callback-функции нельзя делать «тяжелые» вычисления или долгий вывод в консоль. Она должна быть молниеносной: зафиксировали событие, подали сигнал основной программе и завершили работу ⚡

Почему это важно

Современный IoT-девайс должен работать от батарейки-таблетки годами. Блокирующий код разрядит её за пару дней. Переход на событийную модель дает три преимущества:

  1. Экономия: энергопотребление падает в тысячи раз.
  2. Скорость: мгновенная реакция на действия пользователя.
  3. Надежность: Bluetooth-соединение не обрывается из-за пауз в коде.

Мы только начали перестраивать мышление. В следующей теме мы изучим Аппаратное превосходство: Cortex-M4, EasyDMA и архитектура Nordic. Вы узнаете о «секретном оружии» — технологии, которая позволяет периферии передавать данные вообще без участия центрального процессора.