Продолжая цикл публикаций по микроконтроллерам на ядре Cortex-M0 компании Megawin (см. предыдущие статьи 1, 2, 3, 4 и 5), сегодня рассмотрим таймеры общего назначения.
Функциональные возможности таймеров МК серии MG32F02
МК MG32F02x064, MG32F02x128 включают 7 таймеров общего назначения четырех типов TM00/01, TM10/16, TM20/26 и TM36. МК MG32F02A032 включает 5 таймеров трех типов TM00/01, TM10/16, и TM36. Таймеры имеют общий базовый принцип построения, но различаются функциональными возможностями, которые возрастают с увеличением первой цифры в названии.
Таймеры имеют следующие общие функциональные возможности:
основной счетчик (CT1) и предделитель (CT2) с одинаковой разрядностью (8 или 16);
три режима работы предделителя и счетчика: раздельный, каскадный, совмещенный (общая разрядность 16 или 32);
направление счета предделителя вверх или вниз;
выбор источника сигнала внутреннего тактирования модуля с делением частоты на 1, 2, 4 или 8;
выбор внешнего (с вывода МК) или внутреннего сигнала тактирования отдельно для CT1 и CT2;
выбор внешнего или одного из 8 внутренних сигналов (событий) МК в качестве входного триггерного сигнала;
выбор события для генерации выходного триггерного сигнала для других модулей МК;
коммутация выходного триггерного сигнала на внешний вывод МК;
коммутация сигнала переполнения от CT1 или CT2 на внешний вывод МК;
режим "автостоп";
генерация прерывания по выбранному событию в модуле;
работа в режимах ON и SLEEP.
Различия в функциональных возможностях таймеров приведены в таблице.
Функция | TM00/01 | TM10/16 | TM20/26 | TM36 |
---|---|---|---|---|
Разрядность основного счетчика | 8 | 16 | 16 | 16 |
Разрядность предделителя | 8 | 16 | 16 | 16 |
Независимые каналы | - | - | 2 | 4 |
Входы захвата (IC) | - | - | 2 | 4 |
Входной сигнал отключения выходов (Input Break) | - | - | - | + |
Выходы схемы сравнения (OC) | - | - | 2 | 4 |
Комплементарные выходы схемы сравнения (OCN) | - | - | 2 | 3 |
Выходы схемы сравнения для раздельного 8-битного режима (OCH) | - | - | 2 | 4 |
Режим ШИМ | - | - | + | + |
Режим ШИМ с выравниванием по центру | - | - | - | + |
Формированием "мертвого" времени | - | - | - | + |
Направление счета вверх основного счетчика | + | + | + | + |
Направление счета вниз основного счетчика | - | TM16 | TM26 | + |
Дополнительный счетчик для режима "автостоп" | - | - | + | + |
Интерфейс квадратурного энкодера | - | - | TM26 | + |
Сигнал XOR из 3-х сигналов IC в качестве сигнала захвата канала 0 | - | - | - | + |
Задержка выходного сигнала | - | - | + | + |
Поддержка DMA | - | - | - | + |
Функциональная схема включает общую для всех таймеров часть, приведенную на следующем рисунке, и часть дополнительных функций, которая далее будет рассматриваться отдельно для каждого типа таймера.
Общая часть включает:
блок формирования внутреннего сигнала тактирования, сигналов тактирования счетчиков TMx_CK_TC и TMx_CK_TC2 (Clock Control);
блок формирования входного триггерного и выходного триггерного сигналов (Trigger Control);
блок счетчиков (Counter Stage), состоящий из основного счетчика Main Timer (далее — CT1) и предделителя 2nd Timer (Prescaler) (далее — CT2) с одинаковой разрядностью;
блок формирования сигнала прерывания модуля INT_TMx (Interrupt Control).
Тактирование
На следующем рисунке представлена более подробная схема блоков Counter Stage и Trigger Control.
Источник внутреннего тактового сигнала модуля CK_TMx определяется значением поля TMx_CLK.TMx_CKI_SEL
:
0 — сигнал CK_TMx_PR из подсистемы тактирования МК, который, в свою очередь, определяется битом
CSC_CKS2.CSC_TMx_CKS
из сигналов CK_APB (0) или CK_AHB (1);2 — общесистемный НЧ-сигнал CK_LS, частота которого должна быть не выше половины частоты сигнала CK_TMx_PR.
Сигнал CK_TMx подается на делитель частоты с коэффициентом 1, 2, 4 или 8 (выбирается в поле TMx_CLK.TMx_CKI_DIV
), на выходе которого формируется внутренний тактовый сигнал CK_TMx_INT. Альтернативный тактовый сигнал CK_TMx_EXT в зависимости от значения поля TMx_CLK.TMx_CKE_SEL
формируется из одного из сигналов:
0 — внешний сигнал TMx_ETR с вывода МК,
1 — сигнал TMx_ITR с выхода мультиплексора выбора одного из доступных триггерных сигналов для данного таймера ITR_MUX (см. описание далее),
2 и 3 — дополнительные входные сигналы таймера TMx_IN0 и TMx_IN1 (только для таймеров TM20/26 и TM36).
Итоговый сигнал счетных импульсов TMx_CK_TC основного счетчика CT1 выбирается битом TMx_CLK.TMx_CKS_SEL
из сигналов: CK_TMx_INT (0) или CK_TMx_EXT (1). Аналогично выбирается сигнал счетных импульсов TMx_CK_TC2 счетчика CT2 по значению бита TMx_CLK.TMx_CKS2_SEL
.
В таймере TM36 сигнал CK_TMx также подается на другой делитель частоты с коэффициентом 1, 2, 4 или 8 (выбирается в поле TM36_CLK.TM36_DTG_DIV
), на выходе которого сигнал TMx_CK_DTG используется для формирования "мертвого" времени в режиме ШИМ.
Режимы работы счетчиков
Выбор режима
В каждом таймере счетчики CT1 и CT2 могут быть настроены на работу в одном из трех режимов:
раздельном (Separate Mode) — каждый счетчик тактируется и работает независимо от другого;
каскадном (Cascade Mode) — счетчик CT2 выполняет функцию предделителя для основного счетчика CT1 (по-умолчанию);
совмещенном (Full-Counter Mode) — оба счетчика объединяются в единый счетчик с общей разрядностью 16 или 32.
Режим работы счетчиков задается в поле TMx_CR0.TMx_MDS
. При использовании счетчика CT1 он должен быть включен установкой бита TMx_CR0.TMx_EN
. При использовании счетчика CT2 в первых двух режимах необходимо установить бит TMx_CR0.TMx_EN2
; в совмещенном режиме CT2 включается автоматически вместе с CT1 установкой бита TMx_CR0.TMx_EN
.
Раздельный режим (Separate)
В раздельном режиме счетчики включаются и функционируют независимо друг от друга. Счетчик CT1 переключается под действием импульсов сигнала TMx_CK_TC. В таймерах TM00/01, TM10 и TM20 возможен счет только вверх, в остальных таймерах — в обе стороны, направление счета задается битом TMx_CR0.TMx_DIR
. Текущее значение счетчика доступно по чтению и записи в регистре TMx_CNT
(разряды 0-7 или 0-15 в зависимости от типа таймера). В регистре TMx_ARR
(Auto-Reload Register) задается значение автозагрузки счетчика (разряды 0-7 или 0-15). При счете вверх при превышении этого значения генерируется событие Timer Overflow и устанавливается флаг TOF, а счетчик сбрасывается в 0. При счете вниз из нулевого состояния генерируется событие Timer Underflow и устанавливается флаг TUF, а в счетчик загружается значение TMx_ARR
. По-умолчанию значение автозагрузки равно 0. Частота полного цикла счета будет определяться выражением
F1 = F(CK_TC) / (ARR + 1) ,
где F(CK_TC) — частота входных счетных импульсов счетчика CT1, ARR — значение регистра TMx_ARR
.
Счетчик CT2 переключается под действием импульсов сигнала TMx_CK_TC2. Направление счета задается битом TMx_CR0.TMx_DIR2
для всех таймеров. Текущее значение счетчика доступно по чтению и записи в поле TMx_PSCNT
регистра TMx_PSCNT
(разряды 0-7 или 0-15). В этом же регистре в поле TMx_CNTA
продублировано текущее значение счетчика CT1 (разряды 8-15 или 16-31 в зависимости от типа таймера), поле доступно только по чтению. В регистре TMx_PSARR
(Prescaler Auto-Reload Register) задается значение автозагрузки счетчика CT2 (разряды 0-7 или 0-15), которое используется аналогично основному счетчику. При счете вверх при превышении этого значения генерируется событие Timer Overflow и устанавливается флаг TOF2, а счетчик сбрасывается в 0. При счете вниз из нулевого состояния генерируется событие Timer Underflow и устанавливается флаг TUF2, а в счетчик загружается значение TMx_PSARR
. Частота полного цикла счета будет определяться выражением
F2 = F(CK_TC2) / (PSARR + 1) ,
где F(CK_TC2) — частота входных счетных импульсов счетчика CT2, PSARR — значение регистра TMx_PSARR
.
Каскадный режим (Cascade)
В каскадном режиме счетчик CT2 выполняет функцию предделителя для основного счетчика CT1. Счетчик CT2 переключается под действием импульсов сигнала TMx_CK_TC2, а счетчик CT1 — по завершению каждого цикла CT2. В остальном счетчики настраиваются независимо. Частота FC полного цикла счета CT1 будет определяться выражением
FC = F(CK_TC2) / [ (ARR + 1)·(PSARR + 1) ] .
Совмещенный режим (Full-Counter)
В совмещенном режиме оба счетчика объединяются в единый счетчик с общей разрядностью 16 (для таймеров TM00/01) или 32 (для остальных таймеров). Счетчик CT1 представляет старшие разряды (High), а счетчик CT2 — младшие разряды (Low). Единый счетчик переключается под действием импульсов сигнала TMx_CK_TC2. В таймерах TM00/01, TM10 и TM20 возможен счет только вверх, в остальных таймерах — в обе стороны согласно значению бита TMx_CR0.TMx_DIR
. Значение автозагрузки счетчика формируется из значений регистра TMx_ARR
(старшие 8 или 16 бит) и TMx_PSARR
(младшие 8 или 16 бит). При наступлении события Timer Overflow единого счетчика устанавливаются оба флага TOF и TOF2. При наступлении события Timer Underflow устанавливаются оба флага TUF и TUF2. Частота FF полного цикла счета будет определяться выражением
FF = F(CK_TC2) / ( 2N ·ARR + PSARR + 1) ,
где N — разрядность одного счетчика (8 или 16) в зависимости от типа таймера.
Событие обновления счетчиков
В таймере формируются два внутренних сигнала обновления счетчиков TMx_UEV и TMx_UEV2. Схема их формирования показана на следующем рисунке.
Сигнал TMx_UEV активируется при завершении каждого цикла счетчика CT1. В поле TMx_TRG.TMx_UEV_SEL
определяется событие активизации: TOF, TUF или оба (по-умолчанию). В последнем случае можно генерировать событие программно установкой бита TMx_CR0.TMx_USW_EN
, а также можно использовать сигнал TMx_TRGI_EX при установке бита TMx_CR0.TMx_UEX_EN
. Сигнал TMx_TRGI_EX формируется из сигнала TMx_TRGI (см. описание далее) при установленном бите разрешения TMx_CR0.TMx_EX_EN
с опциональным инвертированием при установленном бите TMx_CR0.TMx_EX_INV
.
Сигнал TMx_UEV2 активируется при завершении каждого цикла счетчика CT2 по событиям TOF2 и TUF2. Сигналы TMx_UEV и TMx_UEV2 могут быть выбраны источником выходного триггерного сигнала TMx_TRGO, если в поле TMx_TRG.TMx_TRGO_MDS
установлено соответствующее значение.
Выходной сигнал таймера CKO и функция автостопа
В каждом таймере имеется возможность коммутации выходного сигнала счетчиков на внешний вывод МК TMx_CKO. Схему иллюстрирует следующий рисунок.
Источником сигнала TMx_CKOM в зависимости от значения поля TMx_CKO.TMx_CKO_SEL
может быть:
сигнал TMx_CKO1 с выхода счетчика CT1,
сигнал TMx_CKO2 с выхода счетчика CT2 (по-умолчанию).
Если установлен бит TMx_CKO.TMx_CKO_EN
, сигнал TMx_CKOM проходит на выходной узел формирования сигнала TMx_CKO. Выходной сигнал формируется с помощью T-триггера: при каждом импульсе сигнала TMx_CKOM логическое состояние выхода TMx_CKO изменяется на противоположное. Таким образом, на выходе TMx_CKO формируется сигнал, частота которого в 2 раза ниже частоты сигналов TMx_CKO1 или TMx_CKO2. Начальное состояние выхода TMx_CKO определяется битом TMx_CKO.TMx_CKO_STA
, изменение значения этого разряда возможно при одновременной записи логической "1" в разряд TMx_CKO_LCK
этого же регистра.
В таймере имеется возможность автоматической остановки счетчика CT2 при завершении цикла счетчика CT1. Данная функция включается установкой бита TMx_CR0.TMx_ASTOP_EN
. Счетчик CT2 продолжит считать после программного сброса флагов TOF или TUF (в зависимости от направления счета), при этом в совмещенном режиме единый счетчик начнет считать с начального состояния. Если установлен бит TMx_CR0.TMx_ACLEAR_EN
, то при срабатывании автостопа также сбрасываются флаги TOF и TUF.
Счетчик повторений
В состав таймеров TM20/26 и TM36 (кроме МК MG32F02A032) входит дополнительный блок, предназначенный для остановки счетчиков после заданного числа циклов счета. Блок основан на 8-разрядном счетчике обратного отсчета Repetition Counter (далее — RCT). В поле TMx_RCNT
регистра TMx_RCNT
по чтению и записи доступно значение счетчика, а в поле TMx_RARR
— значение для его перезагрузки после достижения нуля. Работа счетчика разрешается установкой бита TMx_CR0.TMx_RC_EN
. Останов счета основного счетчика CT1 при завершении цикла счета RCT разрешается установкой бита TMx_CR0.TMx_RC_STP
. По завершению одного цикла счета RCT активируется флаг RTUF.
Источник тактовых импульсов для RCT выбирается в поле TMx_CLK.TMx_RC_CKS
из числа следующих:
сигнал TMx_CKO1 с выхода счетчика CT1 (по-умолчанию),
сигнал TMx_CKOM.
Блок формирования входного триггерного сигнала
Все настройки блока осуществляются через регистр TMx_TRG
. Входной триггерный сигнал таймера TMx_TRGI в зависимости от значения поля TMx_TRG_MUX
формируется из одного из сигналов TMx_ETR, TMx_ITR, TMx_IN0 или TMx_IN1 (аналогично сигналу CK_TMx_EXT). В поле TMx_ITR_MUX
выбирается один из восьми доступных для данного таймера источников сигнала TMx_ITR согласно приведенной ниже таблице.
Общесистемные триггерные сигналы ITR6 и ITR7 для всего МК выбираются через поля APB_ITR6_MUX
и APB_ITR7_MUX
регистра APB_CR2
согласно следующей таблице.
Для управления счетчиками используются следующие три сигнала:
Reset (TMx_RST, TMx_RST2) — для сброса счетчика в 0 при возрастающем счете или для перезагрузки значения из регистров
TMx_ARR
/TMx_PSARR
при убывающем счете;Gated Clock (TMx_GT, TMx_GT2) — для отключения подачи счетных импульсов на вход счетчиков;
Trigger (TMx_TR, TMx_TR2) — для запуска счетчика по сигналу в соответствии с установленным условием.
Сигнал TMx_TRGI может быть использован для формирования одного из трех управляющих сигналов для каждого счетчика. Формируемый сигнал и активный уровень определяются полями TMx_TRGI_MDS
и TMx_TRGI2_MDS
для счетчиков CT1 и CT2 соответственно. Схема формирования управляющих сигналов счетчиков приведена на следующем рисунке.
Счетчики CT1 и CT2 могут быть сброшены программно установкой битов TMx_TRG.TMx_RST_SW
и TMx_TRG.TMx_RST2_SW
соответственно. Для возобновления счета эти биты должны быть сброшены. Также возможно отключение подачи счетных импульсов на входы счетчиков установкой битов TMx_TRG.TMx_GT_SW
и TMx_TRG.TMx_GT2_SW
соответственно. В совмещенном режиме сброс единого счетчика осуществляется установкой бита TMx_TRG.TMx_RST_SW
, а отключение подачи счетных импульсов на вход — установкой бита TMx_TRG.TMx_GT_SW
.
Блок формирования выходного триггерного сигнала
На следующем рисунке показана общая схема формирования выходного (триггерного) сигнала таймера TMx_TRGO. Не все указанные события могут быть доступны в конкретном типе таймера.
Все настройки блока также осуществляются через регистр TMx_TRG
. Событие для формирования сигнала TMx_TRGO определяется значением поля TMx_TRGO_MDS
. Сигнал TMx_TRGO может быть использован как входной сигнал (управляющий или счетный) для других периферийных модулей МК и может быть выведен на внешний вывод МК (см. таблицу AFS на конкретный тип МК). Сигнал TMx_TRGO может быть проинвертирован, если будет установлен бит TMx_TRGO_INV
.
Сигналом TMx_TRGO можно управлять программно путем установки и сброса бита TMx_TRGO_SW
, если в качестве источника выбран SW
(9). Если в качестве источника выбирается событие UEV, то в поле TMx_UEV_SEL
можно задать один из трех вариантов формирования выходного сигнала: по переполнению счетчика CT1, по достижению нуля счетчиком CT1, либо оба события (по-умолчанию). Остальные события будут рассмотрены далее.
Таймеры TM00/01 и TM10/16
Данные таймеры представляют собой базовый вариант с минимальным функционалом, поэтому не включают часть дополнительных функций. Их общая часть соответствует приведенной выше функциональной схеме за исключением того, что сигналы TMx_IN0 и TMx_IN1 не поддерживаются. Таймеры TM00/01 отличаются от TM10/16 только разрядностью счетчиков (8 и 16 соответственно). Таймер TM16 отличается возможностью счета вниз для счетчика CT1.
Таймеры TM20/26
Функциональная схема
Функциональная схема таймеров TM20/26 приведена на следующем рисунке.
Часть дополнительных функций включает двухканальную схему захвата/сравнения, состоящую из следующих блоков:
блок формирования входных управляющих сигналов для каждого канала таймера (Input Stage),
блок захвата/сравнения (Capture/Compare),
блок формирования выходных сигналов для каждого канала таймера (Output Stage).
В составе каждого блока захвата/сравнения имеются два 16-разрядных регистра CCnA и CCnB, программно доступные по чтению и записи как TMx_CCnA
и TMx_CCnB
, где n — номер канала 0 или 1. Схема может работать в одном из следующих режимов, задаваемом в поле TMx_CCMDS.TMx_CCn_MDS
:
NOP
(0) — схема отключена;16bit_IC
(1) — захват по входному сигналу,16bit_OC
(2) — выход по сравнению в режиме 16 бит,8bitx2_OC
(3) — два выхода по сравнению в режиме 8 бит,16bit_PWM
(4) — 16-битный формирователь ШИМ-сигнала,8bitx2_PWM
(5) — два 8-битных формирователя ШИМ-сигнала.
Рассмотрим каждый из режимов работы подробнее.
Захват по входному сигналу
В этом режиме (16bit_IC
) в регистрах CCnA и CCnB сохраняется состояние счетчиков в момент срабатывания входного триггера. Схема захвата для одного канала приведена на следующем рисунке.
Каждый канал имеет один вход, на который подается сигнал TMx_ISn, где n — номер канала 0 или 1. Этот сигнал поступает с выхода блока Edge Select, в котором определяется активный фронт входного триггерного сигнала TMx_INn согласно значению поля TMx_ICCR.TMx_ICn_TRGS
: 0 — отключен, 1 — нарастающий (передний), 2 — спадающий (задний), 3 — оба фронта. Источник сигнала TMx_INn выбирается в поле TMx_ICCR.TMx_ICn_MUX
из следующих:
внешний вывод МК TMx_ICn,
внутренний сигнал таймера TMx_ITR (см. схему блоков Counter Stage и Trigger Control выше),
выход компаратора CMPn_OUT.
Если в поле TMx_ICCR.TMx_ICn_TRGS
выбрано срабатывание по одному из фронтов (1 или 2), то в зависимости от режима работы счетчиков схема работает следующим образом:
в раздельном и каскадном режимах в регистре CCnA сохраняется значение счетчика CT1 при первом срабатывании триггера, а в регистре CCnB — значение счетчика CT1 при втором срабатывании триггера;
в совмещенном режиме 32-битное значение единого счетчика сохраняется при каждом срабатывании триггера: старшие 16 бит — в регистре CCnA, младшие 16 бит — в регистре CCnB.
После первого срабатывания триггера и сохранения значения счетчика активируется флаг CFnA, а после второго срабатывания — флаг CFnB, показывая тем самым готовность данных для считывания. Если после этого данные из регистров CCnA и CCnB не были востребованы программой, к началу следующего события захвата возникает состояние "Overrun".
Если в поле TMx_ICCR.TMx_ICn_TRGS
выбрано срабатывание по обоим фронтам (3), то схема работает следующим образом:
в раздельном и каскадном режимах в регистре CCnA сохраняется значение счетчика CT1 при нарастающем фронте импульса сигнала TMx_INn, а в регистре CCnB — значение счетчика CT1 при спадающем фронте импульса;
в совмещенном режиме 32-битное значение единого счетчика сохраняется в регистрах CCnA и CCnB при каждом срабатывании триггера.
Флаг CFnA активируется после сохранения значения единого счетчика при нарастающем фронте импульса, а флаг CFnB — при спадающем. Если после этого данные из регистров CCnA и CCnB не были востребованы программой, к началу следующего события захвата также возникает состояние "Overrun".
При возникновении состояния "Overrun" в зависимости от значения поля TMx_CR1.TMx_OVRn_MDS
(отдельно для каждого канала) происходит следующее:
Overwritten (0) — регистры CCnA и CCnB перезаписываются новыми данными (по-умолчанию),
Keep (1) — регистры CCnA и CCnB не перезаписываются, сохраняются старые данные.
Генерация сигналов сравнения и ШИМ в 16-битном режиме
В данных режимах каждый регистр CCnA используется в качестве "теневого" 16-разрядного регистра (Shadow), с которым фактически сравнивается значение счетчика CT1. Регистр CCnB (TMx_CCnB
) используется для предварительной загрузки значения сравнения (Preload) из программы. Специальный бит TMx_CCMDS.TMx_OC_LCK
управляет синхронным обновлением регистров CCnA для всех каналов таймера. Когда бит установлен (locked), новые данные из регистров CCnB не загружаются в регистры CCnA, пока бит не будет сброшен. После сброса бита (unlocked, по-умолчанию) регистры CCnA будут синхронно обновлены после завершения очередного цикла счета (по сигналу TMx_UEV).
На следующем рисунке показана схема сравнения и формирования выходных сигналов в 16-битном режиме.
Основным выходным сигналом блока сравнения является TMx_OSn. В режимах 16bit_OC
и 8bitx2_OC
его начальный уровень задается битом TMx_OSCR.TMx_OSn_STA
(по-умолчанию 0). Изменение значения этого бита возможно при одновременной записи логической "1" в разряд TMx_OSn_LCK
этого же регистра. Алгоритм управления сигналом зависит от режима работы.
В режиме генерации сигнала сравнения (16bit_OC
) при счете вверх уровень сигнала TMx_OSn изменяется на противоположный в момент достижения счетчиком CT1 значения CCnB, при этом активируется флаг CFnA. При достижении этого же значения в следующем цикле счета уровень сигнала TMx_OSn возвращается к начальному, при этом также активируется флаг CFnA. Временная диаграмма работы таймера показана на следующем рисунке.
Здесь коэффициент счета CT1 ARR (значение регистра TMx_ARR
) выбран равным 8, показаны сигналы TMx_OSn для двух разных начальных уровней при OCnB=2 и для варианта высокого начального уровня при OCnB=8. Если значение OCnB больше ARR, состояние сигнала TMx_OSn не изменяется.
В режиме формирования ШИМ-сигнала (16bit_PWM
) в начале цикла счетчика CT1 сигнал TMx_OSn переходит в состояние высокого уровня. При счете вверх в момент достижения счетчиком значения CCnB сигнал TMx_OSn переходит в состояние низкого уровня. Флаг CFnA активируется только в момент достижения значения CCnB. Длительность одного цикла счета составляет (ARR+1) тактов, а коэффициент заполнения — CCnB/(ARR+1) тактов. Пример временной диаграммы работы таймера показан на рисунке.
Здесь показаны случаи при значениях OCnB — 2, 6 и 8. Если значение OCnB больше ARR, сигнал TMx_OSn всегда остается в состоянии высокого уровня. Если значение OCnB равно нулю, сигнал TMx_OSn всегда остается в состоянии низкого уровня. Настройка начального уровня в поле TMx_OSn_STA
в режиме ШИМ не используется.
В режиме формирования ШИМ-сигнала (16bit_PWM
) при счете вниз сигнал TMx_OSn переходит в состояние низкого уровня в момент переключения счетчика CT1 со значения CCnB на (CCnB-1), при этом также активируется флаг CFnA. Если значение OCnB больше значения ARR, сигнал TMx_OSn всегда остается в состоянии низкого уровня. Если значение OCnB равно нулю, сигнал TMx_OSn всегда остается в состоянии высокого уровня. Пример временной диаграммы работы таймера в таком режиме показан на следующем рисунке.
Генерация сигналов сравнения и ШИМ в 8-битном режиме
На следующем рисунке показана схема сравнения и формирования выходных сигналов в 8-битном режиме.
В 8-битных режимах регистр CCnA разделяется на два 8-битных теневых регистра — старший CCnAH и младший CCnAL. Аналогично разделяется регистр загрузки CCnB на соответствующие старший CCnBH и младший CCnBL регистры. Сравнение выполняется отдельно для младшего (L) и для старшего (H) регистров, причем в сравнении участвуют только младшие 8 разрядов счетчика CT1. Соответственно, в каждом канале таймера формируется второй выходной сигнал TMx_OSnH сравнения старшего регистра, а сигналом сравнения младшего регистра остается TMx_OSn.
Начальный (неактивный) уровень сигнала TMx_OSnH задается битом TMx_OSCR.TMx_OSnH_STA
. Изменение значения этого бита возможно при одновременной записи логической "1" в разряд TMx_OSnH_LCK
этого же регистра.
Флаг CFnA активируется при совпадении в младшей части (L), а флаг CFnB — при совпадении в старшей (H) в обоих режимах 8bitx2_OC
и 8bitx2_PWM
.
Блок формирования выходных сигналов каналов сравнения
Рассмотрим блок формирования выходных сигналов одного канала таймеров TM20/26.
В общем случае имеется три типа выходных сигналов схемы сравнения (n — номер канала):
TMx_OCn — основной сигнал сравнения или ШИМ-сигнал,
TMx_OCnN — комплементарный к TMx_OCn сигнал,
TMx_OCnH — сигнал сравнения в старшей части для 8-битных режимов.
Для каждого из сигналов можно выбрать инвертирование установкой соответствующих битов TMx_OCn_INV
, TMx_OCnN_INV
и TMx_OCnH_INV
в регистре TMx_OCCR1
.
Сигнал TMx_OCn может быть выведен на три разных вывода, каждый из которых включается независимо. Таким образом, на внешние выводы ("пины") МК от каждого канала можно вывести всего 5 сигналов: TMx_OCn0, TMx_OCn1, TMx_OCn2, TMx_OCnN и TMx_OCnH. Вывод сигналов TMx_OCn{0,1,2} и TMx_OCnN разрешается установкой соответствующих разрядов TMx_OCn_OE{0,1,2}
и TMx_OCnN_OE
в регистре TMx_OCCR0
.
Возможно включение небольшой задержки сигналов канала 1 по отношению к сигналам канала 0 путем установки бита TMx_OCCR1.TMx_ODLY_SEL
. Согласно User Guide, величина задержки составляет 3-5 нс, ее зависимость от тактовой частоты не указывается.
Таймер TM36
Функциональная схема
Функциональная схема таймера TM36 приведена на следующем рисунке.
Таймер TM36 отличается от TM20/26 следующими функциональными возможностями:
4 канала в схеме захвата/совпадения,
схема формирования "мертвого" времени для режима ШИМ (DTG),
возможность генерации "центрированных" ШИМ-сигналов,
отключение выходов по входному сигналу (блок Break Input Source),
работа в режиме DMA.
Далее рассмотрим те функции и блоки, которые отличаются от таймеров TM20/26.
Захват по входному сигналу
В данном блоке добавлена возможность использования на каналах 0 и 3 внутреннего сигнала TMx_XOR, который формируется на выходе схемы "Исключающее ИЛИ" из внешних сигналов IC0, IC1 и IC2. Сигналы от компараторов CMP0_OUT и CMP1_OUT как входные доступны только для каналов 0 и 1.
Генерация "центрированных" ШИМ-сигналов в 16-битном режиме
В таймере TM36 в поле TMx_PWM.TMx_PWM_MDS
возможно включение режима ШИМ с выравниванием выходных импульсов всех каналов по центру. Общий цикл формирования ШИМ-сигнала увеличивается до 2·ARR тактов по сравнению с обычным выравниванием с циклом длительностью (ARR+1) тактов.
В начале цикла сигнал TMx_OSn находится в состоянии высокого уровня, счетчик CT1 начинает считать вверх от 0 до значения ARR. При достижении счетчиком значения CCnB сигнал TMx_OSn переходит в состояние низкого уровня и активируется флаг CFnA. В момент, когда значение счетчика изменяется с (ARR-1) на ARR, генерируется событие Timer Overflow и активируется флаг TOF. Этот момент является центром отрицательного импульса длительностью 2·(ARR-CCnB) тактов.
Далее счетчик продолжает считать вниз. При достижении счетчиком значения CCnB сигнал TMx_OSn возвращается в состояние высокого уровня и активируется флаг CFnB. В момент, когда значение счетчика изменяется с 1 на 0, генерируется событие Timer Underflow и активируется флаг TUF. Этот момент является центром положительного импульса длительностью 2·CCnB тактов. Далее счетчик продолжает считать от 0 вверх и цикл повторяется. Временная диаграмма работы таймера показана на следующем рисунке.
В режиме формирования ШИМ-сигнала 8bitx2_PWM
флаг CFnA активируется при совпадении в младшей части (L) при счете вверх, а флаг CFnB активируется при совпадении в младшей части (L) при счете вниз.
Формирование "мертвого" времени
В блок формирования выходных сигналов каналов 0-2 добавлена схема формирования "мертвого" времени DTG (Dead Time Generator). На следующем рисунке показаны временные диаграммы работы схемы.
Формирование ШИМ-сигнала в каждом канале осуществляется с помощью дополнительных внутренних комплементарных сигналов TMx_DTn и TMx_DTnN, которые далее используются как выходные сигналы TMx_OCn и TMx_OCnN. Нарастающий фронт сигнала TMx_DTn задерживается относительно нарастающего фронта сигнала TMx_OSn, а нарастающий фронт сигнала TMx_DTnN задерживается относительно спадающего фронта сигнала TMx_OSn. В итоге между положительными импульсами сигналов TMx_DTn и TMx_DTnN возникает постоянная задержка, величина которой устанавливается в поле TM36_PWM.TM36_DTG_DY
в периодах сигнала TMx_CK_DTG. Задержка одинаковая для всех каналов и по-умолчанию равна 0, т.е. формирования "мертвого" времени не происходит. Сигнал TMx_CK_DTG формируется на выходе делителя частоты из тактового сигнала CK_TMx, коэффициент деления 1, 2, 4 или 8 задается в поле TM36_CLK.TM36_DTG_DIV
. Формирование "мертвого" времени может быть полезно при управлении "верхним" и "нижним" силовыми ключами в мостовой и полумостовой схемах для исключения сквозного тока в моменты переключения.
Блок формирования выходных сигналов каналов сравнения
В таймере TM36 схемы формирования выходных сигналов каналов сравнения 2 и 3 отличаются от каналов 0,1 (см. рисунок).
В каналах 0,1 для формирования сигналов TMx_OCn{0,1,2} и TMx_OCnN вместо сигналов TMx_OSn и TMx_OSnN используются сигналы TMx_DTn и TMx_DTnN. Канал 2 имеет только три внешних вывода TMx_OC2, TMx_OC2N и TMx_OC2H, а канал 3 — два вывода TMx_OC3 и TMx_OC3H. Во всех каналах для управления выходными сигналами TMx_OCn добавлена возможность использования внешнего сигнала TMx_BK_INT.
Флаги событий и прерывания
Флаги событий всех типов таймеров собраны в регистре TMx_STA
, а биты разрешения прерываний — в регистре TMx_INT
. Перечень событий и соответствующих флагов прерываний приведен в следующей таблице.
Разряд | Флаг события | Бит прерывания | Название события | Описание | Наличие |
---|---|---|---|---|---|
0 | DIRF | - | Main Timer up/down counting | Направление счета счетчика CT1 | TM16, TM26, TM36 |
2 | BKF | BKIE | Break input | Сигнал отключения выходов | TM36 |
3 | EXF | EXIE | External trigger | Срабатывание внешнего триггерного сигнала | все |
4 | TOF | TIE | Main Timer overflow | Переполнение счетчика CT1 | все |
5 | TOF2 | TIE2 | 2nd Timer overfloww | Переполнение счетчика CT2 | все |
6 | TUF | TIE | Main Timer underflow | Переход через 0 при счете вниз счетчика CT1 | TM16, TM26, TM36 |
7 | TUF2 | TIE2 | 2nd Timer underflow | Переход через 0 при счете вниз счетчика CT2 | все |
8 | CF0A | CC0_IE | Input capture/output compare A, channel 0 | Событие A захвата/совпадения канала 0 | TM2x, TM36 |
9 | CF1A | CC1_IE | Input capture/output compare A, channel 1 | Событие A захвата/совпадения канала 1 | TM2x, TM36 |
10 | CF2A | CC2_IE | Input capture/output compare A, channel 2 | Событие A захвата/совпадения канала 2 | TM36 |
11 | CF3A | CC3_IE | Input capture/output compare A, channel 3 | Событие A захвата/совпадения канала 3 | TM36 |
12 | CF0B | CC0_IE | Input capture/output compare B, channel 0 | Событие B захвата/совпадения канала 0 | TM2x, TM36 |
13 | CF1B | CC1_IE | Input capture/output compare B, channel 1 | Событие B захвата/совпадения канала 1 | TM2x, TM36 |
14 | CF2B | CC2_IE | Input capture/output compare B, channel 2 | Событие B захвата/совпадения канала 2 | TM36 |
15 | CF3B | CC3_IE | Input capture/output compare B, channel 3 | Событие B захвата/совпадения канала 3 | TM36 |
16 | DIRCF | DIRC_IE | Main Timer up/down counting direction change flag | Смена направления счета счетчика CT1 | TM26, TM36 |
18 | IDXF | IDX_IE | QEI external index signal input active detect and internal timer reset flag | Активность внешнего индексного сигнала | TM26, TM36 |
19 | QPEF | QPE_IE | QEI phase state transition errors detect | Ошибка детектирования фазы энкодера | TM26, TM36 |
20 | RTUF | RTU_IE | Repetition timer underflow | Переполнение счетчика повторений | TM2x, TM36 (*1) |
Примечание: (*1) В МК MG32F02A032 флаг RTUF не поддерживается.
Для включения генерации прерывания необходимо:
Выбрать событие (или события) в регистре
TMx_INT
.Разрешить прерывание самого модуля установкой бита
TMx_INT.TMx_IEA
.Разрешить прерывание IRQ от модуля в контроллере прерываний NVIC в регистре
CPU_ISER
.
Тестирование таймеров
Подготовка
В базовую часть кода ("прошиваемую" во flash-память) в файл svr.c
добавлены функции-обработчики прерываний таймеров IRQ с номерами 12-17. Для работы с портом PA в функцию init_clock()
в файле init.c
добавлено включение его тактирования. Для экономии места в статье этот код не приводится.
Для удобства работы с таймерами создано несколько общих функций. Файлы timer.h
и timer.c
включают объявление перечисления enum TimerID
с идентификаторами таймеров TM00_id
- TM36_id
, а также функции:
tm_init(uint8_t tm_id)
— инициализация таймера (включение тактирования),tm_setup_int(uint8_t tm_id, uint32_t flags)
— включение прерывания INT_TMx по флагам, указанным вflags
согласно формату регистраTMxx_INT
.
Файл timer_test.с
включает все далее рассматриваемые функции тестирования, а также общие функции настройки режима работы счетчиков таймеров:
tm_setup_separate(uint8_t tm_id, uint32_t mode, uint16_t khi, uint16_t klo)
— раздельный режим,tm_setup_cascade(uint8_t tm_id, uint32_t mode, uint16_t khi, uint16_t klo)
— каскадный режим,tm_setup_fullcnt(uint8_t tm_id, uint32_t mode, uint32_t k)
— совмещенный режим.
В аргументе mode
можно задать дополнительные биты настройки по формату регистра TMx_CR0
, кроме полей TMx_MDS
, TMx_EN
, TMx_EN2
, которые задаются в самих функциях. Для 16-битных режимов в аргументах khi
и klo
задаются периоды счета счетчиков CT1 и CT2 (с вычетом единицы), а для 32-битного режима период задается в k
.
Напомню, что весь исходный код и сопутствующие файлы доступны в репозитории GitHub. Также отмечу, что в репозитории обновлена библиотека mg32f02_mem_ap.tcl
и конфигурационные файлы для МК mg32f02a032.cfg
, mg32f02a064.cfg
. Изменения следующие:
добавлена поддержка страниц flash-памяти размером 512 байт, задание размера происходит в файлах
*.cfg
;оптимизирован алгоритм прошивки и добавлена функция верификации данных;
добавлен файл
jlink.cfg
для работы с J-Link, в том числе, с "перешитым" из ST-Link.
В аппаратной части изменений нет, во всех тестах МК тактируется от кварцевого генератора частотой 12 МГц. Необходимые для тестирования входы и выходы МК будут указаны в каждом тесте.
Частотомер
Начнем тестирование таймеров с задачи построения измерителя частоты. Нам потребуются два таймера: один — для формирования временного интервала 1 с, другой — для подсчета количества входящих импульсов в течение этого интервала. Выберем для этого первые два 32-битных таймера TM10 и TM16 соответственно. Функциональная схема частотомера показана на следующем рисунке.
Оба таймера будут работать в совмещенном режиме. Таймер TM10 тактируется от сигнала CK_APB частотой 12 МГц, поделенной на 4 входным делителем таймера. Период счета установлен равным 3 000 000 тактам, что будет обеспечивать измерительный интервал в 1 с. Сигнал переполнения счетчика (флаг TOF, активный уровень — высокий) выведен из модуля в качестве выходного триггерного сигнала TM10_TRGO. Его можно будет контролировать на внешнем выводе PC12.
На внешний вход ETR таймера TM16 (PB0) подается входной сигнал с измеряемой частотой Fx. Он непосредственно поступает на счетный вход единого счетчика. Для управления счетом используется входной триггерный сигнал TM16_TRGI, который подается на вход Gate счетчика: при низком уровне сигнала прохождение счетных импульсов разрешено, при высоком уровне счет останавливается. Значение единого 32-битного счетчика доступно в регистре TM16_PSCNT
. Для коммутации сигнала TM10_TRGO на триггерный вход таймера TM16 необходимо использовать общесистемный сигнал событий ITR6, поскольку прямой возможности выбора такого входного сигнала для TM16 не предусмотрено.
Рассмотрим основную функцию timer_test_freq()
, реализующую частотомер:
/// Частотомер на базе TM10 и TM16
void timer_test_freq() {
// Настройка TM10 как формирователя секундных импульсов
tm_init(TM10_id);
RH(TM10_CLK_h0) = TM_CLK_CKI_DIV_div4_h0 | TM_CLK_CKI_SEL_proc_h0 | TM_CLK_CKS2_SEL_ck_int_h0;
// Включаем режим 32 бита с функцией автостопа:
tm_setup_fullcnt(TM10_id, TM_CR0_ASTOP_EN_enable_h0, 3000000-1); // F(CKO1)=1 Гц
// TRGO <- TOF
RW(TM10_TRG_w) = TM_TRG_TRGO_MDS_tof_w;
// Контроль сигнала на выводе PC12 (30)
RH(PC_CR12_h0) = (5 << 12) | 2; // PC12: TM10_TRGO, push pull output
// Настройка прерывания TM10 по событию TOF (TIE)
SVC2(SVC_HANDLER_SET, 13, timer_hdl_freq); // устанавливаем обработчик прерывания
tm_setup_int(TM10_id, TM_INT_TIE_enable_w);
// Настройка TM16 как основного счетчика входных импульсов
tm_init(TM16_id);
// Настройка тактирования: TM16_CK_TC2 <- TM16_ETR:
RW(TM16_CLK_w) = TM_CLK_CKS2_SEL_ck_ext_w | TM_CLK_CKE_SEL_etr_w;
// Настройка входного сигнала TM16_ETR на пин PB0:
RH(PB_CR0_h0) = (5 << 12) | (1 << 5) | 3; // TM16_ETR, digital input + pull-up
// Включаем режим 32 бит:
tm_setup_fullcnt(TM16_id,TM_CR0_DIR_up_w,0xffffffff);
// Включаем входной триггер ITR6=TM10_TRGO как Gate:
RW(TM16_TRG_w)=
TM_TRG_ITR_MUX_itr6_w | // ITR <- ITR6
TM_TRG_TRG_MUX_itr_w | // TRGI <- ITR
TM_TRG_TRGI_MDS_gate_h_w; // TRGI_MDS: GATE HI
// Включаем сигнал TM10_TRGO как ITR6 (TRG1=TM10_TRGO):
RB(APB_CR2_b0)= APB_CR2_ITR6_MUX_trg1_b0;
}
В начале функции инициализируется и настраивается таймер TM10. Для выполнения точного измерения частоты необходимо не только выдержать интервал 1 с, но и перезапустить таймер одновременно с деактивацией сигнала TM10_TRGO, чтобы начался счет входных импульсов в таймере TM16. Для этого в таймере TM10 задействуем функцию автостопа: поскольку счетчики CT1 и CT2 работают в совмещенном режиме, активация флага TOF и останов счета будут происходить при переполнении счетчика, т.е. в нулевом состоянии. Сброс флага TOF автоматически запустит таймер TM10 с нуля и одновременно разрешит счет в таймере TM16. Для снятия показаний счетчика TM16 и его последующего сброса по окончанию интервала 1 с необходимо задействовать обработчик прерываний по переполнению таймера TM10.
Далее в функции инициализируется и настраивается таймер TM16. Входной сигнал TM16_ETR будет поступать с вывода МК PB0. Счетчики включаются в совмещенный режим с максимальным коэффициентом счета. На вход триггера подается сигнал ITR6 c мультиплексора сигналов событий шины APB, а источником этого сигнала назначается выходной сигнал таймера TM10_TRGO (источник TRG1, см. п. "Блок формирования входного триггерного сигнала").
Теперь рассмотрим обработчик прерывания timer_hdl_freq()
, который будет вызываться каждый раз по окончанию измерительного интервала 1 с:
/// Обработчик прерывания с таймера TM10
void timer_hdl_freq() {
// Считываем значение частоты с TM16:
debug32('F',RW(TM16_PSCNT_w));
// Сбрасываем счетчик в TM16:
RB(TM16_TRG_b3) |= TM_TRG_RST_SW_enable_b3;
RB(TM16_TRG_b3) &= ~TM_TRG_RST_SW_enable_b3;
// Сбрасываем флаг TOF и одновременно запускаем счетчик в TM10:
RB(TM10_STA_b0)=0xff; //TM_STA_TOF_mask_b0;
}
В начале функции считываются показания счетчика таймера TM16 и выводятся в терминал в десятичном виде (для этого функция debug32()
была переписана). Далее счетчик сбрасывается с помощью программной генерации сигнала RST. Наконец, сбрасывается флаг TOF таймера TM10, после чего запускается новый цикл измерения частоты.
Перейдем к эксперименту. Подключим ко входу PB0 внешний лабораторный генератор Rigol DG4102. Подадим с генератора меандр частотой 10 кГц и посмотрим, что приходит в терминал:
F 0000010000
F 0000010001
F 0000010001
F 0000010001
F 0000010001
Результат вполне хороший. Изменим частоту на 100 кГц:
F 0000100007
F 0000100006
F 0000100007
F 0000100006
F 0000100007
И наконец, проверим частотомер на 1 МГц:
F 0001000065
F 0001000064
F 0001000065
F 0001000064
F 0001000064
При тактовой частоте 12 МГц при дальнейшем увеличении частоты входного сигнала частотомер адекватно работал примерно до 3.5-4 МГц. Видно, что с учетом немного заниженной тактовой частоты МК измерительный интервал получился больше, поэтому показания частотомера имеют погрешность "в плюс". Однако, при стабильной частоте кварцевого генератора можно легко добиться более точного значения интервала в 1 c путем подбора периода счета таймера TM10, задаваемого в функции tm_setup_fullcnt()
(в моем случае потребовалось установить значение 2999806). В целом частотомер показал очень хорошую работу с полностью аппаратным обеспечением процесса измерения.
Режим захвата и измерение длительности импульсов
Тестирование схемы захвата/сравнения начнем с функции захвата на основе таймера TM26. Задача будет заключаться в фиксировании моментов времени переключения входного сигнала на канале 0. В качестве источника тактирования выберем вспомогательный таймер TM00, который обеспечит тактовые импульсы с частотой 1 МГц, чтобы время можно было измерять в удобных единицах — микросекундах. Функциональная схема показана на следующем рисунке.
Рассмотрим функцию тестирования timer_test_capture()
:
/// Тестирование функции захвата на TM26
void timer_test_capture() {
// Настройка TM00_TRGO в качестве источника 1 МГц
tm_init(TM00_id);
// Настройка тактирования: TM00_CK_TC2 - 12 МГц
RH(TM00_CLK_h0) = TM_CLK_CKI_DIV_div1_h0 | TM_CLK_CKI_SEL_proc_h0 | TM_CLK_CKS2_SEL_ck_int_h0;
tm00_setup_fullcnt(12-1); // F1 = 1 МГц
// TRGO <- UEV
RW(TM00_TRG_w) = TM_TRG_TRGO_MDS_uev_w;
// Контроль сигнала на выводе PD9 (39)
RH(PD_CR9_h0) = (0x2 << 12) | 2; // PD9: TM00_TRGO, push pull output
// Настройка TM26
tm_init(TM26_id);
// Настройка тактирования: TM26_CK_TC2 <- TM00_TRGO
RW(TM26_CLK_w) = TM_CLK_CKS2_SEL_ck_ext_w | TM_CLK_CKE_SEL_itr_w;
RB(TM26_TRG_b1) = TM_TRG_ITR_MUX_itr6_b1; // TM26: ITR6 = TRG0 = TM00_TRGO
tm_setup_fullcnt(TM26_id,TM_CR0_DIR_up_w,0xffffffff);
// Настройка режима захвата на канале 0 по обоим фронтам от сигнала IC0
RB(TM26_CCMDS_b0) = TM_CCMDS_CC0_MDS_16bit_ic_b0;
RW(TM26_ICCR_w) = TM_ICCR_IC0_TRGS_dual_edge_w | TM_ICCR_IC0_MUX_ic00_w; // IC0
// Настройка входного сигнала TM26_IC0 на пин PB0
RH(PB_CR0_h0) = (6 << 12) | (1 << 5) | 3; // TM26_IC0, digital input + pull-up
// Настройка прерывания по событиям CC0A, CC0B
SVC2(SVC_HANDLER_SET, 16, timer_hdl_capture); // устанавливаем обработчик прерывания
tm_setup_int(TM26_id, TM_INT_CC0_IE_enable_w);
}
В начале функции инициализируется и настраивается таймер TM00. Поскольку таймер работает в режиме делителя частоты, для контроля частоты на выход TM00_TRGO (PD9) выводится сигнал UEV. Далее настраивается таймер TM26. В качестве тактового выбирается внешний триггерный сигнал ITR от источника ITR6, поскольку для данного таймера непосредственно выбрать сигнал TM00_TRGO нельзя. Однако сам общесистемный сигнал событий ITR6 уже связан по-умолчанию с сигналом TM00_TRGO (источник TRG0), поэтому в мультиплексоре APB ничего настраивать не требуется. Счетчики настраиваются на совмещенный 32-битный режим с возрастающим счетом на максимальный период.
В схеме захвата будем использовать только канал 0. Выбираем срабатывание по обоим фронтам (Dual-edge), поскольку необходимо измерять длительность импульсов. Входной сигнал захвата будем подавать на вывод IC0 (PB0). Для обработки событий захвата будем использовать прерывание таймера TM26 (IRQ#16) по событиям CC0A и CC0B, которые объединяются в общее прерывание CC0.
Рассмотрим обработчик прерывания timer_hdl_capture()
:
/// Обработчик прерывания в режиме захвата по каналу 0
void timer_hdl_capture() {
static uint32_t a;
uint32_t b;
uint32_t f=RW(TM26_STA_w);
if (f & TM_STA_CF0A_happened_w) {
b=a;
a=(RH(TM26_CC0A_h0) << 16) | RH(TM26_CC0B_h0);
debug32('A',a);
debug32('T',a-b); // Период A1-A0
}
if (f & TM_STA_CF0B_happened_w) {
b=(RH(TM26_CC0A_h0) << 16) | RH(TM26_CC0B_h0);
debug32('B',b);
debug32('P',b-a); // Длительность импульса B-A
uart_puts(PORT,"--",UART_NEWLINE_CRLF);
}
RW(TM26_STA_w)=0xffffffff; // сброс всех флагов
}
В начале функции считываются флаги и определяется, какое из событий произошло. Событие CC0A возникает при нарастающем фронте входного сигнала, а CC0B — при спадающем. В обоих случаях 32-битный результат захвата сохраняется в регистрах TM26_CC0A
и TM26_CC0B
частями по 16 бит. В первом случае значение счетчика выводится в терминал с пометкой A
и сохраняется в статической переменной a
. Во втором случае значение счетчика также выводится в терминал с пометкой B
и вычисляется его разница с ранее сохраненным в переменной a
. Разница выводится в терминал с пометкой P
— длительность положительного импульса. Дополнительно при наступлении события CC0A выводится период импульсов с пометкой T
. В конце функции сбрасываются все флаги. Отметим, что программа будет работать корректно только в том случае, если интервал между импульсами будет достаточно большим для того, чтобы успел выполниться код обработчика прерывания, в котором самой медленной операцией будет вывод в UART.
Перейдем к эксперименту. Вначале измерим частоту тактового сигнала на выводе TM00_TRGO с помощью частотомера Ч3-85:
Частота несколько ниже 1 МГц, значит период импульсов будет длиннее, а показания схемы захвата будут занижены. На вход IC0 подаем меандр с частотой 1 Гц от генератора DG4102 и получаем вывод в терминал (фрагмент с момента 3.6 с):
A 0003608801
T 0000999935
B 0004108769
P 0000499968
--
A 0004608737
T 0000999936
B 0005108704
P 0000499967
--
A 0005608672
T 0000999935
B 0006108640
P 0000499968
--
A 0006608607
T 0000999935
B 0007108575
P 0000499968
--
A 0007608543
T 0000999936
B 0008108510
P 0000499967
--
Поскольку период сигнала внешнего генератора DG4102 выполнил функцию эталонного интервала 1 с, мы получили фактически частотомер для собственных тактовых импульсов и очевидный результат: период (T) около 999935 мкс, а длительность импульсов (P) — около 499967 мкс. Схема работает корректно.
Формирование ШИМ-сигналов
Для формирования ШИМ-сигналов возьмем самый "продвинутый" таймер TM36. Во-первых, только в нем имеется режим "центрирования" импульсов с разных каналов. Во-вторых, в подопытном МК MG32F02A064AD48 вывести на "пины" нужные сигналы от других таймеров оказалось проблематично для выбранного корпуса и уже подготовленной платы.
Для данного эксперимента нам потребуется только таймер TM36. Поскольку формирование ШИМ-сигнала возможно только на основном счетчике CT1, разумно использовать каскадный режим, а счетчик CT2 использовать как предделитель. Будем формировать следующие сигналы:
TM36_TRGO (PB1) — тактовый сигнал счетчика CT1, полученный из сигнала UEV2 с выхода предделителя;
TM36_OC00 (PA0) — ШИМ-сигнал с канала 0;
TM36_OC10 (PA1) — ШИМ-сигнал с канала 1;
сигнал окончания цикла счетчика CT1 (флаг TOF) для удобства анализа осциллограмм (PA2).
Создадим в файле timer_test.c
тестовую функцию timer_test_pwm()
:
/// Генератор ШИМ-сигнала на базе TM36
void timer_test_pwm() {
// Настройка выводов МК:
RH(PA_CR0_h0) = (0xA << 12) | 2; // PA0 (45): TM36_OC00, канал 0
RH(PA_CR1_h0) = (0xA << 12) | 2; // PA1 (46): TM36_OC10, канал 1
RH(PA_CR2_h0) = (0x0 << 12) | 2; // PA2 (47): GPA2, software TOF
RH(PB_CR1_h0) = (0x7 << 12) | 2; // PB1 (10): TM36_TRGO, тактовый сигнал
// Инициализация TM36:
tm_init(TM36_id);
// Настройка тактирования: CK_TC2 <- 6 МГц
RW(TM36_CLK_w) = TM_CLK_CKI_DIV_div2_w | TM_CLK_CKI_SEL_proc_w | TM_CLK_CKS2_SEL_ck_int_w;
// TRGO <- UEV2
RW(TM36_TRG_w) = TM_TRG_TRGO_MDS_uev2_w;
// Настройка периодов: CT2 - 6000 (1 кГц), CT1 - 20 (50 Гц)
tm_setup_cascade(TM36_id,TM_CR0_DIR_up_w,20-1,6000-1);
//tm_setup_cascade(TM36_id,TM_CR0_DIR_down_w,20-1,6000-1);
// Пороги (полный цикл - 20):
RH(TM36_CC0B_h0)=5;
RH(TM36_CC1B_h0)=10;
// Настройка режима OC:
RB(TM36_CCMDS_b0) =
TM_CCMDS_CC0_MDS_16bit_oc_b0 | // канал 0
TM_CCMDS_CC1_MDS_16bit_oc_b0; // канал 1
// Включение выходов:
RW(TM36_OCCR0_w) =
TM_OCCR0_OC0_OE0_enable_w | // OC00 enable
TM_OCCR0_OC1_OE0_enable_w; // OC10 enable
// Настройка прерывания
SVC2(SVC_HANDLER_SET, 17, timer_hdl_pwm); // устанавливаем обработчик прерывания
tm_setup_int(TM36_id, TM_INT_TIE_enable_w); // прерывание по TOF/TUF
}
В начале функции выполняется настройка используемых выводов МК. Далее происходит инициализация и настройка таймера TM36. В качестве исходного выбирается тактовый сигнал шины APB CK_TM36_PR (12 МГц), частота которого предварительно делится на 2. Итоговый сигнал CK_TC2 частотой 6 МГц поступает на вход счетчика CT2. Его коэффициент счета выбирается равным 6000, чтобы тактовый сигнал основного счетчика имел частоту 1 кГц. Коэффициент счета CT1 выбирается небольшим — 20 тактов (20 мс, частота полного цикла 50 Гц), чтобы было удобно определять моменты времени в выходных сигналах на осциллограммах. Выбирается возрастающий счет для обоих счетчиков.
Далее задаются параметры схемы сравнения: пороги CC0B=5 для канала 0 и CC1B=10 для канала 1. В первом эксперименте включим режим сравнения 16bit_OC
(это пока не ШИМ) и разрешим прохождение сигналов на выходы МК. Для программного формирования сигнала окончания цикла счета будем использовать прерывание TIE по флагам TOF/TUF и создадим его обработчик:
/// Обработчик прерывания
void timer_hdl_pwm() {
RH(PA_SC_h0) = 4; // set PA2
__NOP(); __NOP();
RH(PA_SC_h1) = 4; // clear PA2
RB(TM36_STA_b0) = 0xFF; // clear flags
}
При срабатывании прерывания формируется положительный импульс на выводе PA2 (добавляем пару NOP, чтобы импульс был не такой короткий) и сбрасываются флаги. Этот импульс будем использовать далее как триггерный при снятии осциллограмм.
С помощью цифрового анализатора Saleae Logic получаем такой результат:
Видно, что в данном режиме выходные сигналы изменяют свой уровень при каждом срабатывании схемы сравнения (на отметках 5 и 10 мс), тем самым формируя последовательность импульсов со скважностью 2. Период (40 мс) и длительность импульсов (20 мс) на обоих каналах одинаковые, схема лишь создает относительный сдвиг фаз.
Теперь включим режим формирования ШИМ-сигналов на обоих каналах:
// RB(TM36_CCMDS_b0) =
// TM_CCMDS_CC0_MDS_16bit_oc_b0 | // канал 0
// TM_CCMDS_CC1_MDS_16bit_oc_b0; // канал 1
// // Настройка режима ШИМ:
RB(TM36_CCMDS_b0) =
TM_CCMDS_CC0_MDS_16bit_pwm_b0 | // канал 0
TM_CCMDS_CC1_MDS_16bit_pwm_b0; // канал 1
Получаем следующий результат:
Видно, что формируются нормальные ШИМ-сигналы с заданными длительностями импульсов и одинаковыми нулевыми начальными фазами, а их период соответствует одному циклу счета CT1 (20 мс).
Переключим направление счета CT1 вниз и посмотрим результат:
//tm_setup_cascade(TM36_id,TM_CR0_DIR_up_w,20-1,6000-1);
tm_setup_cascade(TM36_id,TM_CR0_DIR_down_w,20-1,6000-1);
Теперь в выходном сигнале канала 0 длительность импульса изменилась на 20-5=15 мс, а на канале 1 в силу симметрии сигнала длительность не изменилась.
В заключении проверим работу таймера в режиме выравнивания импульсов всех каналов по центру. Для этого вернем возрастающее направление счета CT1, а после настройки регистра TM36_CCMDS_b0
добавим следующую строку:
RH(TM36_PWM_h0) = TM_PWM_PWM_MDS_center_aligned_h0; // выравнивание по центру
Получаем следующий результат:
Видно, что действительно импульсы выровнялись во времени по центру, но их параметры изменились. Период счета CT1 сократился с 20 до 19 мс, период импульсов увеличился и стал равен 2·(20-1)=38 мс, а длительности импульсов увеличились в 2 раза. Таймер работает в полном соответствии с документацией.
Заключение
Мы рассмотрели большинство функциональных возможностей таймеров МК серии MG32F02 и успешно протестировали их на практике. За рамками статьи остались следующие вопросы, которые читатель может изучить по указанным пунктам User Guide:
задание начальных (preload) значений выходных сигналов, которые могут быть активированы по внешнему событию (20.14.3),
отключение выходов по входному сигналу (Input Break, только TM36) (20.15),
интерфейс квадратурного энкодера QEI (Quadrature Encoder Interface, TM26, TM36) (20.16),
применение DMA (только TM36) (20.17).
В следующий раз мы рассмотрим модуль двухпроводного интерфейса I2C.