Введение
Таймер-счетчик является одним из самых ходовых ресурсов AVR микроконтроллера. Его основное назначение - отсчитывать заданные временные интервалы. Кроме того, таймеры-счетчики могут выполнять ряд дополнительных функций, как то - формирование ШИМ сигналов, подсчет длительности и количества входящих импульсов. Для этого существуют специальные режимы работы таймера-счетчика.
В зависимости от модели микроконтроллера количество таймеров и набор их функций может отличаться. Например, у микроконтроллера Atmega16 три таймера-счетчика - два 8-ми разрядных таймера-счетчика Т0 и Т2, и один 16-ти разрядный - Т1. В этой статье, на примере ATmega16, мы разберем как использовать таймер-счетчик Т0.
Используемые выводы
Таймер-счетчик Т0 использует два вывода микроконтроллера ATmega16. Вывод T0 (PB0) - это вход внешнего тактового сигнала. Он может применяться, например, для подсчета импульсов. Вывод OC0 (PB3) - это выход схемы сравнения таймера-счетчика. На этом выводе с помощью таймера может формировать меандр или ШИМ сигнал. Также он может просто менять свое состояние при срабатывании схемы сравнения, но об этом поговорим позже.
Выводы T0 и OC0 задействуются только при соответствующих настройках таймера, в обычном состоянии это выводы общего назначения.
Регистры таймера-счетчика Т0
Хоть это и скучно, но регистры - это то, без чего невозможно программировать микроконтроллеры, конечно, если вы не сидите плотно на Arduino. Так вот, таймер Т0 имеет в своем составе три регистра:
- счетный регистр TCNT0,
- регистр сравнения OCR0,
- конфигурационный регистр TCCR0.
Кроме того, есть еще три регистра, относящиеся ко всем трем таймерам ATmega16:
- конфигурационный регистр TIMSK,
- статусный регистр TIFR.
- регистр специальных функций SFIOR
Начнем с самого простого.
TCNT0
Это 8-ми разрядный счетный регистр. Когда таймер работает, по каждому импульсу тактового сигнала значение TCNT0 изменяется на единицу. В зависимости от режима работы таймера, счетный регистр может или увеличиваться, или уменьшаться.
Регистр TCNT0 можно как читать, так и записывать. Последнее используется когда требуется задать его начальное значение. Когда таймер работает, изменять его содержимое TCNT0 не рекомендуется, так как это блокирует схему сравнения на один такт.
OCR0
Это 8-ми разрядный регистр сравнения. Его значение постоянно сравнивается со счетным регистром TCNT0, и в случае совпадения таймер может выполнять какие-то действия - вызывать прерывание, менять состояние вывода OC0 и т.д. в зависимости от режима работы.
Значение OCR0 можно как читать, так и записывать.
TCCR0 (Timer/Counter Control Register)
Это конфигурационный регистр таймера-счетчика Т0, он определяет источник тактирования таймера, коэффициент предделителя, режим работы таймера-счетчика Т0 и поведение вывода OC0. По сути, самый важный регистр.
Биты CS02, CS01, CS00 (Clock Select) - определяют источник тактовой частоты для таймера Т0 и задают коэффициент предделителя. Все возможные состояния описаны в таблице ниже.
Как видите, таймер-счетчик может быть остановлен, может тактироваться от внутренней частоты и также может тактироваться от сигнала на выводе Т0.
Биты WGM10, WGM00 (Wave Generator Mode) - определяют режим работы таймера-счетчика Т0. Всего их может быть четыре - нормальный режим (normal), сброс таймера при совпадении (CTC), и два режима широтно-импульсной модуляции (FastPWM и Phase Correct PWM). Все возможные значения описаны в таблице ниже.
Более подробно будем разбирать режимы в коде. Сейчас все нюансы все равно не запомнятся.
Биты COM01, COM00 (Compare Match Output Mode) - определяют поведение вывода OC0. Если хоть один из этих битов установлен в 1, то вывод OC0 перестает функционировать как обычный вывод общего назначения и подключается к схеме сравнения таймера счетчика Т0. Однако при этом он должен быть еще настроен как выход.
Поведение вывода OC0 зависит от режима работы таймера-счетчика Т0. В режимах normal и СTC вывод OC0 ведет себя одинаково, а вот в режимах широтно-импульсной модуляции его поведение отличается. Не будем сейчас забивать себе голову всеми этими вариантами и разбирать таблицы для каждого режима, оставим это на практическую часть.
И последний бит регистра TCCR0 - это бит FOC0 (Force Output Compare). Этот бит предназначен для принудительного изменения состояния вывода OC0. Он работает только для режимов Normal и CTC. При установки бита FOC0 в единицу состояние вывода меняется соответственно значениям битов COM01, COM00. FOC0 бит не вызывает прерывания и не сбрасывает таймер в CTC режиме.
TIMSK (Timer/Counter Interrupt Mask Register)
Общий регистр для всех трех таймеров ATmega16, он содержит флаги разрешения прерываний. Таймер Т0 может вызывать прерывания при переполнении счетного регистра TCNT0 и при совпадении счетного регистра с регистром сравнения OCR0. Соответственно для таймера Т0 в регистре TIMSK зарезервированы два бита - это TOIE0 и OCIE0. Остальные биты относятся к другим таймерам.
TOIE0 - 0-е значение бита запрещает прерывание по событию переполнение, 1 - разрешает.
OCIE0 - 0-е значение запрещает прерывания по событию совпадение, а 1 разрешает.
Естественно прерывания будут вызываться, только если установлен бит глобального разрешения прерываний - бит I регистра SREG.
TIFR (Timer/Counter0 Interrupt Flag Register)
Общий для всех трех таймеров-счетчиков регистр. Содержит статусные флаги, которые устанавливаются при возникновении событий. Для таймера Т0 - это переполнение счетного регистра TCNT0 и совпадение счетного регистра с регистром сравнения OCR0.
Если в эти моменты в регистре TIMSK разрешены прерывания и установлен бит I, то микроконтроллер вызовет соответствующий обработчик.
Флаги автоматически очищаются при запуске обработчика прерывания. Также это можно сделать программно, записав 1 в соответствующий флаг.
TOV0 - устанавливается в 1 при переполнении счетного регистра.
OCF0 - устанавливается в 1 при совпадении счетного регистра с регистром сравнения
SFIOR (Special Function IO Register)
Начинающему про этот регистр в принципе можно и не знать, один из его разрядов сбросывает 10-ти разрядный двоичный счетчик, который делит входную частоту для таймера Т0 и таймера Т1.
Сброс осуществляется при установке бита PSR10 (Prescaler Reset Timer/Counter1 и Timer/Counter0) в единицу.
Заключение
Нудная часть закончена. Далее разберем как настроить таймер на определенную частоту, как таймер ведет себя в разных режимах, как генерировать ШИМ сигнал.
Comments
OCR1AH=0x03;//записываем в регистр OCR1A 1000
OCR1AL=0xE8;
или можно просто
OCR1A=0x03E8;
Нет, не обязательно. Можете хоть в десятичном, хоть в символьном.
Quoting alex6441161:
У АВР шина 8-битная, поэтому сначала надо писать в Н, потом в L. При чтении наоборот.
Quoting alex6441161:
Так тоже можно, если компилятор поддерживает (IAR и GCC позволяют так обращатся к регистру, насчёт других не знаю).
ISR(TIMER2_OVF_vect) //программа обработки прерывания по переполнению таймера
{
PORTB = (0);
TIMSK0 = (0b00000000);
}
int main(void) //основная программа
{
TCCR0A = (0b00000000);
TCCR0B |= (0b00000101);
DDRB |= (0b10000001);
DDRD |= (0b10000000);
sei(); //разрешаем глобальные прерывания
while(1)
{
IF(PIND.0 == 1)
{
TIMSK0 = (0b00000001);
TCNT0 = (0b00000000);
PORTB.0 = 1;
}
}
}
Можно ли использовать нечто такое?
RSS feed for comments to this post