Таймеры Arduino UNO — Часть 2. Работа с прерываниями таймеров

Теория

Что такое прерывание и зачем оно нужно

Прерывание — это специальный механизм микроконтроллера, позволяющий при возникновении определённого события мгновенно приостановить выполнение основного кода и выполнить специальную функцию — обработчик прерывания (ISR, Interrupt Service Routine).

Прерывания используются для задач, которые требуют высокой точности по времени, например, измерение интервалов, генерация сигналов, опрос датчиков, приём данных по UART.

Настройка аппаратного таймера на прерывания

В микроконтроллере ATmega328P можно настроить таймер так, чтобы он вызывал прерывание через заданные интервалы времени. Для этого нужно:

  1. Выбрать режим работы таймера (например, CTC — сброс по совпадению).
  2. Установить значение сравнения в регистре OCRnA (Output Compare Register).
  3. Разрешить прерывание в регистре TIMSKn.
  4. Разрешить глобальные прерывания командой sei().

Регистр TIMSKx и векторы прерываний

  • TIMSK0, TIMSK1, TIMSK2 — регистры разрешения прерываний для соответствующих таймеров.
  • Вектор прерывания — это адрес функции, которую вызовет контроллер при срабатывании события. Например, для таймера 1 в режиме CTC это TIMER1_COMPA_vect.

Практика

Настройка Timer1 для вызова прерывания каждые 1 мс


#include <avr/interrupt.h>

volatile unsigned long counter = 0; // Счётчик миллисекунд

void setup() {
  pinMode(13, OUTPUT);

  // Настройка Timer1
  noInterrupts();           // Отключаем прерывания
  TCCR1A = 0;               // Регистр управления A
  TCCR1B = 0;               // Регистр управления B
  TCNT1  = 0;               // Сброс счётчика

  OCR1A = 15999;            // 16 МГц / 1000 Гц / 1 = 16000 - 1
  TCCR1B |= (1 << WGM12);   // Режим CTC
  TCCR1B |= (1 << CS10);    // Делитель 1 (prescaler 1)
  TIMSK1 |= (1 << OCIE1A);  // Разрешаем прерывание по совпадению

  interrupts();             // Включаем прерывания
}

ISR(TIMER1_COMPA_vect) {
  counter++;
  digitalWrite(13, !digitalRead(13)); // Мигаем светодиодом
}

void loop() {
  // Основной код может выполняться параллельно
}
  

Мерцание светодиода в обработчике прерывания

В приведённом примере встроенный светодиод на пине 13 мигает каждые 1 мс. Однако на практике так часто мигать не имеет смысла — человеческий глаз не заметит.

Проект: Точный секундомер с использованием прерываний

Создадим секундомер, который считает время с точностью до миллисекунды, используя прерывания Timer1.


#include <avr/interrupt.h>

volatile unsigned long millisCounter = 0;

void setup() {
  Serial.begin(9600);

  // Настройка Timer1
  noInterrupts();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 249;              // 16 МГц / 64 / 1000 Гц = 250 - 1
  TCCR1B |= (1 << WGM12);   // Режим CTC
  TCCR1B |= (1 << CS11) | (1 << CS10); // Делитель 64
  TIMSK1 |= (1 << OCIE1A);  // Разрешаем прерывание

  interrupts();
}

ISR(TIMER1_COMPA_vect) {
  millisCounter++;
}

void loop() {
  static unsigned long lastPrint = 0;
  if (millisCounter - lastPrint >= 1000) { // Каждую секунду
    lastPrint = millisCounter;
    Serial.print("Секунд прошло: ");
    Serial.println(millisCounter / 1000);
  }
}
  

Теперь секундомер работает независимо от основного кода, благодаря прерываниям, а точность не зависит от функций delay().

<< Проекты << Все товары >> Статьи, уроки >>

Написать отзыв

Примечание: HTML разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
Модуль 2 — Основы электроники: напряжение, ток, сопротивление и кнопочный фонарик

Модуль 2 — Основы электроники: напряжение, ток, сопротивление и кнопочный фонарик

Модуль 2 — Основы электроники (курс для начинающих) Цель модуля: познакомиться с базовыми э..

Arduino SIM800 CBC уровень заряда

Arduino SIM800 CBC уровень заряда

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

Arduino функции и как с ними бороться

Arduino функции и как с ними бороться

Эта статья из серии уроки Arduino. Тема этого урока: Arduino функции и как с ними бороться. Мы узнае..

Модуль MicroSD карты памяти

Модуль MicroSD карты памяти

Модуль карточки памяти с интерфейсом SPI. Предназначен для сохранения различных данных контроллера: ..

38.02грн.

Переменный резистор 10 кОм

Переменный резистор 10 кОм

Резистор 10 ком переменный. Переменный резистор или потенциометрСопротивление 10 кОмМощность 0,..

21.46грн.