Использование таймера в Xmega

    Данное семейство содержит два 16-битных таймеров-счетчиков с четырьмя каналами захвата/сравнения в первом и двумя каналами захвата/сравнения во втором. Все каналы имеют двойную буферизацию. Таймеры-счетчики позволяют реализовать генерацию: прямоугольных импульсов, широтно-импульсную модуляцию с одно- и двунаправленным счетом и частотных импульсов. Входной 32-битный захват имеет возможности шумоподавления, захвата частоты и длительности импульсов. Таймеры имеют возможности генерации событий/прерываний по переполнению, по совпадению или захвату и по ошибке. Также имеет возможность использовать поддержку DMA. Для реализации более сложных и специализированных генераторов импульсов предусмотрена возможность совместной работы таймеров-счетчиков с блоками расширения разрешающей способности (Hi-Res) с возможностью увеличения разрешающей способности на 2 бита (в 4 раза) и расширения возможностей генерации импульсов (AWeX) включающих в себя: 4 блока генерации мертвого времени (DT) с отдельными настройками для включения и отключения сигнала, событие контролирующие защиту от повреждения, одноканальная работа с несколькими выходами и образцовый генератор.
    Таймер-счетчик состоит из основного счетчика и нескольких каналов сравнения или захвата (CC-каналов). Основной счетчик может использоваться для счета импульсов синхронизации или событий. Предусмотрена возможность задания направления и периода счета. CC-каналы могут использоваться для реализации функций управления по условию совпадения счетчика с заданным значением, для генерации импульсов (частота или ШИМ) или для измерения параметров импульсного сигнала.
    Функции захвата и сравнения нельзя выполнять одновременно, т.е. таймер-счетчик не может одновременно выполнять и генерацию, и захват импульсов. Когда CC-канал используется для выполнения операций сравнения, его называют каналом сравнения. Если же CC-канал используется для захвата, то его называют каналом захвата.
    Таймер-счетчик может быть в двух исполнениях: таймер-счетчик 0, который содержит четыре CC-канала, и таймер-счетчик 1 с двумя CC-каналами. Таким образом, упоминаемые далее регистры и биты регистров CC-каналов 3 и 4 имеются только у таймера-счетчика 0. Блок AWeX доступен только у таймера-счетчика 0, а блок Hi-Res имеется у всех таймеров-счетчиков.
BOTTOM - Счетчик достиг нижней границы счета, когда он становится равным нулю
MAX -  Счетчик достиг максимального значения, когда все его биты равны единице (0xFFFF)
TOP -  Счетчик достиг верхней границы счета, когда он становится равным наибольшему значению счетной последовательности. Значение TOP может быть равно периоду (PER) или значению регистра сравнения канала А (CCA) в зависимости от настройки режима генерации импульсов (WGM)
UPDATE - Таймер-счетчик сигнализирует об обновлении, когда он достигает значения BOTTOM или TOP, в зависимости от выбранного режима генерации импульсов (WGM)
Модуль таймеров-счетчиков XMega A имеет 16-битные таймеры-счетчики с функциями захвата/сравнения с опциональными выходами на ножки ввода/вывода. Типичные применения модуля:
- синхронизация;
- периодическая генерация прерываний/событий;
- широтно-импульсная модуляция;
- событие счета;
- событие временных остановок;
- измерение параметров сигнала (период, длительность цикла и т.д.).
    Варианты таймера-счетчика
    Модуль таймера-счетчика (ТС) XMega A связан с портом ввода/вывода через ножки ввода/вывода, что позволяет управлять выходами сравнения. У каждого модуля TC есть имя, которое следует за формой: TCxn. ТС – обозначает таймер-счетчик, x – обозначает порт с которым связан данный ТС, а n – номер ТС порта PORTx. Например, TCD0 – таймер-счетчик 0 связанный с портом D.
    Таймеры доступны на портах C, D, E и F, при наличии их в процессоре.
    Таймер 0 в каждом порту имеет по 4 канала захвата/сравнения, а таймер 1 имеет 2 канала. На рис.1 показана связь каналов ТС с портами ввода/вывода. Таймер 0 соединяется с ножками 0-4 портов, а таймер 1 с ножками 4 и 5.
Рис.1. Соединение выходов сравнения с портами ввода/вывода
Таблица 1. Источники тактирования
Прерывания
Прерывания могут быть сгенерированы в следующих ситуациях:
- переполнение таймера;
- ошибка таймера (входные данные по захвату теряются т.к. буфер ввода захвата переполнен);
- захват или сравнения. Отдельные прерывания по каждому каналу.
Настройка периода
У каждого модуля TC есть регистр периода (PER[H:L]), в которое записывается верхнее значение (TOP) счетчика (кроме режима генерации частоты).
PER[H:L] является регистром двойной буферизации через регистр PERBUF[H:L].
Регистр PER[H:L] автоматически приравнивается 0xFFFF после сброса.
Каналы захвата/сравнения
    Каждый модуль имеет 2 или 4 канала захвата/сравнения. Каналы могут быть настроены или на захват или на сравнение. Вход захвата может быть использован для измерения времени, измерение параметров сигнала таких как частота или длительность цикла. Функция сравнения может быть использована для генерации прерывания и событий в определенные моменты времени или для генерации ШИМ.
    Каналы захвата/сравнения состоят из 16-битных регистров с именем CCx[H:L], где х – имя канала. У таймера 0, с 4 каналами, есть CCA[H:L], CCB[H:L], CCC[H:L] и CCD[H:L], в то время как у таймера 1 только CCA[H:L] и CCB[H:L]. Кроме того, у каждого CCx[H:L] регистра есть буферный регистр CCxBUF[H:L].
    Когда модуль используется для входного захвата значение регистра PER определяет как интерпретируются входные значения захвата. Если установлен 15 бит регистра PER, то полное значение 16-битного счетчика хранятся в буфере захвата. Если же бит 15 регистра PER равен 0, то в 15 бите буфера захвата хранится полярность события. Это может применяться при измерении частоты и длительности цикла, используя только одну входную ножку и один канал захвата.
    Выбор входного события
    При использовании ТС как вход захвата, все включенные входные каналы захвата должны быть связаны с каналом событий. Биты EVSEL[3:0] находящиеся в регистре CTRLD выбирают каналы событий, которые связаны с входными каналами захвата. EVSEL3 должен быть равен 1, чтобы выбрать источник событий. EVSEL [2:0] выбирается между 8 каналами событий.
    Каналы событий, связанные с различными каналами, не могут быть выбраны индивидуально. Таблица 2 показывает картографию между глобальными каналами событий и входными каналами захвата, когда EVSEL3 = 1 и EVSEL [2:0] = N. “%” - оператор модуля. Отметим, что, когда каналы событий были выбраны для TC, это не означает, что эти каналы событий используются только для TC. TC просто "слушает" выбранные каналы и может получить события из этих каналов событий.
Таблица 2. Карта каналов событий входов канала захвата
Пример 1:
EVSEL3 = 1 и EVSEL [2:0] = 0 режим когда входные каналы захвата A, B, C и D, срабатывают по каналам событий 0, 1, 2 и 3 соответственно.
Пример 2:
EVSEL3 = 1 и EVSEL [2:0] = 6 режим когда входные каналы захвата A, B, C и D, срабатывают по каналам событий 6, 7, 0 и 1 соответственно.
     Если источник событий подвергается шуму, например, вызванному внешним переключением, возможно применение цифрового фильтрования канала событий.
    Регистры двойной буферизации
    Регистры PER[H:L] и CCx[H:L] в модулях TC имеют двойную буферизацию. Они связаны с буферными регистрами под названием PERBUF[H:L] и CCxBUF[H:L].
    При записи непосредственно в регистр PER[H:L], значение будет немедленно обновлено. Если же значение будет записано в PERBUF[H:L], то значение PER[H:L] не будет обновлено немедленно, но вместо этого будет передано из PERBUF[H:L] при следующем обновлении (UPDATE). У каждого буферного регистра есть связанный с ним флаг “действия буфера” в регистре CTRLE. Флаг действия буфера установлен, когда новое значение записано в соответствующий буферный регистр. Флаг очищен, когда буферный регистр скопирован в регистр его предназначения. Это гарантирует, что копируются только новые значения.
    Также возможно захватить автоматическое обновление от буферных регистров. Это позволяет одновременные обновления нескольких регистров при одном условии обновления. Установление бита обновления захвата таймера (LUPD) в регистре CTRLE позволяет захват обновления.
    Когда модуль TC используется для ШИМ, буферирование обычно используется, чтобы удостовериться, что рабочие циклы не изменены в середине периода ШИМ, и синхронизировать изменение всех каналов ШИМ. Новое значение сравнения/TOP, как правило записывается в буферные регистры вместо того, чтобы записать непосредственно в регистры CCx. Аналогично, все каналы ШИМ могут быть обновлены в то же время (по событию UPDATE).
    В режиме входного захвата, значения с входа захвата буферизируются. Новое значение захвата, с входа, вначале помещается в регистр CCxBUF[H:L]. Значения хранящиеся в CCxBUF[H:L], переданы CCx[H:L], если флаг CCIFx не установлен. Флаг CCIFx очищен автоматически, когда CCx[H:L] прочитан. Практически, это означает, что пользователь должен только считать регистр CCx[H:L], в то время как остальное обрабатывается автоматически.
    Режимы работы
ТС имеет 6 режимов работы:
- нормальный режим;
- режим генерации частоты;
- односторонняя ШИМ;
- двусторонняя ШИМ с переполнением на TOP;
- двусторонняя ШИМ с переполнением на TOP и BOTTOM;
- двусторонняя ШИМ с переполнением на BOTTOM.
    Нормальный режим
    В нормальном режиме счет идет в направлении установленном битом DIR в регистре CTRLF до тех пор, пока он не достигнет значение TOP установленного в PER[H:L] или BOTTOM (нуля). Когда TOP достигнут, значение счетчика сбрасывается в ноль при следующем цикле тактирования. Если счетчик ТС уменьшающийся, то значение заново пойдет со значения в регистре PER[H:L] по достижению BOTTOM.
Рис. 2. Нормальный режим с установленным периодом
    Как показано на рис. 2, допустимо изменять значение счетчика в процессе работы. Запись имеет более высокий приоритет, чем счет, очищение или перезапуск и осуществляется немедленно. Однако, если записанное значение выходит за границу BOTTOM-TOP, счетчик должен или уменьшатся пока не достигнет значения TOP или увеличиваться до его достижения (миную MAX) для восстановления периода.
    Этот режим работы должен применяться при использовании ТС как захват входа.
    Режим генерации частоты
    Есть небольшое различие между режимами генерации частоты (FRQ) и нормальным режимом работы. Для FRQ периодом (T) управляет регистр CCA[H:L] вместо PER[H:L], который в этом случае не используется. Кроме того, выход генерации сигнала (WG), переключается при каждом равенстве CNT[H:L] и CCA[H:L], как показано в рис.3.
Рис.3. Режим генерации частоты
    Генерация сигнала имеет максимальную частоту fclk/2 когда значение CCA[H:L] равно нулю. Частота сигнала определена формулой:
fFRQ=fclk/2N(CCA+1)
Где N является делителем частоты ТС.
    Флаг статуса переполнения (OVFIF) или флаг сравнения по каналу А (CCAIF) может быть использован для генерации прерываний. Программа обработки прерываний может быть использована для обновления CCA[H:L] и изменения выходной частоты.
    Режим односторонней ШИМ
    На рис.4 показан режим работы счетчика от BOTTOM до TOP, где сбрасывается в BOTTOM. Выход генератора сигналов устанавливается в единицу при равенстве счетчика регистру сравнения (CCx) и сбрасывается по достижению счетчиком значения TOP.

Рис.4. Режим односторонней ШИМ
    Односторонний ШИМ обеспечивает частоту ШИМ вдвое большую чем двухсторонняя ШИМ. Высока частота ШИМ делает этот режим пригодным для применения в областях регулирования энергии, выпрямления и ЦАП. Высокая частота позволяет физически уменьшить размер внешних компонентов фильтра, которая уменьшит общую системную стоимость.
    Регистр периода (PER[H:L]) определяет разрешение ШИМ. Минимальное разрешение допустимое для этого модуля является 2-битовым (PER[H:L]=0x0003), а максимальное – 16-битовым (PER[H:L]=MAX). Для точного вычисления разрешения односторонний ШИМ может быть использована следующая формула:

RPWM_SS=log2(PER+1)
Базовая частота ШИМ зависит от установленного периода PER[H:L], системной частоты и делителя частоты. Базовая частота ШИМ может быть вычислена по формуле:

fPWM_SS=fclk/N(PER+1)
Где N отображает делитель частоты ТС.
   Флаг статуса переполнения (OVFIF) или флаг сравнения (CCxIF) может быть использован для генерации прерываний. Программа обработки прерываний может быть использована для обновления периода и значений буфера сравнения.
    Режим двухсторонний ШИМ
    Работа счетчика двухсторонний ШИМ показана на рис.5. Счетчик неоднократно считает от BOTTOM до TOP и затем обратно до BOTTOM. При достижения счетчиком BOTTOM или TOP он моментально меняет направление счета. Текущее направление счетчика можно определить по флагу DIR в регистре CTRLF.
    Выход генерации сигнала (WG) переключается при достижении счетчиком значения BOTTOM или значения регистра сравнения (CCx). Рабочий цикл выходного сигнала пропорционален значению сравнения.
Рис.5. Двухсторонняя ШИМ
    Результирующая операционная частота двухсторонний ШИМ ниже чем у односторонней ШИМ.
    Регистр периода (PER[H:L]) определяет разрешение ШИМ. Минимальное разрешение допустимое для этого модуля является 2-битовым (PER[H:L]=0x0003), а максимальное – 16-битовым (PER[H:L]= 0xFFFF). Для точного вычисления разрешения двухсторонней ШИМ может быть использована следующая формула:
RPWM_DS=log2(PER+1)
    Базовая частота ШИМ зависит от установленного периода PER[H:L], системной частоты и делителя частоты. Базовая частота ШИМ может быть вычислена по формуле:
fPWM_DS=fclk/2N(PER+1)
Где N отображает делитель частоты ТС.
    Флаг статуса переполнения (OVFIF) или флаг сравнения (CCxIF) может быть использован для генерации прерываний. Программа обработки прерываний может быть использована для обновления периода и значений буфера сравнения.
    Команды таймера-счетчика
    Биты CMD[1:0] в CTRLFSET используются для применения следующих специальных команд к TC:
     - Принудительное обновление (UPDATE). Команда принудительного обновления используется для вызова условия UPDATE. Пи вызове UPDATE буферные регистры копируются в их регистры предназначения. Команда UPDATE вызывается независимо от направления счетчика. Команда может использоваться для одновременного обновления периода и сравнения регистров. В режиме захвата входа, команда принудительно обновления имеет эффект только на регистры PERBUF/PER.
     - Принудительный перезапуск. Команда принудительного перезапуска очищает регистры CNT[H:L] и сбрасывает бит направления счета.
     - Принудительная перезагрузка. Команда принудительной перезагрузки сбрасывает в начальное состояние все регистры ТС.
    Использование двух 16-битных таймеров-счетчиков как один 32-битный
    Существует возможность использовать систему событий для каскадирования двух 16-битных ТС в один 32-битный ТС с функциями 32-битного входа захвата.
    Режим каскадирования двух 16-битных ТС
    Любой из модулей ТС может быть выбран в качестве тактирования каналов событий. Для получения каскадирования двух 16-битных ТС, событие по переполнению от младшего слова ТС должно быть включено в систему событий и использоваться для тактирования старшего слова ТС. На рис.6 показано как используется TCC0 в качестве младшего слова и TCC1 как старшего слова через канал событий 0. Канал событий 0 настраивается через регистр EVSYS.CH0MUX, для использования переполнения по TCC0 в качестве источника событий. Биты CLKSEL в TCC1.CTRLA настраиваются на использование канала событий 0 в качестве источника тактирования. Результат в том, что TCC1 увеличивается на единицу при каждом переполнении TCC0. Это и создает 32-битовый TC. Отметим, что таким способом могут быть каскадированы любые два модуля TC
Рис. 6. Каскадирование двух 16-битных модулей ТС
    Доступ к 32-битому значению
    При чтении каскадируемого ТС, 32-битное значение должны быть вручную получены от двух 16-битовых частей. Однако, здесь нет никакого временного регистра для 32-битного значения счетчика, младшее и старшее слово не могут быт прочитаны за один такт. Младшее слово TC может переполниться сразу после прочтения. Это привело бы к неправильной прочитанному значению, так как переполнение младшего слова увеличивает значение старшего на 1. Один из способов избежать этого состоит в том, чтобы остановить младшее слово TC, при чтении 32-битого значения счетчика. Если остановка TC не возможна, лучшим решением является использование 32-битного входного захвата.
    Те же проблемы могут произойти, при записи нового значения в каскад TC. Самый безопасный способ записать новое 32-битное значение состоит в том, чтобы остановить TC, записать значение и запустить TC снова.
    Использование 32-битного входа захвата
    32-битный ТС может быть настроен на выполнение 32-битный входной захват. Оба ТС настраиваются для входного захвата, с теми же самыми каналами событий как и источники захвата. Однако, существует задержка в один такт связанная с распространением бита переполнения от младшего слова TC к старшему. Это означает, что необходимо задержать событие по высокому слову TC, чтобы гарантировать правильность входного значения захвата. Чтобы задержать событие, бит EVDLY в регистре CTRLD должен быть установлен.
    Возможно использовать регистр EVSYS.STROBE в системе событий, чтобы вручную вызвать событие на любом из доступных каналов событий. Это может быть использовано в качестве альтернативы чтению TC непосредственно программным путем.
    Покажем, как настроить ТС на различные режимы работы.
    Основной настройки ТС
    Задача: Настройте ТС для использования в качестве регулярного таймера.
    1. Записать в регистр PER[H:L] значение, являющееся периодом/TOP ТС. Т.е. устанавливаем значение, где ТС сбрасывается в ноль и где ТС генерирует прерывание/событие по переполнению.
    2. Задать источник тактирования ТС битами CLKSEL в регистре CTRLA.
    В этом режиме текущее значение счетчика может быт считано из регистра CNT[H:L]. Бит переполнения TC указывает, на то что переполнение произошло. Этот бит может использоваться, для генерации прерываний с фиксированными интервалами.
    Использование функций входного захвата
    Задача: Настроить таймер TCC0 на входной захват по каналу A. Входной захват срабатывает по заднему (падающему) фронту ножки PC0.
    3. Настройте ножку PC0 как выход, защелкивающейся по заднему (падающему) фронту.
    4. Выберите PC0 как вход мультиплексора для канала событий 0.
    5. Настройте TCC0 на входной захват, установив источник событий и действие по событию “Входной захват (Input capture)” в регистре CTRLD.
    6. Разрешите работу входного захвата по каналу А, установив бит CCAEN в регистре CTRLB.
    7. Запустите TC, выбрав источник тактирования (CLKSEL в CTRLA).
    8. Ожидайте установки флага прерывания по входному захвату канала А в регистре INTFLAGS.
    9. Прочитайте захваченное значение в регистре CCA[H:L].
    10. И так далее с пункта 6.
    Использование входного захвата для вычисления частоты и рабочего цикла сигнала
    Задача: Настроить таймер ТСС0 на измерение частоты и рабочего цикла сигнала поступающего на ножку PC0.
    1. Выберите источник(и) событий. См. «Выбор входного события» этого урока.
    2. Выберите действие по событию = входной захват (input capture).
    3. Разрешите захват по входным каналам (CCENx).
    4. Установите регистр PER[H:L] равным 0x7FFF (старший бит должен быть очищен),
    5. Запустите TC с выбранным режимом тактирования (clock).
    6. Ожидайте установки флага прерывания по входному захвату канала А в регистре INTFLAGS.
    7. Прочитайте захваченное значение в регистре CCA[H:L] для ‘этого захвата’.
    8. Проверьте 15 бит ‘этого захвата’.
    9. Если бит 15 из ‘этого захвата’ установлен, то
    Запишите ‘этот захват’ как ‘задний фронт’
    10. иначе Вычислите полный период.
    Использование ТС как ШИМ генератор
    Задача: Настроить TCC0 на вывод ШИМ с переменным рабочим циклом по каналу А.
    1. Настройте ножку PC0 на выход, установив бит 0 в PORTC.DIR.
    2. Выберите период таймера, установив регистр PER[H:L].
    3. Выберите режим генерации сигнала формы волны, установив биты WGMODE[2:0] в регистре CTRLB в режим PWM.
    4. Разрешите захват по каналу А, установив бит CCAEN в регистре CTRLB.
    5. Запустите TC, выбирая источник тактирования (clock) битами CLKSEL[3:0] в регистре CTRLA.
    6. Вычислите желаемое значения сравнения.
    7. Запишите новое значение для сравнения в регистр с CCA[H:L].
    8. Ожидайте установки флага переполнения OVFIF в регистре INTFLAGS.
    9. Очистите флаг переполнения TC.
    10. И так далее с пункта 6.
    Используя этот способ, сравниваемое значение обновляется единожды каждый период ШИМ.
    Использование счетчика событий
    Задание: Настроить TCC0 на счет числа переключений сигнала на ножке используя канал событий 0. Сгенерировать прерывание на ножке PC1 после 5 нажатий клавиши.
    1. Настройте ножку PC0 как вход, отслеживающий задний фонт.
    2. Настройте ножку PC1 как выход.
    3. Выберите PC0 как вход мультиплексора для канала событий 0.
    4. Разрешить фильтрацию по каналу событий 0.
    5. Установите период TCC0 равным 4 (чтобы сгенерировать прерывание по переполнению после 5 переключения).
    6. Разрешить прерывание низкого уровня (low level) по переполнению TCC0.
    7. Выберите канал событий 0 как источник тактирования для TC.
    Прерывание по переполнению в TCC0 переключает PC1.
    При такой настройке, регистр CNT[H:L] будет содержать число переключений (нажатий) поступающих на ножку PC0. После 5 нажатий сработает программа обработки прерываний по переполнению, переключающая PC1, в то время как CNT[H:L] сбрасывается в 0.
    Настройка 32-битного ТС с входным захватом
    Задача: Настройте таймеры TCC0 и TCC1 как один 32-битный TC с входным захватом по каналу А и срабатыванием по заднему (падающему) фронту на ножке PC0. Канал событий 0 используется для переноса переполнения, пока входной сигнал захвата от PC0 переходит на канал событий 1.
    1. Настройте PC0 как вход, срабатывающий по заднему фронту.
    2. Настройте PC0 как вход мультиплексора для канала событий 1.
    3. Настройте переполнение по TCC0 как вход мультиплексора для канала событий 0.
    4. Настройте TCC0 и TCC1 как входной захват со срабатыванием по каналу событий 1.
    5. Разрешите задержку события TCC1 (это задержит событие по захвату входа на один цикл, чтобы позволить переполнению от TCC0 перейти к TCC1 прежде, чем произойдет входной захват).
    6. Разрешить входной захват по каналу А на TCC0 и TCC1.
    7. Выберите канал событий 0 как источник тактирования для TCC1 битами CLKSEL в регистре CTRLA.
    8. Запустите TCC0, выбрав системные часы как источник тактирования битами CLKSEL в регистре CTRLA.
    9. Ожидайте установки в регистре INTFLAGS флага прерывания А входного захвата TCC0 или TCC1.
    10. Прочитайте значение младшего слова входного захвата в регистре TCC0.CCA[H:L].
    11. Прочитайте значение старшего слова входного захвата в регистре TCC1.CCA[H:L].
    12. Объедините младшее и старшее слова в 32-битное значение входного захвата.
    13. И так далее с пункта 9.
    И на последок парочку простейших примеров использования таймера, для того чтобы помочь начать практическую работу.
    Пример 1.
    Задача: Написать программу с переключением ножки PA0 с частой 1 мс (на данной ножке получим частоту 500Гц) с использованием прерываний по таймеру, что может быть полезно для проверки правильности настройки таймеров и применения с четким отслеживанием временных параметров.
    Будем использовать внешний кварцевый генератор с частотой 16 МГц и основной системной частоты 48 МГц и нормальный режим таймера. Более подробную информацию о тактировании от внешнего источника можно найти в уроке «Задание частоты тактирования Xmega A от внешнего генератора».

#define ENABLE_BIT_DEFINITIONS     // разрешение использования групповых битовых имен
/* Объявление используемых библиотек */
#include <ioxm128a1.h>
#include <ina90.h>
void main(void)
{
__disable_interrupt(); // Отключение прерываний
/* Установка тактирования от 3-х кранной частоты внешнего генератора 3*16=48 */
OSC.XOSCCTRL = 0xCB; // выбор внешнего генератора с временем запуска 16 тыс. CLK и частотой 12-16 МГц
OSC.CTRL = 0x08; // разрешение работы внешнего генератора
while((OSC.STATUS & 0x08) == 0 ) ; // ожидание появления в регистре статуса бита включения синхронизации от внешнего генератора
OSC.PLLCTRL = 0xC3; // настройка блока PLL на синхронизацию от внешнего источника и 3-х кратоное умножение
OSC.CTRL = OSC.CTRL | 0x10; // разрешение работы блока PLL
while((OSC.STATUS & 0x10) == 0 ) ; // ожидание появления в регистре статуса бита включения блока PLL
CCP = 0xD8; // включение защиты от изменения регистров ввода-вывода на время изменения синхронизации
CLK.CTRL = 0x04; // настройка системной синхронизации от блока PLL
OSC.CTRL = OSC.CTRL & 0xFE; // отключение системной синхронизации от внутреннего RC-генератора частотой 2 МГц
PORTA.DIRSET = 0x01; // настройка первой ножки 0 порта А как выхода
PORTA.OUTSET = 0x01; // установка ножки 0 порта А в 1
/* Настройка таймера TCС0 */
TCC0.CTRLA=0x05; // N=64;
TCC0.PER=750-1; // частота таймера 1кГц при частоте процессора 48МГц
TCC0.INTCTRLA=1; // уровень прерываний таймера low
PMIC.CTRL = 1; // приоритет прерываний уровня low
__enable_interrupt(); // Разрешение прерываний
while(1){} // пустой бесконечный цикл
}
#pragma vector=TCC0_OVF_vect // обработка прерываний по переполнению таймера TCС0
__interrupt void irqTCC0_OVF_vect(void)
{
PORTA.OUTTGL = 0x01; // переключение состояния ножки 0 порта А на противоположное
}

    Пример 2.
Задача: Оцифровать входной сигнал поступающий на микропроцессор и выдачи его в режиме ШИМ на другую ножку. Пример может быть полезен для изучения генерации ШИМ.
    В качестве основной системной частоты процессора будем использовать внутренний RC-генератор 2 МГц. Таймер TCC0 настроим на прерывание в 1мс, а TCE0 настроим в режим односторонней генерации ШИМ. Значение входного сигнала будем подавать на ножку 3 порта А и оцифровав его с помощью модуля АЦП, выводить на 0 ножку порта С. Более подробную информацию об использовании АЦП можно посмотреть в уроке«Использование АЦП в микропроцессорах XMega А»
#define ENABLE_BIT_DEFINITIONS     // разрешение использования групповых битовых имен

/* Объявление используемых библиотек */

#include <ioxm128a1.h>
#include <ina90.h>
void InitADC(void)
{
/* значение смещения считанное из сигнатуры процессора */
ADCA.CAL=0xff;
/* беззнаковый режим, автоматический режим, 12-битный результат с правым выравниванием */
ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc | 0x08;
/* разрешение работы бэндгап-элемента, внутреннее опорное напряжение 1В */
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;
/* периферийная частота = clk/16 (2MHz/16)*/
ADCA.PRESCALER = ADC_PRESCALER_DIV16_gc;
/* канал 0 ADCA настроен на внешний несимметричных вход */
ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
/* Ножка 3 порта А настроена как положительный вход */
ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN3_gc;
/* Разрешение работы АЦП */
ADCA.CTRLA|=ADC_ENABLE_bm;
}
void main(void)
{
__disable_interrupt(); // Отключение прерываний
/* Настройка таймера TCС0 */
TCC0.CTRLA=0x04; // N=8;
TCC0.PER=250-1; // частота таймера 1кГц при частоте процессора 2МГц
TCC0.INTCTRLA=1; // уровень прерываний таймера low
/* Настройка таймера TCE0 */
TCE0.CTRLA=0x01; // N=1;
TCE0.CTRLB=0x13; // установка режима односторонней ШИМ и разрешение захвата по каналу А
TCE0.PER=4000-1; // 12 кГц частота ШИМ при частоте процессора 2МГц
InitADC(); // Запуск процедуры инициализации АЦП
PMIC.CTRL = 1; // приоритет прерываний уровня low
__enable_interrupt(); // Разрешение прерываний
while(1){} // пустой бесконечный цикл
}
#pragma vector=TCC0_OVF_vect // обработка прерываний по переполнению таймера TCС0
__interrupt void irqTCC0_OVF_vect(void)
{
TCE0.CCA =ADCA.CH0RES; // запись значения из АЦП в регистр сравнения таймера
while(!(TCE0.INTFLAGS & TC0_OVFIF_bm)); // ожидания флага переполнения
TCE0.INTFLAGS = TC0_OVFIF_bm; // очищение флага переполнения
}
    Blogger Comment
    Facebook Comment

0 коммент.:

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