Управление таймерами микроконтроллеров AVR с помощью программ на языке C (Си)
Таймеры/счётчики AVR — аппаратные модули микроконтроллера, предназначенные для отсчёта времени, подсчёта импульсов, формирования периодических событий и ШИМ-сигналов.
Главное преимущество таймера — он работает аппаратно и не требует постоянного выполнения задержек программой.
1. Для чего используются таймеры AVR
С помощью таймеров можно:
создавать точные временные интервалы;
формировать задержки;
генерировать периодические прерывания;
подсчитывать внешние импульсы;
измерять длительность сигналов;
формировать ШИМ;
управлять яркостью светодиодов;
регулировать скорость двигателя;
формировать звуковые сигналы;
измерять частоту и период.
2. Основные регистры таймера
Конкретные названия зависят от модели AVR, но обычно используются следующие группы регистров.
Счётный регистр
Например:
TCNT0 TCNT1В нём находится текущее значение таймера.
Таймер получает тактовые импульсы и изменяет содержимое этого регистра:
0 → 1 → 2 → 3 → ... → максимальное значениеРегистры управления
Например:
TCCR0A TCCR0B TCCR1A TCCR1BЧерез них задаются:
режим работы;
источник тактирования;
коэффициент деления частоты;
режим ШИМ.
Регистры сравнения
Например:
OCR0A OCR0B OCR1A OCR1BВ них задаётся значение, с которым сравнивается содержимое таймера.
Если:
может произойти:
установка флага;
вызов прерывания;
изменение состояния аппаратного выхода.
3. Предделитель частоты
Тактовая частота микроконтроллера обычно слишком велика для непосредственного формирования длинных интервалов.
Поэтому применяется предделитель — prescaler.
Например:
1 8 64 256 1024Если микроконтроллер работает с частотой:
а предделитель равен 64:
Период одного отсчёта:
То есть таймер изменяется один раз каждые 4 мкс.
4. Основные режимы работы
Normal — обычный режим
Таймер считает от нуля до максимального значения.
Для 8-разрядного таймера:
0 → 1 → 2 → ... → 255 → 0При переполнении может возникнуть прерывание.
CTC — сброс при совпадении
CTC — Clear Timer on Compare Match.
Таймер считает до значения, записанного в регистре сравнения, например OCR0A.
0 → 1 → 2 → ... → OCR0A → 0Этот режим очень удобен для получения точных периодических прерываний.
PWM — широтно-импульсная модуляция
Таймер может автоматически формировать ШИМ-сигнал.
Изменяя значение регистра сравнения, можно изменять коэффициент заполнения импульсов.
Например:
25 % ──┐ ┌── └──────┘ 50 % ────┐ ┌──── └────┘ 75 % ──────┐ ┌────── └──┘ШИМ применяется для управления:
яркостью светодиодов;
скоростью двигателя;
нагревателями;
силовыми ключами.
5. Прерывания таймера
Таймер способен вызвать прерывание:
при переполнении;
при совпадении со значением сравнения;
при захвате входного сигнала.
Для разрешения прерываний используются специальные регистры, например:
TIMSK0 TIMSK1Глобальное разрешение прерываний:
sei();Для этого обычно подключается:
#include <avr/interrupt.h>6. Пример таймера AVR на языке C
Рассмотрим пример для AVR с Timer0, работающим в режиме CTC.
Пусть:
предделитель:
и требуется прерывание примерно каждые 1 мс.
Частота таймера:
За 1 мс требуется:
отсчётов.
Поэтому:
OCR0A = 249;Программа:
#include <avr/io.h> #include <avr/interrupt.h> volatile unsigned int ms = 0; int main(void) { // Режим CTC TCCR0A |= (1 << WGM01); // Значение сравнения OCR0A = 249; // Разрешить прерывание по совпадению TIMSK0 |= (1 << OCIE0A); // Предделитель 64 TCCR0B |= (1 << CS01) | (1 << CS00); // Разрешить глобальные прерывания sei(); while (1) { // Основная программа } } ISR(TIMER0_COMPA_vect) { ms++; }Прерывание вызывается примерно один раз в миллисекунду.
7. Пример мигания светодиодом без _delay_ms()
Можно использовать таймер вместо программной задержки:
#include <avr/io.h> #include <avr/interrupt.h> volatile uint16_t counter = 0; ISR(TIMER0_COMPA_vect) { counter++; if (counter >= 500) { PORTB ^= (1 << PB0); counter = 0; } } int main(void) { DDRB |= (1 << PB0); TCCR0A |= (1 << WGM01); OCR0A = 249; TCCR0B |= (1 << CS01) | (1 << CS00); TIMSK0 |= (1 << OCIE0A); sei(); while (1) { // Здесь могут выполняться другие задачи } }Светодиод меняет состояние примерно каждые 500 мс, а микроконтроллер в это время может выполнять другие функции.
8. Формирование ШИМ
Для генерации ШИМ таймер переводится в режим PWM.
Упрощённый пример:
DDRB |= (1 << PB1); TCCR1A |= (1 << COM1A1); TCCR1A |= (1 << WGM10); TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS11); OCR1A = 128;Значение OCR1A определяет длительность импульса.
При изменении OCR1A изменяется коэффициент заполнения ШИМ.
9. 8-разрядные и 16-разрядные таймеры
AVR могут иметь таймеры различной разрядности.
8-разрядный
Диапазон счёта:
То есть:
состояний.
16-разрядный
Диапазон:
То есть:
состояний.
16-разрядный таймер позволяет получать более длительные интервалы и большую точность задания периода.
10. Счёт внешних импульсов
Таймер может работать не только от внутренней тактовой частоты.
На специальный вход можно подавать внешние импульсы:
Датчик → вход таймера → TCNTКаждый импульс увеличивает счётчик.
Так можно измерять:
число оборотов;
количество изделий;
импульсы расходомера;
частоту внешнего сигнала.
Основной принцип настройки таймера
Обычно программа выполняет следующие действия:
выбирает таймер;
задаёт режим его работы;
выбирает предделитель;
записывает начальное значение или значение сравнения;
при необходимости разрешает прерывание;
запускает таймер;
обрабатывает событие в основной программе или обработчике прерывания.
Кратко для ответа по билету
Управление таймерами AVR на языке C выполняется через специальные регистры TCNT, TCCR, OCR и TIMSK. Таймер подсчитывает внутренние или внешние импульсы и может работать в режимах Normal, CTC и PWM. С помощью предделителя задаётся частота его работы.
Таймеры применяются для формирования временных интервалов, прерываний, подсчёта импульсов, измерения сигналов и генерации ШИМ. Например, в режиме CTC значение TCNT сравнивается с OCR, после совпадения таймер может обнулиться и вызвать прерывание. Это позволяет выполнять точные периодические операции без применения программных задержек.