Sfera-perm.ru

Сфера Пермь
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Таймер счетчик atmega 128

Таймер счетчик atmega 128

В этой статье будет рассмотрено использование таймеров в МК и способ подсоединения кнопок к нему.Сначала немного теории.

В МК ATMega16 есть три таймера/счетчика – два 8-битных (Timer/Counter0, Timer/Counter2) и один 16-битный (Timer/Counter1). Каждый из них содержит специальные регистры, одним из которых является счетный регистр TCNTn (n – это число 0, 1 или 2). Каждый раз, когда процессор выполняет одну команду, содержимое этого регистра увеличивается на единицу (либо каждые 8, 64, 256 или 1024 тактов). Потому он и называется счетным. Помимо него, есть еще и регистр сравнения OCRn (Output Compare Register), в который мы можем сами записать какое-либо число. У 8-битного счетчика эти регистры 8-битные. По мере выполнения программы содержимое TCNTn растет и в какой-то момент оно совпадет с содержимым OCRn. Тогда (если заданы специальные параметры) в регистре флагов прерываний TIFR (Timer/Counter Interrupt Flag Register) один из битов становится равен единице и процессор, видя запрос на прерывание, сразу же отрывается от выполнения бесконечного цикла и идет обслуживать прерывание таймера. После этого процесс повторяется.

Ниже представлена временная диаграмма режима CTC (Clear Timer on Compare). В этом режиме счетный регистр очищается в момент совпадения содержимого TCNTn и OCRn, соответственно меняется и период вызова прерывания.

Это далеко не единственных режим работы таймера/счетчика. Можно не очищать счетный регистр в момент совпадения, тогда это будет режим генерации широтно-импульсной модуляции, который мы рассмотрим в следующей статье. Можно менять направление счета, т. е. содержимое счетного регистра будет уменьшаться по мере выполнения программы. Также возможно производить счет не по количеству выполненных процессором команд, а по количеству изменений уровня напряжения на «ножке» T0 или T1 (режим счетчика), можно автоматически, без участия процессора, менять состояние ножек OCn в зависимости от состояния таймера. Таймер/Счетчик1 умеет производить сравнение сразу по двум каналам – А или В.

Далее представлена функциональная схема таймера/счетчика0:

Для запуска таймера нужно выставить соответствующие биты в регистре управления таймером TCCRn (Timer/Counter Control Register), после чего он сразу же начинает свою работу.

Мы рассмотрим лишь некоторые режимы работы таймера. Если вам потребуется работа в другом режиме, то читайте Datasheet к ATMega16 – там все подробнейше по-английски написано, даны даже примеры программ на С и ассемблере (недаром же он занимает 357 страниц печатного текста!).

Теперь займемся кнопками.

Если мы собираемся использовать небольшое количество кнопок (до 9 штук), то подключать их следует между «землей» и выводами какого-либо порта микроконтроллера. При этом следует сделать эти выводы входами, для чего установить соответствующие биты в регистре DDRx и включить внутренний подтягивающий резистор установкой битов в регистре PORTx. При этом на данных «ножках» окажется напряжение 5 В. При нажатии кнопки вход МК замыкается на GND и напряжение на нем падает до нуля (а может быть и наоборот – вывод МК замкнут на землю в отжатом состоянии). При этом меняется регистр PINx, в котором хранится текущее состояние порта (в отличие от PORTx, в котором установлено состояние порта при отсутствии нагрузки, т. е. до нажатия каких-либо кнопок). Считывая периодически состояние PINx, можно определить, что нажата кнопка.

ВНИМАНИЕ! Если соответствующий бит в регистре DDRx будет установлен в 1 для вашей кнопки, то хорошее нажатие на кнопку может привести к небольшому пиротехническому эффекту – возникновению дыма вокруг МК. Естественно, МК после этого придется отправить в мусорное ведро…

Читайте так же:
Перепрограммирование счетчика меркурий 234

Перейдем к практической части. Создайте в IAR новое рабочее пространство и новый проект с именем, например, TimerButton. Установите опции проекта так, как это описано в предыдущей статье. А теперь наберем следующий небольшой код.

Давайте посмотрим, как это работает. В функциях init_timern задаются биты в регистрах TCCRn, OCRn и TIMSK, причем такой способ может кому-нибудь показаться странным или незнакомым. Придется объяснить сначала, что означает запись «(1 © KERNELCHIP 2006 — 2021

ПРОГРАММИРОВАНИЕ МИКРОКОНТРОЛЛЕРОВ: таймер

Для самых маленьких познавателей микроконтроллеров.
Поговорим про таймеры-счетчики микроконтроллеров AVR и конкретно ATTiny13A.
Начинающим очень сложно порой понять, как работают таймеры, в даташите столько написано про таймеры и так непонятно, что жуть. Да ещё и по-английски.

Обычно описание работы начинают как в даташите сверху вниз, а я начну снизу вверх, так более понятно начинающим.

Работа таймера-счетчика очень похожа на работу механического колесика одометра в панели приборов автомобиля. Вот и с ним будем сравнивать.

Долее по даташиту:

TCNT0 Timer/Counter Register. Это регистр таймера счетчика. Это колесико одометра. Если этому колесику придать вращение от какого нибудь сигнала, то он начнет крутиться. У колесика 255 положений, а не от нуля до девяти, как у одометра авто. Крутится он по кругу, то есть 0,1,2,3…254,255,0,1,2,3… Этот регистр открыт для чтения и записи, то есть можно считывать его значение и писать свое. простой пример: колесико должно крутится до 127, а потом сразу сбрасываться в ноль и считать дальше:

По-русски:
Если значение счетчика равно 127 if(TCNT0==127)
То сбрасываем этот же счетчик в ноль (присваиваем регистру нулевое значение )

В этом примере есть и чтение регистра TCNT0 и запись в этот же регистр.

Теперь выше по даташиту: как и чем и отчего заставить крутится это колесико одометра?

Для этого есть два способа:

1.- От тактового генератора микроконтроллера.
2. — От состояние входа( ножки) Т0

От тактового генератора:

Счетчик крутится от тактового генератора, «скорость» вращения колесика можно выбирать делителем. Отвечает за делитель регистр TCCR0B

Пример расчета «скорости»: тактовый генератор лопатит на 1,2МГц:

TCCR0B=0x00 счетчик выключен.Можно использовать это значение как выключалку таймера-счетчика
TCCR0B=0x01 счетчик лопатит на 1,2МГц: деление на единицу типа)
TCCR0B=0x02 счетчик лопатит на 150кГц: деление на 8
TCCR0B=0x03 счетчик лопатит на 18,75кГц: деление на 64
TCCR0B=0x04 счетчик лопатит на 4,688кГц: деление на 256
TCCR0B=0x05 счетчик лопатит на 1,172кГц: деление на 1024

От состоянии на входной ножке Т0 (это 7 ножка порт РВ2)

TCCR0B=0x06 по спаду сигнала
TCCR0B=0x07 по фронту сигнала

Например: на входе Т0 логический ноль. В регистре TCCR0B=0x06 стоит по спаду сигнала. Счетчик стоит. Появилась единица на входе. Счетчик почуял это и приготовился, ибо по спаду. Пропала единица — стал ноль на входе Т0 — регистр таймера счетчика TCNT0 прибавил себе единичку и опять следит за состоянием по входу Т0

Колесико то крутится, но в холостую. Надо теперь сделать так, чтоб оно делало полезную работу. А вот тут уже много возможностей.

Есть несколько основных выводов полезной работы счетчика-таймера.

Читайте так же:
Габаритные размеры счетчика меркурий 231

Делать работу, можно если значение счетчика (колесико TCNT0) сравняется с регистром сравнения-совпадения OCR0х. Это ещё составная часть таймера счетчика, состоящая из двух равнозначных регистра OCR0A и OCR0B.
OCR0A и OCR0B — это как колесики на кодовом навесном замке. Если уж совсем так сравнивать, то это два отдельных кодовых навесных замка с одним колесиком:

То есть можно выставлять свое значение колесика замка OCR0A или OCR0B, затем крутить колесико таймера одометра TCNT0, при совпадении значений замок открывается и происходит какое либо событие. Описание этого события зависит от того, в каком режиме работы находится таймер-счетчик. От этого режима зависит алгоритм работы и взаимодействия этих регистров. Режимы можно посмотреть в мастере CodeVisionAVR:

Далее простым детским языком уже достаточно сложно объяснять, поэтому резко взрослеем, и начинаем понимать, что такое прерывание, что такое Широтно Импульсная Модуляция и что такое прерывание по переполнению таймера и как эти слова можно использовать к нашему таймеру счетчику, чтоб получить полезное действие.

Теперь примеры, созданные для среды разработки CodeVisionAVR:
значение фьюзов по умолчанию, поэтому тактовая частота равна 1.2МГц. Значения настройки портов и т.п. не указано, только мясо:

TCCR0B=0x03; //Запускаем таймер в обычном счетном режиме на 18,750 kHz
OCR0A=0xF0; // Указываем значение регистра сравнения равное 0хF0
TIMSK0=0x04;//Разрешаем выполнение прерываний по совпадению в OCR0A
#asm(«sei») // Разрешаем сами глобальные прерывания
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
<
// Здесь малюем код
TCNT0=0x00;
>

Скриншот мастера:

Описание:
Таймер-счетчик прибавляет единичку 18750 раз в секунду (то самое колесико одометра TCNT0), значение OCR0A=0xF0; как и так понятно равно F0, в десятичной системе это равно числу 240. Если колесико одометра насчитает 240 «тиков», то сработает прерывание: основной цикл программы останавливается, и начинается выполнения кода «здесь малюем код»:
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
<
// Здесь малюем код
TCNT0=0x00;
>

Внутри фигурных скобок есть сброс колесика одометра в ноль: TCNT0=0x00;, то есть после выполнения кода счетчик сбрасывается и начинается счет с нуля. И так циклично.

Этот код применяется, если необходимо производить какое либо действо через определенный точно заданный промежуток времени: делать опрос какого либо устройства, мерять температуру, сканировать состояние энкодера да еще много что можно. Ну или например, если настроить вызов прерывания ровно раз в секунду, то можно сделать секундомер. Конкретно данный пример срабатывает 18750/240=78,125 раза в секунду.

Теперь интереснее: запускаем ШИМ:

TCCR0A=0x81;//запускаем ШИМ с фазовой коррекцией и назначаем выход ножки PB0(OC0A) на выход импульсов ШИМа
TCCR0B=0x02;//частота работы таймера 150 кГц
TIMSK0=0x02;//разрешаем прерывания по переполнению таймера
#asm(«sei»)// Разрешаем сами глобальные прерывания
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
<
// Малюем код
>

Ну а здесь описание совсем короткое: на выходе PB0 микроконтроллера (ножка 5) будет присутствовать ШИМ сигнал (если будет правильно сконфигурирован этот порт на выход), с заполнением пропорционально значению регистра OCR0A
Примеры:
OCR0A=0; — ШИМа небудет, ноль на выходе
OCR0A=127; — на выходе ровный меандр с заполнением 50/50
OCR0A=255; — на выходе единица, ШИМа нет

Так как включено прерывание по переполнению таймера, то когда счетчик насчитает максимальное значение, то будет срабатывать прерывание (выполняться код «Малюем код»)
Скриншот мастера:

Теперь, освоив и поняв принцип работы таймера, несложно понять, как работает таймер в других режимах, чем отличается ШИМ с фазовой коррекцией от обычного Fast PWM и так далее и тому подобное. Но это вы уже сами.

Читайте так же:
Со скольки считается ночное время по счетчику

MEGA-AVR

Лень — двигатель прогресса! — эксперементируйте облегчая себе жизнь!

Асинхронный режим таймера на примере AVR Atmega8 + CVAVR

В некоторых моделях микроконтроллеров таймер может работать в асинхронном режиме. Это даёт возможность нам построить часы без каких либо внешних спец-микросхем. В этом режиме у Atmega8 может работать Timer2, кварц на 32768 Гц или внешний тактовый сигнал подают на выводы TOSC1 и TOSC2.
Генератор Timer2 оптимизирован под использование часового кристалла с частотой 32768 Гц.


Внешний тактовый сигнал, подаваемый на этот вывод, проходит через тот же самый усилитель с полосой пропускания 256 кГц. Таким образом, внешний тактовый сигнал должен быть в диапазоне от 0 Гц до 256 кГц. Частота внешнего тактового сигнала, подаваемого на вывод TOSC1, не должна превышать одной четвертой от тактовой частоты CPU. Отметим, что тактовая частота CPU может быть ниже частоты XTAL, если разрешено деление частоты XTAL.
Но для правильной его работы нужно правильно его настроить, рассмотрим пример на Atmega8 в CVAVR. Мы не будем строить часы, а просто сделаем «мигалку» с частотой 1 гц – 1 секунда.
И так вооружившись пивом и желанием запускаем наш компилятор, выбираем новый проект и запускаем генератор начального кода.
Выбираем наш AVR микроконтроллер Atmega8 и на вкладке Chip устанавливаем тактирование 8 мгц.
Идём далее в вкладку Ports – и устанавливаем PB0 и PB1 как выходы. К ним будут подключатся светодиоды и внешний таймер в симуляторе.
Теперь самая главная вкладка это Timers->Timer2. В поле «Clock Source» выставляем «TOSC1 pin», тоесть внешнее тактирование с этого пина.
Далее нужно настроить пред-делитель таймера.

Тут на выбор 7 значений, в зависимости от поставленой задачи – нам нужно получить на выходе 1 секунду поэтому мы выбираем пред-делитель на 128, позже поясню почему. Далее разрешаем прерывание по Timer2 и устанавливаем начальное значение счётчика(в нашем случае 00).

Настройка окончена – можно генерировать код.
И так почему же мы выбрали 128 спросите? А всё очень просто можно посчитать по следующей формуле:

T=1/(Tn/(Fr/Td));

где T – время одного прерывания таймера;
Fr – частота резонатора или внешнего тактового сигнала;
Td – предделитель таймера;
Tn – максимальное значение таймера;

Пример:
Т = 1(256 / (32768/2)) = 0.015625 с.
Т = 1(256 / (32768/8)) = 0.0625 с.
Т = 1(256 / (32768/32)) = 0.25 с.
Т = 1(256 / (32768/64)) = 0.5 с.
Т = 1(256 / (32768/128)) = 1 с.
Т = 1(256 / (32768/256)) = 2 с.
Т = 1(256 / (32768/1024)) = 8 с.
Чтобы получить другие временные интервалы нужно изменить частоту или изменить Tn (максимальное значение таймера). Tn = 256 – TCNT2 (начальное значение). Например начальное значение таймера TCNT2=0х05, Tn = 256 – 5 = 251. Подставляем в формулу:
Т = 1(251/ (32768/128)) = 0.98046 с.

Пишем простейший код:

Результат:
В точности совпадает с расчётами.
А теперь закомментируем начальное значение таймера

Результат:

Во время счёта:

Схема с дип и с smd корпусом:

Обратите внимание что нумерация выводов отличается, а программа подходит для обоих чипов. Ещё желательно повесить канденсаторы к кварцу 10-20 pf(для надёжного запуска).
Скачать весь проект Atmega8-32768Hz Скачали 3528 раз

Для удобства я написал программу для ПК которая в автоматическом режиме делает все расчёты по выше изложенным формулам.

Читайте так же:
Плата по счетчику 2015 satrip

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

В микроконтроллерах AVR может быть до 4х таймеров/счетчиков (ТС). Разрядность этих таймеров 8 или 16 бит (т.е. они могут считать до 2 8 =256 или до 2 16 =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 значения 2 16 счетчик переполняется и сбрасывается, и начинает счет заново. В этот регистр мы также можем записать какое-нибудь значение, с которого мы хотим, чтобы наш счетчик стартовал. Для 16-битной операции записи, старший байт должен быть записан первым. Младшийвторым. Для операции 16-битного чтения, младший байт должен быть прочитан первым, а содержимое старшего байта считывается вторым. Если мы настроили изменение состояния входа OC1A или OC1B, тогда значение счетного регистра сравнивается каждый раз со значением регистров OCR1A и OCR1B — регистры сравнения. Каждый из этих регистров состоит из двух байт (например, OCR1AH и OCR1AL). Мы можем записать в эти регистры нужное нам значение и по совпадению значения регистра счетчика с регистром сравнения будет происходить нужное нам изменение на выходах OC1A и OC1B. Также есть регистр захвата входа — ICR1 (ICR1H и ICR1L). Значение TCNT1 в этот регистр записывается при наступлении события на входе ICP1.

Читайте так же:
Денежный счетчик money counts

Счет и изменение состояния ножек МК это уже хорошо, но также этот таймер может при определенных событиях генерить прерывания. Как мы уже видели из таблицы векторов прерываний у ТС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 будет выглядеть вот так

голоса
Рейтинг статьи
Ссылка на основную публикацию
Adblock
detector