arduino timer - el-pths/w GitHub Wiki

#Ардуино - часть 4

###Таймеры

Контроллеры AtMega имеют в составе себя 3 таймера - устройства, которые могут постоянно и равномерно увеличивать значение специальных регистров независимо от работы программы. Кроме того, если таймер переключить так, чтобы он считал не тики внутреннего генератора, а импульсы на одной из ног - то он становится "счетчиком". Типичные примеры когда это может потребоваться:

  • необходимо измерять сигнал, например, 500 раз в секунду с равной периодичностью;
  • измерение длительности какого-то сигнала (например, от датчика расстояния);
  • подсчет импульсов за единицу времени (например, от счетчика радиоактивного излучения).

Таймеры 0 и 2 работают с 8-разрядными регистрами (т.е. могут считать не больше чем до 255, после чего начинают с 0). Таймер 1 является 16-разрядным. Таймеры можно запускать непосредственно от тиков тактового генератора (на ардуино он работает с частотой 16 МГц) или от делителя частоты (например, с делителем на 64 частота будет 250 кГц, т.е. один тик в 4 микросекунды). Кроме того у таймеров много разных режимов - они могут считать в сторону увеличения и уменьшения, могут в обе попеременно. Могут сбрасываться доходя до нужного числа и т.п.

###Прерывания

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

более подробно, на русском

###Использование прерываний от таймера

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

void setup() {
  pinMode(13, OUTPUT);
  // ... setup timer 0 here for overflow interrupt
}

void loop() {
  digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}

ISR(TIMER1_OVF_vect) {
  // ...
  Serial.println(digitalRead(13)); // print the state of LED
}

Осталось только сконфигурировать (внутри setup) таймер таким образом чтобы эта функция вызывалась, например несколько раз в секунду и мы могли наблюдать в Serial Monitor что она прилежно выписывает изменяющееся состояние светодиода.

Можно также добавить в эту программу изменение частоты мигания, если с компьютера по UART поступил какой-нибудь управляющий символ (например от 1 до 9).

В качестве дополнительных источников две статьи с примерами: короткая и подлиннее

Полезно также почитать и понять смысл значений записываемых в регистры таймера (по документации на AtMega32U4).