Таймеры 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 разметка не поддерживается! Используйте обычный текст.
    Плохо           Хорошо
ATTINY85

ATTINY85

Плата контроллера ATTINY85Питание от USB 5ВПитание внешнее 7-16В..

179.35грн.

Пружина для натяжения ремня 6мм

Пружина для натяжения ремня 6мм

Стальная пружина для натяжки зубчатого ремня GT2 шириной 6 ммИспользуется в 3d принтерах и CNC-станк..

4.82грн.

Модуль термопары К-типа MAX6675 0...+1024°C для Arduino

Модуль термопары К-типа MAX6675 0...+1024°C для Arduino

Модуль на базе специализированной микросхемы MAX6675 предназначен для точного измерения высоких темп..

168.35грн.

Шестерня для зубчатого ремня на 40 зубьев под ось 8 мм

Шестерня для зубчатого ремня на 40 зубьев под ось 8 мм

Используется для передачи и редукции крутящего момента от двигателя до оси 8 ммКоличество зубьев 40 ..

87.33грн.

Arduino Nano 3.0

Arduino Nano 3.0

Миниатюрная плата контроллера из линейки Aduino на базе микропроцессора ATMEGA328P-AU (это тот же ко..

179.44грн.