Таймеры счетчики микроконтроллеров AVR

Просмотров: 145082Комментарии: 7
Электроника. СхемотехникаAVR.Начинающим

В микроконтроллерах AVR может быть до 4х таймеров/счетчиков (ТС). Разрядность этих таймеров 8 или 16 бит (т.е. они могут считать до 28=256 или до 216=65536). Обычно их используют для точного формирования временных интервалов, подсчета импульсов на выводах микроконтроллера, формирования последовательности импульсов. Таймеры способны вырабатывать запросы на прерывания, при  этом освобождая процессор от необходимости опроса состояния таймеров. В данной статье мы разберем работу таймеров и прерываний, которые они могут вырабатывать, на примере 16-ти битного таймера/счетчика1 (TС1) микроконтроллера ATmega8. Всего у этого МК три таймера - два 8ми битных (TС0, TС2) и один 16 битный (TС1). Взглянем на таблицу векторов прерываний МК mega8 - 7 прерываний связаны с таймерами микроконтроллера, из них 4 связаны с таймером/счетчиком1 (TС1). Давайте разберемся, что же может этот таймер, какие регистры им управляют и что в них нужно записать, чтобы настроить таймер как нам нужно. Для начала рассмотрим все регистры ТС1 и за что какой бит отвечает, а потом рассмотрим какие-нибудь простые примеры по настройке таймера. Начнем с регистров управления таймером.

TCCR1A - регистр управления A
Биты 7:6 - COM1A 1:0: контролируют поведение выхода OC1A (см. Таблицу 1).
Биты 5:4 - COM1B 1:0: контролируют поведение выхода OC1B (см. Таблицу 1).
Биты 3:2 - FOC1A, FOC1B: служат для принудительного изменения состояния выходов OC1A и OC1B.
Биты 1:0 - WGM11, WGM10: служат для настройки ТС1 для работы в качестве широтно-импульсного модулятора (ШИМ). В режиме ШИМ состояние выходов OC1A и OC1B будет отличаться. В этой статье не буду ничего писать про режим ШИМа, а то будет куча информации, которую трудно переварить. Что такое ШИМ опишу как-нибудь в другой раз.

TCCR1B - регистр управления В
Бит 7 - ICNC1: подавление дребезга на входе ICP1. Если бит установлен, то определение события на входе ICP1 происходит с задержкой в 4 машинных цикла (см. дальше по тексту).
Бит 6 - ICES1: выбор фронта срабатывания прерывания по захвату. Если установлен - на растущем фронте, если сброшен - на падающем фронте.
Бит 5 - не используется
Биты 4:3 - WGM1 3:2: для настройки ШИМа.
Биты 2:0 - CS1 2:0: выбор тактирования ТС1 (Таблица 2).

Ну, настроили мы таймер и что? А дальше с частотой, которую мы выбрали в регистре TCCR1B счетчик таймера начинает считать и записывать значение счетчика в регистры TCNT1H и TCNT1L - старший и младший байт счетного регистра. При достижении TCNT1 значения 216 счетчик переполняется и сбрасывается, и начинает счет заново. В этот регистр мы также можем записать какое-нибудь значение, с которого мы хотим, чтобы наш счетчик стартовал. Для 16-битной операции записи, старший байт должен быть записан первым. Младший - вторым. Для операции 16-битного чтения, младший байт должен быть прочитан первым, а содержимое старшего байта считывается вторым. Если мы настроили изменение состояния входа OC1A или OC1B, тогда значение счетного регистра сравнивается каждый раз со значением регистров OCR1A и OCR1B - регистры сравнения. Каждый из этих регистров состоит из двух байт (например, OCR1AH и OCR1AL). Мы можем записать в эти регистры нужное нам значение и по совпадению значения регистра счетчика с регистром сравнения будет происходить нужное нам изменение на выходах OC1A и OC1B. Также есть регистр захвата входа - ICR1 (ICR1H и ICR1L). Значение TCNT1 в этот регистр записывается при наступлении события на входе ICP1.
Счет и изменение состояния ножек МК это уже хорошо, но также этот таймер может при определенных событиях генерить прерывания. Как мы уже видели из таблицы векторов прерываний у ТС1 есть 4 вектора прерывания - прерывание по захвату, прерывание по совпадению А, прерывание по совпадению В, прерывание по переполнению (указаны в порядке уменьшения приоритета). Рассмотрим регистры, настраивая которые можно управлять прерываниями ТС1.

TIMSK - регистр маски прерываний таймеров/счетчиков
Бит 7 - OCIE2: прерывание по совпадению ТС2
Бит 6 - TOIE2: прерывание по переполнению ТС2
Бит 5 - TICIE1: прерывание по захвату ТС1
Бит 4 - OCIE1A: прерывание по совпадению A ТС1
Бит 3 - OCIE1B: прерывание по совпадению В ТС1
Бит 2 - TOIE1: прерывание по переполнению ТС1
Бит 1 - не используется
Бит 0 - TOIE0: прерывание по переполнению ТС0
Если соответствующий бит установлен в "1" и бит I (7-й бит) регистра состояний  SREG установлен в "1", тогда соответствующее прерывание будет срабатывать.

TIFR - регистр флагов прерываний таймеров/счетчиков

Флаги соответствуют прерываниям в регистре TIMSK. Устанавливаются в "1" при выполнении условий соответствующего прерывания.
Вот и вся теория связанная с ТС1. Остальные таймеры настраиваются аналогичным образом. Теперь мы можем обобщить и записать какими возможностями обладает этот таймер:
  • Счетчик 16-ти битный (16 битный ШИМ)
  • Два независимых выхода, срабатывающих по совпадению
  • Один вход по захвату события (растущий или падающий фронт)  и подавление дребезга на этом входе
  • Тактирование от встроенного тактового генератора или внешний источник тактирования таймера (T1)
  • 4 независимых прерывания
Есть и другие возможности, но о них не в этот раз. На рисунке отметил ножки связанные с таймерами/счетчиками МК.
Теперь давайте придумаем себе какие-нибудь условия работы TC1 и настроим его соответствующим образом, записав нужные значения в регистры таймера.
Итак, наш МК тактируется от внешнего кварца с частотой 2.048МГц, мы хотим, чтобы на выходе OC1A был прямоугольный сигнал с периодом 1сек. Как мы дальше думаем? Нам нужно чтобы на выходе OC1A при достижении какого-то значения в счетчике менялся уровень на противоположный каждые 0.5сек. Чтобы уровень менялся на противоположный в регистр TCCR1A нужно записать 0x40 (см. таблицу 1). Теперь посчитаем до какого значения должен считать счетчик. Т.к. время 1сек довольно большая то выберем делитель тактовой частоты 1024, и запишем соответственно в регистр TCCR1B значение 0x05 (см. таблицу 2). Теперь наш таймер считает с частотой 2048000/1024=2000Гц, т.е. за 1сек ТС1 досчитает до 2000, а нам нужно значение до которого он досчитает за 0.5сек. Это значение равно 2000/2=1000 (0x03E8). Именно это значение запишем в регистр OCR1A.Теперь ТС1 досчитает до 1000, его значение совпадет с OCR1A и он изменит состояние выхода OC1A на противоположное и пойдет считать дальше, что нам совсем не нужно. Чтобы этого не произошло запустим прерывание по совпадению А (TIMSK=0x10) и в обработчике будем сбрасывать регистр TCNT1. Вот собственно и все настройки. Эта программа в WinAVR будет выглядеть вот так

#include <iom8.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 2048000
ISR(TIMER1_COMPA_vect)//обработчик прерывания по совпадению А
{
TCNT1H=0;//обнуляем регистр TCNT1
TCNT1L=0;
}
int main()
{
DDRB=0x02;//настраиваем OC1A как выход
PORTB=0x00;
TCCR1A=0x40;//при совпадении уровень OC1A меняется на противоположный
TCCR1B=0x05;//CLK/1024
OCR1AH=0x03;//записываем в регистр OCR1A 1000
OCR1AL=0xE8;
TIMSK = 0x10;//разрешаем прерывание по совпадению
sei();//разрешаем прерывания глобально
while(1);
}

Обновлено 27.03.2011 - ШИМ микроконтроллеров AVR

Комментариев: 7 RSS

2 Андрей 18-12-2012 09:37

как поместить какое-либо значение в счетный регистр А, в В?

3 Beany 22-10-2013 23:59

У Вас небольшая ошибочка в статье

прерывание по совпадению А (TIMSK=0x10)
Прерывание по совпадению А согласно таблице битов будет 0х16 , а не 0х10 - это В

4 Андрей 02-02-2014 05:00

Ощибки нет именно 0x10 ето числа в 16-и ричной системе. Очень толковая статья, вроде все понятно написано. Топикстартер молодец, спасибо!!!

5 Александр 02-12-2014 23:35

подскажите а обязательно значение в регистр OCR1A записывать в 16ричном формате? и обязательно ли записывать значение сначала в старший а потом младший, т.е. вот так:

OCR1AH=0x03;//записываем в регистр OCR1A 1000
OCR1AL=0xE8;

или можно просто

OCR1A=0x03E8;

6 Александр 03-12-2014 00:45

И еще вопрос, если я в программе регулярно меняю значение OCR1A, то мне надо очищать флаг?

7 mVolodya 12-06-2016 22:19

мой трудный вопрос: почему при включении в код двух таймеров в AtMega 8 компилятор требует предопределить макрос isr второго таймера? При удалении любой функции с таким макросом ошибка пропадает.

Оставьте комментарий!

grin LOL cheese smile wink smirk rolleyes confused surprised big surprise tongue laugh tongue rolleye tongue wink raspberry blank stare long face ohh grrr gulp oh oh downer red face sick shut eye hmmm mad angry zipper kiss shock cool smile cool smirk cool grin cool hmm cool mad cool cheese vampire snake excaim question

Используйте нормальные имена. Ваш комментарий будет опубликован после проверки.

Вы можете войти под своим логином или зарегистрироваться на сайте.

(обязательно)