Частота тактирования таймера счетчика
В этом переводе апноута AVR130 [1] рассматриваются следующие вопросы:
• Описание событий таймеров/счетчиков
• Оповещение о событиях таймера/счетчика
• Опции тактирования
• Пример кода для Timer0 (прерывание по переполнению)
• Пример кода для Timer1 (Input Capture, прерывание по захвату входного сигнала)
• Пример кода для Timer2 (асинхронная работа, прерывание по совпадению Compare Match)
• Базовые сведения о ШИМ (PWM)
• Пример генерации ШИМ на основе Timer2
В апноуте описано, как использовать различные таймеры AVR на примере микроконтроллера AT90S8535. Назначение документа — дать общий обзор таймеров, показать их возможности и разъяснить конфигурирование. Все это пояснено примерами кода, которые можно взять за основу для создания других приложений. Продвинутые читатели могут пропустить общий обзор, и сразу начать с секции «Настройка таймеров». Дополнительную информацию можно найти в даташитах на микроконтроллер и в апноутах, где используются таймеры.
[Общий обзор]
В принципе таймер это простой счетчик. Его достоинство в том, что он может считать импульсы входной частоты и работать независимо от основного потока выполнения программы. Строго заданная частота тактирования делает возможным измерять интервалы времени в единицах периода тактов таймера.
Почему существуют разные таймеры? Ответ очень прост: для создания подходящего таймера для разных задач нужны некоторые разные (аппаратные) ресурсы.
Обычно в микроконтроллерах серий 90S, megaAVR и tinyAVR имеется два 8-битных таймера и один 16-битный. Таймер, у которого 16-битное разрешение, обычно более гибок в настройке и обладает расширенным функционалом в сравнении с 8-битным таймером. Однако правило «чем больше тем лучше» не всегда справедливо для мира микроконтроллеров, когда нужно решить узкоспециализированную задачу. Для многих приложений достаточно 8-разрядной разрешающей способности. Использование разрядности выше означает увеличение затрат на вычисления, увеличение времени обработки, и этого нужно пытаться избегать путем оптимизации кода по скорости. Это также означает, что нужно применять более дорогой микроконтроллер. Гибкость таймеров AVR позволяет приспособить их для решения различных задач. Количество таймеров определяет количество различных конфигураций. Далее будут более подробно описаны эти опции конфигурации.
[События таймеров]
Таймер AVR может быть настроен на обработку некоторых событий. Флаги состояния в регистре TIMSK покажут, произошло ли какое-то событие. Микроконтроллер AT90S8535 может быть сконфигурирован для отслеживания до 3 событий на таймер. Ниже описаны эти события.
Переполнение (Timer Overflow). Переполнение таймера (timer overflow) означает, что счетчик таймера досчитал до своего предельного значения (255 для 8-битного таймера и 65535 для 16-битного) и сбросился в 0 при следующем тактовом цикле. Разрешение таймера (т. е. диапазон его счета) определяется разрядностью счетчика в таймере. В микроконтроллере AT90S8535 есть 2 таймера с 8-битным разрешением и 1 таймер с 16-битным разрешением. Максимальное значение, до которого может считать таймер, вычисляется по следующей формуле (здесь Res, стоящая в показателе степени, это разрешающая способность в битах, или 8 или 16):
MaxVal = 2 Res – 1 | (Формула 1) |
Событие переполнения взведет флаг Timer Overflow (TOVx) в регистре Timer Interrupt Flag Register (TIFR).
Совпадение (Compare Match). В тех случаях, когда недостаточно отслеживать переполнение таймера, может использоваться прерывание по совпадению счетчика с неким заданным значением (compare match interrupt). Регистр Output Compare Register (OCRx) может быть загружен значением [0..MaxVal] которое будет проверяться на совпадение со счетчиком при каждом тактовом цикле таймера. Когда таймер достигнет значения сравнения, будет установлен соответствующий флаг Output Compare Flag (OCFx) в регистре TIFR. Таймер может быть сконфигурирован для очистки регистра счетчика в 0 при событии совпадения.
Связанные с функцией совпадения порты микроконтроллера могут быть сконфигурированы как выходы для автоматической установки, сброса и переключения при наступлении события совпадения. Эта функция очень полезна для генерирования сигналов прямоугольной формы различных частот. Эта функция предоставляет много возможностей для реализации DAC (преобразование цифровых данных в аналоговый сигнал). Режим PWM специально предназначен для наилучшей генерации сигналов синусоидальной и другой формы. Подробнее см. раздел «Базовые сведения о PWM», даташит [4].
Захват входа (Input Capture). У AVR есть входной порт, предназначенный для срабатывания от входных событий, т. е. происходит событие захвата входного события (input capture event). Изменение сигнала на этом входе приведет к тому, что значение из счетчика таймера будет прочитано и сохранено в регистре захвата Input Capture Register (ICRx). Одновременно с этим установится флаг Input Capture Flag (ICFx) в регистре TIFR. Функция захвата полезна для измерения длительности внешних импульсов.
[Как происходит оповещение о событиях]
Таймер работает независимо от выполнения кода программы. Для каждого события таймера есть соответствующий флаг состояния в регистре флагов прерывания (Timer Interrupt Flag Register, TIFR). Произошедшее событие таймера требует оповещения процессора, чтобы он предпринимал по событию соответствующие действия. Это как раз и делается установкой определенного флага, когда происходит определенное событие.
Есть три различных способа отслеживать события таймера и реагировать на них:
1. Постоянный опрос флагов статуса – флагов прерывания и по ним определять запуск соответствующего кода.
2. Остановка основного потока программы и выполнение обработчика прерывания Interrupt Service Routines (ISR).
3. Автоматическое измерение уровня выходного порта.
Опрос флагов прерывания. Этот метод использует тот факт, что процессор помечает события таймера установкой соответствующих флагов прерывания. Основной код программы может часто проверять состояние этих флагов — чтобы узнать, произошло ли какое-то событие. Это требует некоторой излишней траты процессорного времени. Достоинства этого решения — простота, и возможность очень быстрой реакции, если используется очень короткие циклы опроса.
Реализация на ассемблере этого метода для Timer0 может выглядеть примерно как показано в примере ниже. Эти три строки кода должны быть размещены в главном цикле, который прокручивается с большой частотой.
Оповещение по прерываниям. Микроконтроллер AVR может быть сконфигурирован так, что будет запускаться обработчик прерывания, если произошло событие таймера (если установится соответствующий флаг прерывания в регистре TIFR). В этом случае главный поток программы немедленно (почти всегда немедленно) останавливается (прерывается, отсюда и пошел термин «прерывание»), и процессор переходит к выполнению кода обработчика прерывания (Interrupt Service Routine, сокращенно ISR). Достоинство по сравнению с опросом флагов состоит в том, что основной код освобождается от затрат процессорного времени на опрос флагов, и может вместо опроса заниматься другими вычислениями. В разделе «Настройка таймеров» даны несколько примеров, как это делается. Прерывания таймера разрешаются установкой соответствующих битов в регистре маски прерываний таймера Timer Timer Interrupt Mask Register (TIMSK). В следующем примере показано, как разрешить Output Compare Interrupt для Timer2:
Автоматическая обработка событий. Timer1 и Timer2 поддерживают реагирование на события прерывания таймера полностью аппаратно, без необходимости выполнения кода. Связанные с этой функцией выходные порты могут быть сконфигурированы для автоматической установки, сброса или переключения в противоположное состояние при возникновении события совпадения (compare match). Если сравнивать с двумя предыдущими методами, то после настройки это будет происходить параллельно с выполнением обычной программы, и не будет требовать трат процессорного времени на обработку событий.
Следующий пример кода показывает, как установить значение совпадения и разрешить переключение вывода порта. Обычно настройка действия выходного порта делается путем конфигурирования двух битов COMx0 и COMx1 в регистре TCCRx (вместо x подставляется номер таймера, 1 или 2). Конфигурирование Timer2 может выглядеть примерно так:
Для того, чтобы вывод порта OCx мог переключаться, он должен быть настроен как выход установкой соответствующего бита в регистре направления данных (data direction register, DDR). К функции OCx привязана определенная ножка определенного порта микроконтроллера.
[Тактирование]
Узел тактирования таймеров AVR состоит из предделителя (прескалера), подключенного к мультиплексору. Прескалер можно описать как ступенчатый делитель частоты. Он реализован как двоичный счетчик с несколькими выходными сигналами от разных ступеней счетчика. Для AT90S8535 это 10-разрядный счетчик, используемый для деления входной частоты на 4 разных коэффициента деления (в случае Timer2 это 6 коэффициентов), так что можно получить разные тактовые частоты. Мультиплексор используется для выбора нужной поделенной тактовой частоты в качестве входного сигнала для тактирования таймера. Альтернативно мультиплексор может быть использован для пропуска прескалера, и для конфигурирования внешнего вывода для использования его как входа для счетчика таймера.
Фактически имеется 2 разных прескалера, но 3 разных таймера, что можно увидеть в контексте выбора — на каком источнике тактов основана делимая величина частоты. Оба таймера Timer0 и Timer1 синхронны с системной тактовой частотой (тактовая частота ядра AVR) в качестве источника тактов. В этом случае нет ограничений, если оба счетчика используют один и тот же прескалер (при этом каждый таймер может быть сконфигурирован отдельно). Однако асинхронно тактируемый Timer2 нуждается в собственном прескалере, чтобы быть независимым от системной тактовой частоты.
На рис. 1 ниже показан прескалер и узел конфигурирования тактовой частоты таймера на мультиплексоре. Даташит на используемый микроконтроллер даст больше информации о всех прескалерах и мультиплексорах. Обзор возможных настроек тактирования приведен в таблице 1. В следующих секциях это будет рассмотрено подробнее.
Таблица 1. Обзор настроек тактирования.
TCCRx | Для синхронных Timer0 и Timer1 PCK = CK | Для синхронно/асинхронного Timer2 PCK = f(AS2) | ||
Бит 2 | Бит 1 | Бит 0 | ||
CSx2 | CSx1 | CSx0 | TCK0,1 | TCK2 |
0 (таймер остановлен) | 0 (таймер остановлен) | |||
1 | PCK (системная частота ядра AVR) | PCK2 (системная частота / асинхронное тактирование) | ||
1 | PCK / 8 | PCK2 / 8 | ||
1 | 1 | PCK / 64 | PCK2 / 32 | |
1 | PCK / 256 | PCK2 / 64 | ||
1 | 1 | PCK / 1024 | PCK2 / 128 | |
1 | 1 | Внешний вывод, тактирование по спаду уровня | PCK2 / 256 | |
1 | 1 | 1 | Внешний вывод, тактирование по нарастанию уровня | PCK2 / 1024 |
1. Во время работы прескалер функционирует непрерывно. В случаях, когда таймер должен делать отсчеты очень точно, нужно обеспечить, чтобы прескалер начинал считать от нуля. В моделях микроконтроллеров, где не возможности сброса прескалера, момент перехода прескалера через переполнение можно детектировать в программном обеспечении, и соответственно инициализировать регистр таймера/счетчика TCNTx.
2. В новых устройствах, где имеется общий прескалер, выполнение сброса прескалера повлияет на все подключенные к нему таймеры.
Рис. 1. Предделитель (прескалер).
Тактирование от частоты ядра (System Clock). В этом случае системная тактовая частота используется в качестве входного сигнала для прескалера. Даже если было выбрано поделенное значение частоты вместо системной частоты, эта поделенная частота основана на частоте системных тактов. Таким образом, тактовая частота таймера синхронна с системной частотой тактов.
Все 3 таймера AT90S8535 и большинство таймеров других AVR поддерживают эту опцию. Достоинство тактирования от частоты ядра в том, что для этого не требуется дополнительных внешних схем. Из-за высокой тактовой частоты системы можно отслеживать короткие отрезки времени.
Частота переполнения таймера является хорошим индикатором размера фрейма времени, в пределах которого может работать таймер. Формула ниже (вычисление частоты переполнения таймера TOVCK) показывает взаимосвязь между частотой переполнения таймера TOVCK, максимальным значением для счетчика таймера (MaxVal), системной тактовой частоты (CK) и коэффициента деления прескалера (PVal):
fCK (PCKx/PVal) PCKx TOVCK = ——— = ————- = —————— MaxVal MaxVal (PVal * MaxVal) | (Формула 2) |
Предположим, что ядро AVR работает частоте fCPU = 3.69 МГц, разрядность таймера 8 битt (MaxVal = 256). Если выбрать коэффициент деления прескалера 64, то таймер будет тактироваться от частоты TCK = 3.69 MHz/64, так что будет происходить 225 переполнений таймера в секунду. Вот корректное математическое описание:
При 225 переполнениях таймера в секунду получается, что между переполнениями будет проходить 4.4 миллисекунды. С максимальным коэффициентом деления прескалера прерывание от переполнения таймера будет происходить каждую 71 мс, а с минимальным коэффициентом деления каждые 69 мкс. В большинстве случаев для определения настроек могут быть использованы разные методы. Требования приложения будут задавать частоту переполнений таймера. Базируясь на ней, и на имеющейся частоте тактов ядра вместе с разрядностью таймера настройки прескалера могут быть вычислены по следующей формуле:
PCKx PVal = —————— (TOV * MaxVal) | (Формула 3) |
Реализация на ассемблере для Timer0 может выглядеть как в следующем примере кода. Эти строки установят значения прескалера в TCCR0 для коэффициента деления 1024 (см. таблицу 1).
Тактирование от асинхронного источника. В отличие от двух других таймеров, которые не поддерживают этот вариант тактирования, Timer2 микроконтроллера AT90S8535 может асинхронно тактироваться от внешнего тактового сигнала. Для этой цели к выводам TOSC1 и TOSC2 может быть подключен кварцевый или керамический резонатор — это выводы, которые подсоединены к встроенному генератору.
Встроенный генератор на выводах TOSC1 и TOSC2 оптимизирован для часового резонатора на частоту 32.768 кГц. Эта частота хорошо подходит для реализации часов реального времени (Real Time Clocks, RTC) (1) . Показано главное достоинство отдельной тактовой частоты — она не зависит от системной частоты ядра AVR. Это делает возможным работу микроконтроллера на высокой частоте, в то время как таймер тактируется от внешних тактов с частотой, оптимизированной под точный отсчет времени. Дополнительно можно переключать ядро в режимы пониженного энергопотребления, что не повлияет на работу асинхронно тактируемого таймера.
Примечание (1): внешняя тактовая частота должна быть в интервале 0 Гц .. 256 кГц, и с максимальным значением CK/4.
Асинхронное функционирование требует учета некоторых дополнительных условий. Поскольку тактирование Timer2 асинхронно, то события таймера синхронизируются с ядром AVR. Это требует, чтобы тактовая частота таймера была как минимум вчетверо меньше, чем системная частота ядра (т. е. внутренняя частота ядра должна быть как минимум в 4 раза выше частоты тактирования таймера). С другой стороны, нужно избегать конфликтов между синхронным и асинхронным доступом. Это осуществляется путем использования промежуточных регистров. Биты состояния сигнализируют, что происходит обновление конфигурационных регистров. См. подробности в описании Asynchronous Status Register (ASSR) в даташите на микроконтроллер.
Частота переполнения таймера TOVCK вычисляется по формуле 2, но вместо системной частоты в формулу подставляется частота генератора. Настройки TCCR2 даны в таблице 1. Входная частота прескалера PCK2 является функцией бита AS2 в регистре ASSR. Если этот бит очищен, то таймер работает в синхронном режиме от системной тактовой частоты. Если этот бит установлен, то для входной частоты прескалера используется асинхронный тактовый сигнал выводов TOSC1 и TOSC2.
Реализация на ассемблере для Timer2 может выглядеть как в примере кода ниже. Эти 2 строки установят настройку прескалера в TCCR2 на коэффициент деления 1024 (см. таблицу 1).
Внешнее тактирование. Внешнее тактирование поддерживается только таймерами Timer0 и Timer1. Этот режим позволяет использовать широкий диапазон внешних сигналов в качестве тактовых частот. Это синхронное тактирование, что означает, что ядро детектирует состояние вывода и тактирует таймер синхронно с системной тактовой частотой, если был детектирован внешний тактовый сигнал. По каждому фронту нарастания внутреннего такта ядра делается выборка внешнего тактового сигнала. Для ядра нужно как минимум 2 такта ядра для детектирования изменения на внешнем тактовом входе, так что максимальная тактовая частота внешних тактов должна быть не более чем CK/2. Для индикации внешнего события такта может использоваться либо фронт, либо спад внешнего тактового сигнала T0/T1. Этот выбор делается в регистре TCCRx путем установки битов CS00, CS01 и CS02 (см. таблицу 1).
Реализация на ассемблере для Timer0 может быть выглядеть как в примере кода ниже. Эти строки настроят вывод T0 в качестве входа для тактовой частоты таймера, активным перепадом тактирования будет фронт нарастания сигнала (см. таблицу 1).
Примечание: важно настроить вывод T0 как вход через регистр направления данных (Data Direction Register) порта B (DDRB). Настройка регистра направления не перезаписывается настройкой таймера, потому что это также разрешено в AVR для реализации программно тактируемого таймера. T0 и T1 по умолчанию (после сброса или включения питания) настроены как входы.
Как остановить таймер. Остановка таймера, чтобы он прекратил счет, очень проста. Нулевое значение для настройки прескалера в регистре TCCRx остановит соответствующий таймер (см. таблицу 1). Однако помните, что прескалер все равно работает.
Реализация на ассемблере для Timer0 может выглядеть как в примере кода ниже.
Примечание: другие регистры TCCRx могут содержать конфигурационные биты помимо битов выбора тактовой частоты (CSxx). Поэтому пример выше также сбросит и эти биты. В примере ниже показано, как этого можно избежать, что потребует дополнительной строки кода:
[Настройка таймеров]
В этой секции показаны конкретные примеры — как настроить три разные таймера. Дополнительная информация есть в даташитах и апноутах, приведенных в разделе «Ссылки», к ним следует в особенности обратиться в тех случаях, когда настройка таймера должна быть портирована на другие микроконтроллеры (примеры рассчитаны на AT90S8535). Для реагирования на события таймеров чаще всего используют прерывания, поэтому в примерах ниже задействованы прерывания.
Независимо от разных возможностей трех таймеров, у них у всех есть две общие черты. Таймер запускается на счет путем выбора источника тактирования, и если используются прерывания, то они должны быть разрешены.
Общие регистры. Если используются общие регистры в обработчике прерывания (ISR) и основном коде программы, то эти регистры должны быть предварительно сохранены в начале ISR, и восстановлены по окончании ISR. Если в приложении используются не все 32 регистра, то можно избежать процедуры сохранения и восстановления регистров путем использования разных регистров в основном коде программы и в ISR.
Очень важно помнить, что нужно сохранить регистр состояния (Status Register, SREG), потому что ISR это не делает автоматически.
Примечание: все вышеперечисленное касается использования языка ассемблера. Если используется язык C, то компилятор C все это делает автоматически.
[8-bit Timer0]
8-разрядный таймер Timer0 является синхронным таймером. Это означает, что он тактируется от системной тактовой частоты (возможно поделенной прескалером), или от внешней тактовой частоты (возможно также поделенной прескалером), которая все равно синхронизируется с системной тактовой частотой (подробнее см. раздел «Тактирование»). Этот таймер самый простой из всех трех. Для его запуска нужно выполнить только несколько установок.
Здесь будет показано, как Timer0 можно использовать для генерации Timer Overflow Interrupt. В коде ISR для примера будут переключаться выводы порта B. Чтобы это было видно, можно использовать плату разработчика STK500. В ней порт B может быть подключен к светодиодам 10-жильным ленточным кабелем. Светодиоды (LED) будут мигать с частотой fLED, которую можно вычислить по формуле:
У нашего 8-разрядного Timer0 величина MaxVal = 256, и системная тактовая частот CK = 3.69 МГц, поделенная прескалером на величину PVal = 1024, что приведет к частоте мерцания LED fLED примерно 7 Гц. Настройка показана в следующем примере кода:
Соответствующий код на C для компилятора IAR:
На следующем шаге должен быть написан код для ISR (подпрограмма — обработчик прерывания). Этот код будет выполняться каждый раз, когда таймер переполнится. В качестве примера ISR будет переключать в противоположное состояние ножки порта B (поэтому светодиоды LED будут мерцать).
Соответствующий код на C для компилятора IAR:
[16-bit Timer1]
16-разрядный Timer1 также является синхронным. Это означает, что он тактируется от системной тактовой частоты, поделенной прескалером системной тактовой частоты, или от внешних тактов (которые также могут быть поделены прескалером), которые синхронизируются с системной тактовой частотой. Чтобы гарантировать, что 16-разрядные регистры будут читаться и записываться одновременно (атомарной операцией), применяется специальная процедура с неявным задействованием промежуточного регистра (Temp). Во время выполнения этой процедуры доступ к регистрам должен выполняться в определенном, строго заданном порядке (подробнее см. AVR072 [2]). Корректный путь для доступа к регистрам показан в таблице 2.
Таблица 2. Доступ к 16-битным регистрам.
Операция | 1 доступ | 2 доступ |
Чтение | Младший байт | Старший байт |
Запись | Старший байт | Младший байт |
В соответствии с этими правилами, операция чтения 16-битного регистра будет выглядеть так:
Операция записи в этот регистр происходит в обратном порядке:
Компилятор C автоматически обрабатывает операции 16-битного ввода/вывода в нужном порядке.
Здесь показан очень простой пример использования события захвата по входу с обработкой по прерыванию. Вывод порта PD6 является входом захвата (input capture pin, ICP). Если логический уровень на этом выводе поменяется, то время между соседними положительными или отрицательными перепадами будет измерено системой захвата Timer1. 8 старших бит значения таймера будут записаны в порт B. Порт B может быть подключен к светодиодам платы разработчика STK500, а порт D подключен к кнопкам (с использованием двух 10-жильных ленточных кабелей). Это сделает возможным наблюдение значения таймера светодиодами LED, и использовать кнопки для подачи измеряемого сигнала на вход ICP.
В этом примере максимальное измеренное время может быть примерно 1 секундой (TOVCK = 1). Используйте формулу 3 для подбора нужного коэффициента деления прескалера. Для системной тактовой частоты CK = 3.69 МГц значение коэффициента деления прескалера определяется так:
Ближайшее к 56 выбираемое значение коэффициента деления PVal будет 64. Следующая подпрограмма инициализации показывает, как настроить такую систему:
Соответствующий код на C для компилятора IAR:
На следующем шаге должен быть написан код для ISR (подпрограмма — обработчик прерывания). Этот код будет выполняться каждый раз, когда произойдет событие захвата (input capture event). Назначение этого примера — вывести старший байт Timer1 в порт B (светодиоды LED). Потом таймер сбрасывается для подготовки следующего измерения.
Соответствующий код на C для компилятора IAR:
1. Инверсия битов нужна потому, что светодиоды в STK500 подключены к + питания, т. е. когда на выходе порта лог. 0, то светодиод горит, а когда лог. 1 — гаснет.
2. В этой реализации есть один недостаток: не обрабатывается переполнение таймера. Для того, чтобы этого избежать, можно использовать установку глобальной переменной в отдельном ISR для события переполнения таймера. Если эта переменная установлена, то в порт B должно быть записано значение 0xFF вместо значения из таймера.
[Асинхронный 8-bit Timer2]
Timer2 может использоваться в синхронном режиме, как Timer0 и Timer1. Дополнительно может использоваться асинхронный режим. Подробнее см. «Тактирование от асинхронного источника» в разделе «Тактирование».
Как и в предыдущем примере, порт B подключен к светодиодам LED и порт D подключен к переключателям платы STK500. Дополнительно кварцевый резонатор на 32.768 кГц (часовой кварц) подключен к выводам TOSC1/PC6 и TOSC2/PC7 порта C.
Настройки таймера могут быть вычислены по формуле 2. Вместо максимальной величины таймера MaxVal используется значение OCR2. Частота для подачи на вход тактирования прескалера (PCKx) в этом случае будет тактовым сигналом от часового кварца (fOSCCK), в то время как TOVCK будет использоваться в качестве тактового сигнала для события изменения уровня вывода с периодом 1 секунда. Математическое описание этого соотношения показано в следующей формуле:
Выбрано значение коэффициента деления прескалера 1024 и соответствующее значение 32 для OCR2, чтобы получить задержку 1 секуда между двумя событиями Timer compare match.
Следующая подпрограмма инициализации показывает, как настроить такую систему:
Соответствующий код на C для компилятора IAR:
На следующем шаге должен быть написан код для ISR (подпрограмма — обработчик прерывания). Этот код будет выполняться каждый раз, когда произойдет событие сравнения выхода (output compare event). Назначение этого примера — просто переключить в противоположное состояние биты порта B (они подключены к светодиодам LED для индикации события).
Соответствующий код на C для компилятора IAR:
[Базовые сведения о PWM]
PWM является аббревиатурой от Pulse Width Modulation (по-русски это Широтно-Импульсная Модуляция, или ШИМ). Это специальный режим который может быть сконфигурирован для таймеров Timer1 и Timer2. В этом режиме таймер работает как счетчик вверх и вниз. Это означает, что счетчик считает вверх до своего максимального значения, и затем считает вниз до нуля. Это контрастирует с обычным режимом счета, когда таймер переполняется и переходит в 0 после достижения своего максимального значения. Преимущество режима PWM в том, что изменение скважности ШИМ может быть реализовано с корректным сохранением фазы.
Если PWM сконфигурирован для переключения вывода Output Compare (OCx), то сигнал на этом выводе может выглядеть так, как показано на рис. 2.
Рис. 2. Выходной сигнал PWM.
VH: выходное напряжение лог. 1
VL: выходное напряжение лог. 0
VAV: средний уровень выходного напряжения (Average Output Voltage)
x: высокий уровень периода PWM
y: низкий уровень периода PWM
ФНЧ, подключенный к выходному выводу PWM, вместе с относительно высокой частотой выходного сигнала PWM приведет к постоянному среднему уровню на выходе вместо прямоугольных импульсов. Формула 4 показывает, как можно вычислить уровень этого среднего напряжения:
(VH * x + VL * y) VAV = ——————- (x + y) | (Формула 4) |
y = (MaxVal — OCRx) * 2
(VH * OCRx + VL * (MaxVal — OCRx)) VAV = —————————————— MaxVal | (Формула 5) |
Фактически этот метод позволяет таймеру генерировать уровни напряжения между напряжением питания VCC и нулевым общим проводом GND — получится цифро-аналоговый преобразователь (DAC), реализованный на основе PWM. Подробнее, как это делается, описано в аптноутах AVR314 [4] и AVR335 [5].
Этот пример показывает, как генерировать напряжения между VCC и GND с помощью сигнала PWM (PD7/OC2). Чтобы увидеть результаты регулирования, порт D должен быть подключен к светодиодам с помощью 10-жильного плоского кабеля.
Порт D сконфигурирован так, что светодиоды, подключенные к младшей четверке битов порта будут включаться, а светодиоды, подключены к старшей четверке битов порта, выключаться. Только светодиод на выводе PD7 / OC2 не будет выключаться, у него будет меняться яркость, потому что скважность сигнала PWM будет меняться от 1/8 до 7/8 (OCR2 = 0xE0).
Примечание: соотношение скважность в этой конфигурации проинвертировано потому, что светодиоды на плате STK500 подключены к + питания.
Соответствующий код на C для компилятора IAR:
Источник
Частота тактирования таймера счетчика
8-разрядный таймер-счетчик 0 с функциями широтно-импульсной модуляции и асинхронного тактирования
Таймер-счетчик 0 — модуль многофункционального одноканального 8-разрядного таймера-счетчика с аппаратным выходом для генерации ШИМ-сигнала и встроенным асинхронным опциональным тактовым генератором, который оптимизирован под использование часового кварца (32768Гц) для асинхронного по отношению к системной синхронизации тактирования.
Основные отличительные особенности:
- Одноканальный счетчик
- Опциональный режим сброса таймера при совпадении (автоматическая перезагрузка)
- Широтно-импульсная модуляция без генерации ложных импульсов при записи нового порога сравнения в OCR0 (двойная буферизация) и с фазовой коррекцией
- Генератор частоты
- 10-разрядный предделитель тактовой частоты
- Генерация прерываний по переполнению и выполнения условия сравнения (TOV0 и OCF0)
- Возможность асинхронного тактирования совместно с внешним кварцевым резонатором частотой 32 кГц независимо от частоты синхронизации ввода-вывода
Укрупненная функциональная схема 8-разр. таймера-счетчика представлена на рис. 34. Для уточнения расположения выводов см. «Расположение выводов». Связи с регистрами, к которым осуществляет доступ ЦПУ, в т.ч. биты ввода-вывода и линии ввода-вывода показаны жирной линией. Специфические для данного устройства регистры, расположение и назначение его бит приведены в «Описание регистров 8-разр. таймера-счетчика 0».
Рисунок 34. Функциональная схема 8-разр. таймера-счетчика
Регистр таймера-счетчика (TCNT0) и регистр порога сравнения (OCR0) — 8-разр. регистры. Сигналы запроса на прерывание представлены как флаги прерываний таймера в регистре TIFR. Все прерывания индивидуально маскируются с помощью регистра маски прерываний таймеров (TIMSK). Регистры TIFR и TIMSK не представлены на функциональной схеме, т.к. они совместно используются с другими таймерами микроконтроллера.
Таймер-счетчик может тактироваться через предделитель внутренне или асинхронно через внешние выводы TOSC1/2, что описано в последующих разделах. Асинхронная работа управляется регистром асинхронного состояния (ASSR). Блок синхронизации осуществляет выбор, какой тактовый источник используется для инкрементирования (декрементирования) состояния таймера-счетчика. Если источник тактирования не задан, то таймер-счетчик находится в неактивном состоянии. Выход логики выбора синхронизации обозначен как синхронизация таймера (clkT0).
Значение регистра порога сравнения с двойной буферизацией (OCR0) непрерывно сравнивается со значением таймера-счетчика. Результат сравнения может использоваться для генерации сигналов с ШИМ или прямоугольных импульсов переменной частоты на выводе OC0. См. «Блок сравнения». Совпадение порога сравнения со значением таймера-счетчика приводит к установке флага результата сравнения (OCF0), который может использоваться для генерации запроса на прерывание по результату сравнения.
Некоторые определения и их сокращенные наименования, которые интенсивно используются в этом разделе, представлены в таблице 51.
Таблица 51. Определения
НП (нижний предел) | Счетчик достигает нулевого значения (0х00) |
МАКС (максимальное значение) | Счетчик достигает максимального значения 0xFF (десятич. 255) |
ВП (верхний предел) | Счетчик достигает верхнего предела счета (вершина счета). В качестве вершины счета может выступать фиксированное значение 0xFF или содержимое регистра OCR0. |
Тактовые источники таймера-счетчика 0
Таймер-счетчик 0 может тактироваться внутренне синхронно или внешне асинхронно (по отношению к внутренней системной синхронизации). По умолчанию используется тактовый сигнал clkT0, эквивалентный тактовому сигналу микроконтроллера clkI/O. Если в бит AS0 регистра ASSR записать лог. 1, то в качестве источника синхронизации выступает генератор таймера-счетчика, связанный с выводами подключения низкочастотного кварцевого резонатора TOSC1 и TOSC2. Более подробно асинхронная работа описана в «Регистр асинхронного состояния — ASSR». Подробности по источникам синхронизации см. в разделе «Предделитель таймера-счетчика 0».
Основу 8-разр. таймера-счетчика 0 составляет программируемый двунаправленный счетчик. Рисунок 35 показывает функциональную схему счетчика и окружающих его элементов.
Рисунок 35. Функциональная схема счетчика
Описание сигналов (внутренние сигналы):
- Счет — Инкрементирует или декрементирует TCNT0 на 1.
- Направление — Задает направление счета: инкрементирование (+1, прямой счет) или декрементирование (-1, обратный счет).
- Сброс — Сбрасывает содержимое TCNT0 (запись лог. 0 во все разряды).
- clkT0 — Синхронизация таймера-счетчика.
- Верхний предел — Задает максимальное значение, которое может достигнуть TCNT0.
- Нижний предел — Задает минимальное значение, которое может достигнуть TCNT0 (ноль).
В зависимости от выбранного режима работы счетчик сбрасывается, инкрементируется или декрементируется на каждом такте синхронизации (clkT0). Тактовый сигнал clkT0 может быть внутренним или внешним, а его частота выбирается с помощью бит выбора частоты синхронизации CS02-CS00. Если источник синхронизации не задан (CS02-CS00 = 0b000), то таймер останавливается. Однако состояние TCNT0 доступно ЦПУ независимо от того работает синхронизация таймера или нет. Запись в регистр таймера через ЦПУ перекрывает любые действия самого счетчика: сброс или счет, т.е. имеет более высокий приоритет.
Последовательность счета определяется установкой бит WGM01 и WGM00, расположенных в регистре управления таймером-счетчиком (TCCR0). Имеется точная связь между поведением счетчика (алгоритмом счета) и генерируемой на выходе OC0 формы сигнала. Более подробно об алгоритмах счета и генерации импульсов написано в «Режимы работы».
Флаг переполнения таймера-счетчика (TOV0) устанавливается в соответствии с режимом работы, который выбирается битами WGM01, WGM00. Бит TOV0 может использоваться для генерации прерывания ЦПУ.
8-разрядный цифровой компаратор непрерывно выполняет сравнение содержимого регистра таймера-счетчика TCNT0 с регистром порога сравнения OCR0. Всякий раз, когда значение TCNT0 совпадает со значением OCR0 компаратор устанавливает флаг совпадения OCF0 следующим тактом синхронизации таймера. Если разрешено прерывание битом OCIE0 = 1, то установка флага совпадения вызывает запрос на прерывание. Флаг OCF0 автоматически сбрасывается во время выполнения процедуры обработки прерывания. Альтернативно, флаг OCF0 можно сбросить программно путем записи лог. 1 в позицию данного бита. Генератор сигнала использует сигнал результата сравнения для генерации прямоугольных импульсов по одному из алгоритмов, который выбирается битами задания режима работы таймера WGM01, WGM00 и битами задания режима формирования выходного сигнала (COM01, COM00). Верхний и нижний пределы счета используются в некоторых режимах работы для выполнения специальных действий (см. «Режимы работы таймера -счетчика 0»). На рисунке 36 приведена функциональная схема блока сравнения.
Рисунок 36. Функциональная схема блока сравнения
Регистр OCR0 выполнен по схеме двойной буферизации при использовании режимов с широтно-импульсной модуляцией (ШИМ). В нормальном режиме и режиме сброса таймера при совпадении (CTC) схема двойной буферизации отключается. Двойная буферизация позволяет синхронизировать обновление регистра сравнения OCR0 по достижении верхнего или нижнего предела счета. Такая синхронизация предотвращает возможность возникновения несимметричных ШИМ-импульсов нечетной длины, тем самым гарантируя отсутствие сбоев при генерации прямоугольных импульсов.
Доступ к регистру OCR0 может показаться сложным, но это выполнено не случайно. После разрешения двойной буферизации ЦПУ осуществляет доступ к буферному регистру OCR0, а после отключения — непосредственно адресуется к регистру OCR0.
Принудительная установка результата сравнения
В режимах генерации импульсов без ШИМ в формирователе импульсов результат сравнения может быть установлен непосредственно через бит принудительной установки результата сравнения FOC0. Принудительная установка результата сравнения компаратора не приводит к установке флага OCF0 или сбросу/перезагрузке таймера, но влияет на состояние вывода OC0, который будет устанавливаться, сбрасываться или переключаться (инвертироваться) в зависимости от выбранной установки бит COM01, COM00.
Результат сравнения блокируется записью в TCNT0
Если ЦПУ осуществляет запись в регистр TCNT0, то результат сравнения будет игнорироваться на следующем такте синхронизации таймера, даже если таймер остановлен. Данная функция позволяет установить в регистре OCR0 то же значение, что и в TCNT0 без генерации запроса на прерывание, если разрешено тактирование таймера-счетчика.
Использование блока сравнения
Поскольку запись в TCNT0 блокирует любые действия по результату сравнения на один такт синхронизации таймера независимо от режима работы, то при изменении TCNT0 при использовании канала сравнения (независимо работает синхронизация таймера или нет) необходимо учесть следующие особенности. Если в регистр TCNT0 записано значение равное OCR0, то игнорирование совпадения приведет к генерации некорректной формы сигнала. По аналогии следует избегать записи в TCNT0 значения равного нижнему пределу (0x00), если счетчик работает как вычитающий.
Установка OC0 должна быть выполнена перед настройкой линии ввода-вывода на вывод в регистре направления данных. Самый легкий путь установки значения OC0 — использование бита принудительной установки результата сравнения (FOC0) в нормальном режиме. Регистр OC0 сохраняет его значение, даже если происходит изменение режима работы таймера.
Учтите, что биты COM01, COM00 не содержат схемы двойной буферизации и на любые изменения реагируют мгновенно.
Источник
Таймеры-счетчики
Таймером называется средство микропроцессора, служащее для измерения времени и реализации задержек. Основой таймера служит суммирующий счетчик, который считает количество импульсов генератора тактовой частоты. Для таймера могут быть указаны:
- разрядость таймера;
- коэффициент предварительного деления;
- диапазон изменения счетного регистра;
- режим работы.
Разрядность таймера представляет собой разрядность двоичного счетчика, используемого для его реализации и определяет верхнюю допустимую границу счетного регистра. Например, для 8-разрядного таймера верхняя граница счетного регистра будет 2 8 -1 = 255.
Предварительный делитель – делитель частоты тактового сигнала, работающий как один или несколько последовательно соединенных T-триггеров. Таймер изменяет свое значение на 1 каждые n сигналов тактового импульса. n называют коэффициентом предварительного деления .
Зная частоту тактового генератора fosc и коэффициент предварительного деления Kpre, легко определить частоту таймера по формуле:
Время одного тика таймера соответственно будет
Полное время счета таймера (время перебора всех допустимых значений двоичного счетчика) определится как
Например, если требуется реализовать задержку 1с на 8-разрядном таймере с коэффициентом предварительного деления Kpre=1 и тактовой частотой fosc=8 МГц, имеем
tic = 0,125 мкс;
Tcount = 0,125*2 8 = 32 мкс
1с/32мкс = 31250 повторений
Широтно-импульсная модуляция
Широтно-импульсная модуляция (ШИМ) – импульсный сигнал постоянной частоты и переменной скважности.
Скважность есть отношения периода следования импульса к длительности импульса.
С помощью задания скважности (длительности импульсов) можно менять среднее напряжение на выходе ШИМ.
Обратная величина, то есть отношение длительности импульса к периоду, называется коэффициентом заполнения .
Разрядностью ШИМ называется разрядность таймера, используемого для формирования ШИМ-сигнала.
Существуют два основных режима работы ШИМ:
Быстрый ШИМ
Период ШИМ определяется максимальным значением, до которого считает счетчик. В этот момент ШИМ-сигнал устанавливается в «1». При достижении счетчиком значения, поданного на второй вход цифрового компаратора, осуществляется сброс выходного ШИМ-сигнала.
Фазовый ШИМ
В данном режиме счетчик работает как суммирующий и считает от 0 до максимального значения, а при достижении максимального значения работает как вычитающий, считая до 0.
При совпадении значения счетчика с некоторым установленным значением, происходит переключение выхода ШИМ.
Частотно-импульсная модуляция — сигнал переменной частоты и постоянной скважности, равной 2. При таком виде модуляции изменяется период сигнала, а длительность импульса всегда составляет половину периода.
Источник