Наш канал в telegram

Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 15. Таймеры. Глава 3 — Таймеры общего назначения TIM2 — TIM5

Особенности

Таймеры TIM2 — TIM5, равно как и описанные в предыдущей главе таймеры TIM9 — TIM14, являются таймерами общего назначения, соответственно и работа с ними во многом похожа (хотя у TIM2 — TIM5 возможности чуть шире). Тем не менее, в этой главе я опишу функционал таймеров TIM2 — TIM5 полностью, не обращая внимания на то, что некоторые её части будут повторять соответствующие части предыдущей главы. Также в этой главе, как я и обещал, будет пример работы с таймерами.

Итак, таймеры TIM2 — TIM5 работают полностью независимо друг от друга, не используя никаких общих ресурсов. При этом они обладают следующим функционалом:

  • 16-битный автоматически перезагружаемый нарастающий счётчик (может считать от нуля до заданного значения)
  • 16-битный программируемый предделитель (позволяет увеличивать счётчик не каждый такт, а через заданное количество тактов)
  • модуль «захвата/сравнения» с четырьмя независимыми каналами (у TIM9-14 только 1 или 2 канала), которые, в зависимости от настройки направления (на вход или на выход) можно использовать для решения следующих задач:
    • фиксация событий на входах («захват»)
    • управление выходами по достижению определённых промежуточных значений («сравнение»)
    • генерация ШИМ-сигнала на выходах (граничный режим и центрально-выравненный режим; у TIM9-14 был только граничный режим)
    • генерация единичного импульса на выходах
  • генерация прерываний по следующим событиям:
    • update (UEV) — событие обновления счётчика. Генерируется в результате переполнения (достижения заданнного значения) или при инициализации (реинициализации по триггеру или программной)
    • input capture (ICx) — изменение уровня на входе (событие «захват»)
    • output compare (OCx) — достижение заданного промежуточного значения счётчика (событие «сравнение»)
    • события триггера — старт/стоп счётчика, инициализация или счёт (одно увеличение счётчика) от внутреннего или внешнего триггера
  • Поддержка режимов интерфейса нарастающего энкодера и датчика Холла (не было у TIM9-14)
  • Вход триггера для внешнего тактирования или поциклового режима управления током (не было у TIM9-14)

Блок-схемы

Блок-схема таймеров TIM2 — TIM5:

блок-схема счётчиков TIM2 - TIM5

Базовый модуль

Базовый модуль таймеров TIM2-TIM5 точно такой же как и для простейших таймеров (подробно о нём можно прочитать в первой главе про таймеры), поэтому здесь я перечислю лишь главные моменты.

Основу базового модуля составляют три регистра:

  • TIMx_CNT — регистр-счётчик
  • TIMx_PSC — регистр предделителя (с буферизацией)
  • TIMx_ARR — регистр автоматической перезагрузки (с буферизацией)

Включение/выключение счётчика производится установкой/сбросом бита CEN в регистре TIMx_CR1.

Для регистров с буферизацией данные сначала записываются в буферы, а уже оттуда в рабочие регистры. В случае с регистром TIMx_PSC загрузка данных из буфера в рабочий регистр происходит только по событию обновления счётчика. Для регистра TIMx_ARR, в зависимости от состояния бита ARPE регистра TIMx_CR1, возможны два варианта: 1) данные сразу записываются в рабочий регистр (сквозная запись, ARPE = 0); 2) данные записываются в рабочий регистр по событию обновления счётчика (отложенная запись, ARPE = 1).

Базовый модуль может генерировать только одно событие — update (UEV). Оно генерируется при переполнении счётчика (когда счётчик досчитает до величины, записанной в регистр TIMx_ARR) или программно, установкой бита UG в регистре TIMx_EGR. Генерацию UEV можно отключить установкой бита UDIS регистра TIMx_CR1. При этом счётчик и предделитель будут по прежнему сбрасываться в ноль при переполнении, однако значения рабочих регистров TIMx_PSC и TIMx_ARR не будут обновляться.

Кроме того, установкой бита URS можно добиться того, что при возникновении события UEV не будет устанавливаться флаг UIF. Это позволяет избежать генерации прерываний по событиям обновления и «захвата» (при сбросе счётчика по событию «захвата»).

Тактирование счётчиков

В качестве источника счётных импульсов таймеров могут быть выбраны следующие варианты:

  • внутренний тактовый сигнал (CK_INT) — выбирается установкой битов SMS[2:0]=’000′ (контроллер slave-режима — выключен).
  • внешнее тактирование, режим 1. Этот режим устанавливается битами SMS[2:0]=’111′, а источник тактового сигнала при этом выбирается битами TS[2:0]. В этом режиме источником тактового сигнала могут быть:
    • внешние входы (TIx) — передний или задний фронт на выбранном выходе
    • внутренние входы триггера (ITRx) — каскадно подключенные к выходам других таймеров)
    • внешний вход триггера (ETRF)
  • внешнее тактирование, режим 2. В этом случае источником тактового сигнала служит внешний вход триггера (ETRF).
    • если для режима 1 качестве источника тактового сигнала выбран сигнал ETRF (TS[2:0]=’111′), то режим 1 аналогичен режиму 2 (в плане источника тактового сигнала).
    • режим 2 выбирается установкой в 1 бита ECE, и имеет приоритет над режимом 1 (при установленном режиме 2 источником тактовых импульсов всегда будет вход ETRF).
    • можно использовать режим 2 одновременно с режимами сброса, шлюза или триггера (при этом источником тактирования будет вход ETRF, а другие внешние входы будут использоваться для синхронизации счётчиков).

Пример настройки счётчика на счёт каждых двух растущих фронтов на входе ETR:

  1. Сбрасываем фильтрацию на входе ETR (ETF[3:0]=’0000′ в регистре TIMx_SMCR)
  2. Настраиваем предделитель для сигнала ETRP (ETR после фильтрации) равным двум (ETPS[1:0]=’01’ в регистре TIMx_SMCR)
  3. Настраиваем детектирование растущего фронта сигнала ETR (ETP=’0′ в регистре TIMx_SMCR)
  4. Устанавливаем режим внешнего тактирования 2 (ECE=’1′ в регистре TIMx_SMCR)
  5. Включить счётчик (записать CEN=’1′ в регистре TIMx_CR1)

Теперь значение счётчика будет увеличиваться на 1 после обнаружения каждого второго растущего фронта на входе ETR.

Модуль захвата/сравнения

Две основные возможности, реализуемые модулями захвата/сравнения (Capture/Compare Module — CCM):

  • По событиям на внешних выводах запоминать в регистрах захвата/сравнения значение счётчика («захват») (в этом случае внешние выводы используются в качестве входов)
  • Управлять внешними выводами в зависимости от результатов сравнения значений счётчика и регистров захвата/сравнения («сравнение») (в этом случае внешние выводы используются в качестве выходов)

Исходя из описанных возможностей CCM имеют несколько режимов работы и позволяет реализовывать такие интересные штуки как: измерение параметров сигналов (период/длительность импульса), генерация сигналов с заданными параметрами (период/длительности импульса), широтно-импульсная модуляция и так далее. Кроме того, входные каналы таймеров TIM2 — TIM5 могут работать в связке, что дополнительно позволяет реализовать на этих входах интерфейс энкодера.

Каждый канал модуля захвата/сравнения построен вокруг регистра захвата/сравнения (Capture/Compare Register — TIMx_CCRx), входного каскада для захвата (с цифровым фильтром, мультиплексором и предделителем) и выходного каскада (с компаратором и блоком управления).

Регистр захвата/сравнения (TIMx_CCRx) — 16-битный и имеет буферизацию. То есть фактически существует два регистра: регистр предварительной загрузки (буфер) и рабочий регистр (он же теневой регистр). В программе операции чтения/записи производятся только с буфером, который синхронизируется с рабочим регистром по различным событиям в зависимости от установленного режима.

Теперь давайте о каждом режиме поговорим более подробно:

Режим захвата по входу (Input Capture Mode)

В этом режиме таймер отслеживает состояние сигнала ICx и при обнаружении этого сигнала запоминает в регистре захвата/сравнения значение счётчика. Это событие (запоминание в регистре TIMx_CCRx значения таймера) как раз и называется «захват».

Сигнал ICx может формироваться от нужного фронта соответствующего входного сигнала TIx или от сигнала TRC (выбирается настройками в регистре TIMx_CCMR1)

Когда происходит «захват» — устанавливается соответствующий флаг CCxIF (в регистре TIMx_SR), при этом, если включены, то генерируется прерывание и/или запрос DMA. Если «захват» случился в тот момент, когда флаг CCxIF уже установлен, тогда устанавливается флаг перезахвата (over-capture) — CCxOF (в регистре TIMx_SR). Флаг «захвата» сбрасывается программно, записью нуля, или аппаратно, при чтении сохранённого в регистр TIMx_CCRx значения. Флаг CCxOF сбрасывается только программно (записью нуля).

Пример настройки модуля CCM для захвата по растущему фронту на входе TI1:

  1. Настроить TI1 в качестве входа для канала CC1 (записать CC1S=’01’ в регистре TIMx_CCMR1)
  2. Настроить время демпфирования для входного фильтра (записать IC1F[3:0] в регистре TIMx_CCMR1. Например, если при переключении, входной сигнал не стабилизируется в течении максимум пяти тактов таймера, то мы должны выбрать время демпфирования больше пяти тактов. Скажем, можно настроить время демпфирования равным восьми тактам частоты тактирования таймера (fCK_INT) (записать IC1F[3:0]=’0011′ в регистре TIMx_CCMR1), в результате чего фронт будет считаться валидным только если сигнал в течении 8 тактов после этого фронта остаётся неизменным. Время демпфирования, задаваемое битами ICxF регистра TIMxCCMR1 может задаваться относительно частоты тактирования таймера (fCK_INT) и относительно частоты сэмплирования (fDTS), которая, в свою очередь, настраивается относительно fCK_INT в регистре TIMx_CR1 (биты CKD[1:0])
  3. Настроить активный фронт сигнала TI1FP1 (выбрать фронт, который нужно отслеживать). Поскольку мы (по условиям примера) хотим отслеживать растущий фронт, то нужно записать CC1NP/CC1P=’00’ в регистре TIMx_CCER
  4. Настроить входной предделитель. Поскольку в нашем примере мы хотим отслеживать каждый растущий фронт, то нам этот предделитель не нужен и его нужно выключить (записать IC1PSC=’00’ в регистре TIMx_CCMR1)
  5. Разрешить работу канала 1 модуля CCM (установить в 1 бит CC1E в регистре TIMx_CCER)
  6. Если нужно, то включить связанный запрос на прерывание (установить в 1 бит CC1IE в регистре TIMx_DIER)

В результате, при возникновении события захвата:

  • В регистре TIMx_CCR1 будет сохранено значение значение счётчика
  • Установится флаг CCIF (флаг ожидания прерывания), а также (в случае, если случился второй захват до того, как обработан первый) флаг CC1OF
  • Случится прерывание если оно разрешено флагом CC1IE

При обработке событий рекомендуется сначала читать данные, а потом уже значение флага CC1OF, поскольку в противном случае возможен вариант, что перезахват произойдёт после чтения флага, но до чтения данных (и мы об этом не узнаем).

Событие захвата может быть сгенерировано программно, установкой бита CCxG в регистре TIMx_ERG.

Режим измерения параметров ШИМ (PWM Input Mode)

Этот режим является частным случаем режима захвата по входу. Особенности этого режима заключаются в следующем:

  • Один и тот же физический вход (TIx) подключен на оба канала (IC1, IC2) (смотрите блок схему таймеров TIM9/12 выше)
  • Каналы сигналов IC1, IC2 настроены на работу по противоположным фронтам
  • Один из двух сигналов TIx_FP настроен в качестве входа триггера, а контроллер слэйв-режимов сконфигурирован в режиме сброса (reset mode). То есть по сигналу на входе триггер сбрасывает счётчик (и он начинает считать с нуля).

Например, для того, чтобы измерить период (в регистре TIMx_CCR1) и ширину импульсов (в регистре TIMx_CCR2) ШИМ-сигнала на входе TI1 нужно использовать следующую процедуру настройки:

  1. Настроить TI1 в качестве входа для канала CC1 (записать CC1S=’01’ в регистре TIMx_CCMR1)
  2. Выбрать растущий фронт активным фронтом сигнала TI1FP1 (записать CC1P=’0′ в регистре TIMx_CCER). По этому фронту будет происходить захват значения таймера в регистр TIMx_CCR1 и сброс таймера (то есть по нему будет отсчитываться период)
  3. Настроить TI1 в качестве входа для канала CC2 (записать CC2S=’10’ в регистре TIMx_CCMR1)
  4. Выбрать падающий фронт активным фронтом сигнала TI1FP2 (записать CC2P=’1′ в регистре TIMx_CCER). По этому фронту будет происходить захват значения таймера в регистр TIMx_CCR2 (то есть по нему будет отсчитываться ширина импульса)
  5. Убедиться, что входные предделители для обоих каналов выключены (в регистре TIMx_CCMR1 IC1PSC=’00’, IC2PSC=’00’)
  6. Выбрать TI1FP1 в качестве входа триггера (записать TS=’101′ в регистре TIMx_SMCR)
  7. Настроить контроллер слэйв-режимов в режим сброса (записать SMS=’100′ в регистре TIMx_SMCR)
  8. Разрешить работу каналов 1 и 2 модуля CCM (установить в 1 биты CC1E и CC2E в регистре TIMx_CCER)

Режим форсированного выхода (Forced Output Mode)

При использовании внешнего вывода в качестве выхода (CCxS=’00’ в регистре TIMx_CCMRx) каждый выходной сигнал модуля сравнения (OCxREF и далее OCx) может быть принудительно переключен к активному или неактивному уровню напрямую из программы, независимо от результатов сравнения счётчика и соответствующего регистра захвата/сравнения.

Для того, чтобы принудительно переключить выходной сигнал модуля сравнения к активному уровню нужно записать OCxM=’101′ в соответствующий регистр TIMx_CCMRx. В результате сигнал OCxREF будет принудительно переключен к высокому уровню (для сигнала OCxREF активный уровень всегда высокий) и сигнал OCx переключится в состояние, противоположное значению бита CCxP.

Например, если CCxP=’0′ (активный уровень OCx — высокий), то OCx будет принудительно переключен к высокому уровню.

Для того, чтобы принудительно переключить выходной сигнал модуля сравнения к неактивному уровню нужно записать OCxM=’100′ в соответствующий регистр TIMx_CCMRx. В результате сигнал OCxREF будет принудительно переключен к низкому уровню (для сигнала OCxREF неактивный уровень всегда низкий) и сигнал OCx переключится в состояние, одинаковое со значением бита CCxP.

В любом случае сравнение между рабочим регистром TIMx_CCRx и счётчиком продолжает выполняться и по результатам этого сравнения по прежнему может быть установлен соотвевтствующий флаг и сгенерирован запрос на прерывание (смотрите ниже описание режима управления выходами по сравнению).

Режим управления выходом по сравнению (Output Compare Mode)

В этом режиме в регистр захвата/сравнения записывается некоторое значение и далее оно сравнивается со значением счётчика каждый новый отсчёт. При совпадении значений счётчика и регистра захвата/сравнения происходит следующее:

  • Базовый выходной сигнал (OCxREF) устанавливается в соответствии со значением, запрограммированным битами OCxM регистра TIMx_CCMR1. Он может быть запрограммирован на то, чтобы остаться неизменным (OCxM=’000′), переключаться в активное (OCxM=’001′) или неактивное (OCxM=’010′) состояние, а также переключаться в противоположное состояние ((OCxM=’011′)). Далее итоговый выходной сигнал (OCx) устанавливается в соответствии со значением сигнала OCxREF и запрограммированной полярностью выходного сигнала (бит CCxP регистра TIMx_CCER)
  • Устанавливается флаг ожидания прерывания от модуля захвата/сравнения (CCxIF) в регистре статуса (TIMx_SR)
  • Генерируется прерывание, если оно разрешено соответствующим битом (CCxIE=’1′ в регистре TIMx_DIER)
  • Генерируется запрос к DMA, если установлены соответствующие биты (CCxDE=’1′ в регистре TIMx_DIER, а также бит CCDS в регистре TIMx_CR2)

Установкой/сбросом битов OCxPE в регистре TIMx_CCMRx можно разрешить/запретить буферизацию регистра захвата/сравнения (TIMx_CCRx). Если буферизация выключена, то регистр TIMx_CCRx может быть перезаписан программно в любое время, в противном случае рабочий регистр будет обновлён только по событию UEV.

В режиме управления выходом по сравнению, событие UEV не влияет на базовый (OCxREF) и итоговый (OCx) выходной сигнал.

Процедура настройки:

  1. Настраиваем источник тактирования таймеров (внутренний, внешний) и предделитель
  2. Записываем нужные значения в регистры TIMx_ARR и TIMx_CCRx
  3. Если нужно — разрешаем прерывание от нужного канала модуля захвата/сравнения (установкой бита CCxIE) и запрос к DMA.
  4. Выбираем нужный режим управления выходом. Например:
    • записываем OCxM=’011′ для переключения сигнала на выходе при совпадении счётчика и значения в регистре CCRx
    • записываем OCxPE=’0′ для выключения буферизации (в регистре TIMx_CCMR1)
    • записываем CCxP=’0′ для выбора высокого активного уровня (active high) (в регистре TIMx_CCER)
    • записываем CCxE=’1′ для включения выхода (чтобы на выходном пине появился сигнал OCx) (в регистре TIMx_CCER)
  5. Включаем счётчик установкой бита CEN в регистре TIMx_CR1

Режим ШИМ (PWM Mode)

Режим ШИМ позволяет генерировать сигнал с частотой, определённой значением регистра TIMx_ARR, и временем импульса, определённым значением регистра TIMx_CCRx.

Режим ШИМ может быть установлен независимо для каждого канала записью битов OCxM=’110′ (PWM Mode 1) или OCxM=’111′ (PWM Mode 2) в регистре TIMx_CCRx. При этом нужно включить буферы для соответствующего регистра захвата/сравнения (установить в 1 бит OCxPE в регистре TIMx_CCMRx) и регистра автоматической перезагрузки (установить в 1 бит ARPE регистра TIMx_CR1).

Поскольку теперь данные в рабочие регистры TIMx_ARR и TIMx_CCRx будут переписываться только по событию UEV, то после записи значений в эти регистры и перед стартом счётчика нужно будет программно сгенерировать событие UEV установкой бита UG регистра TIMx_ERG (чтобы записанные данные «провалились» из буферов в рабочие регистры).

Полярность сигналов OCx может быть программно установлена с помощью битов CCxP в регистре TIMx_CCER. Может быть выбран один из двух вариантов: active high (активный высокий уровень) или active low (активный низкий уровень). Для того, чтобы выходные сигналы OCx физически появились на выходах — нужно включить выходы, установкой в 1 битов CCxE регистра TIMx_CCER.

В ШИМ-режиме значения регистров TIMx_CNT и TIMx_CCRx постоянно сравниваются для определения момента, когда TIMx_CNT≤TIMx_CCRx или TIMx_CCRx≤TIMx_CNT в зависимости от направления счёта. Однако, для согласования с ETRF (OCxREF может быть сброшен внешним событием через сигнал ETR до начала следующего периода ШИМ), сигнал OCREF устанавливается только когда изменяется результат сравнения или при переключении конфигурации из состояния «frozen» (нет сравнения, OCxM=’000′) в один из режимов ШИМ (OCxM=’110′ или ‘111’).

Таймеры TIM2- TIM5 способны генерировать ШИМ сигнал в граничном режиме (два варианта: с нарастающим и с вычитающим счётом) и в центрально-выровненном режиме (три варианта).

Граничный режим выбирается сбросом битов CMS (CMS=’00’) в регистре TIMx_CR1, при этом вариант счёта определяется битом DIR этого же регистра (DIR=’0′ — нарастающий счёт, DIR=’1′ — вычитающий счёт).

В режиме нарастающего счёта счётчик считает от 0 до значения записанного в регистре TIMx_ARR, после чего счётчик рестартует с нуля и генерирует событие переполнения счётчика (от которого может быть сгенерировано событие UEV).

В режиме вычитающего счёта счётчик считает от значения записанного в регистре TIMx_ARR до 0, после чего счётчик рестартует со значения TIMx_ARR и генерирует событие переполнения счётчика (от которого может быть сгенерировано событие UEV).

В центрально-выровненном режиме счётчик считает от 0 до значения записанного в регистре TIMx_ARR-1, генерирует событие переполнения, затем считает от значения TIMx_ARR до 1, снова генерирует событие переполнения, после чего счётчик рестартует с 0 и цикл повторяется снова (от события переполнения может быть сгенерировано событие UEV).

Режим центрального выравнивания активен в том случае, когда значение битов CMS в регистре TIMx_CR1 отлично от ’00’. В этом режиме бит DIR в регистре TIMx_CR1 управляется аппаратно и не должен изменяться программно. Сигналы OCX_REF/OCx в этом режиме ведут себя одинаково, с той лишь разницей, что флаг сравнения может устанавливаться только при счёте вверх, при счёте вниз или при счёте в обоих направлениях, в зависимости от значения битов CMS.

Переключение между различными режимами ШИМ возможно только когда таймер выключен (CEN=0).

Режим одиночного импульса (One-pulse Mode)

Этот режим является частным случаем предыдущих режимов управления выходом (Output Compare и PWM). То есть выход управляется в соответствии с режимом Output Compare или PWM, просто дополнительный выбор режима одиночного импульса (установка бита OPM в регистре TIMx_CR1) приводит к тому, что по событию UEV счётчик автоматически останавливается (сбрасывается бит CEN регистра TIMx_CR1).

Таким образом, мы можем запустить счётчик в ответ на запрограммированное событие (с помощью контроллера слэйв-режимов), сгенерировать одиночный импульс заданной ширины после заданной задержки и затем остановить счётчик.

Импульс может быть корректно сгенерирован только если значение в регистре сравнения отличается от начального значения счётчика. Перед запуском (когда таймер ожидает событие от триггера), конфигурация должна быть следующей: CNT<CCRx≤ARR (в частности при CNT=0).

Например, если мы хотим после обнаружения положительного фронта на TI2 сгенерировать положительный импульс на выходе OC1 шириной tPULSE с задержкой между обнаруженным фронтом и импульсом равной tDELAY:

  1. Первым делом настроим запуск счётчика от положительного фронта на входе TI2:
    • Настраиваем TI2 в качестве входа и подключаем его к сигналу TI2FP2 (записываем CC2S=’01’ в регистр TIMx_CCMR1)
    • Настраиваем TI2FP2 на определение растущего фронта (записываем CC2P=’00’ в регистре TIMx_CCER)
    • Настраиваем TI2FP2 в качестве входа триггера для контроллера slave-режима (подключаем TI2FP2 к сигналу TRGI) (записываем TS=’110′ в регистре TIMx_SMCR)
    • Настраиваем slave-режим на запуск счётчика по растущему фронту сигнала триггера (TRGI) (записываем SMS=’110′ в регистре TIMx_SMCR). (теперь по растущему фронту сигнала TRGI будет устанавливаться в 1 бит CEN регистра TIMx_CR1)
  2. Теперь нужно настроить длительности импульса и паузы. В нашем случае tDELAY будет определяться значением, записанным в регистр TIMx_CCR1, а tPULSE — разницей между TIMx_ARR и TIMx_CCR1:
    • Для того, чтобы сгенерировать сигнал с переходом из 0 в 1 по достижению счётчиком значения TIMx_CCR1 и переходом из 1 в 0 по достижению счётчиком значения TIMx_ARR — нужно включить ШИМ-режим 2 (OC1M=’111′ в регистре TIMx_CCMR1)
    • Далее мы пишем значение для сравнения в TIMx_CCR1 и значение автоматической перезагрузки в TIMx_ARR и генерируем событие UEV, чтобы эти значения переписались в рабочие регистры. Если нужно, то перед этим можно дополнительно включить и настроить предделители, записав OC1PE=’1′ (в регистре TIMx_CCMR1) и ARPE=1 (в регистре TIMx_CR1)
    • Полярность выходного сигнала сбрасываем в 0 (CC1P=0 в регистре TIMx_CCER), чтобы при неактивном состоянии базового выходного сигнала на выходе был ноль
  3. Теперь, поскольку мы хотим получить один единственный импульс, осталось только установить в 1 бит OPM регистра TIMx_CR1 и ждать положительного фронта на входе TI2.

Если бы бит OPM был сброшен, то положительный фронт на TI2 запустил бы периодический процесс генерации импульсов заданной скважности, но в нашем случае, когда бит OPM установлен, первое же после старта событие UEV (которое произойдёт при обнулении счётчика по достижению им значения TIMx_ARR) вызовет остановку счётчика.

Частный случай: OCx fast enable (быстрое включение выхода)

Ещё раз посмотрим на режим одиночного импульса: фронт на входе TIx устанавливает бит CEN, таким образом включая счётчик. Затем равенство значений счётчика и регистра захвата/сравнения переключает выход. Но, для этих операций требуется некоторое количество циклов, что ограничивает минимальную задержку, которую мы можем получить.

Если есть необходимость переключать выход с минимальной задержкой, то можно установить бит OCxFE в регистре TIMx_CCMRx. В результате базовый выходной сигнал OCxREF (и соответственно выход OCx) будет переключаться сразу по событию от триггера, не принимая во внимание результат операции сравнения. При этом новый уровень сигнала OCxREF будет установлен таким же, как если бы случилось совпадение значений счётчика и регистра захвата/сравнения. Быстрое переключение работает только если канал сконфигурирован в режиме ШИМ (1 или 2).

Сброс сигнала OCxREF по внешнему событию

Сигнал OCx_REF для выбранного канала может быть принудительно сброшен в низкий уровень подачей высокого уровня на вход ETRF (эта опция включается установкой в 1 соответствующего бита OCxCE в регистре TIMx_CCMRx). При этом сигнал OCx_REF будет оставаться в состоянии Low до тех пор, пока не случится следующее событие Update (UEV).

Эта функция может быть использована только в режимах сравнения и ШИМ и не работает в режиме форсирования выхода.

Например, сигнал ETR может быть подключен к выходу компаратора и использоваться для ограничения тока (чтобы гасить выход ШИМ по перегрузу).

Режим интерфейса энкодера (Encoder Interface Mode)

Для выбора режима интерфейса энкодера нужно в регистре TIMx_SMCR установить SMS=’001′ (для счёта только по фронту на входе TI2), SMS=’010′ (для счёта только по фронту на входе TI1) или SMS=’011′ (для счёта по фронтам на обоих входах TI1 и TI2).

При использовании интерфейса энкодера счётчик как бы тактируется от одного из внешних сигналов (TI1 или TI2), при этом уровень на другом входе определяет направление счёта. Счёт выполняется от 0 до значения в регистре TIMx_ARR. Все остальные функции (захват, сравнение, предделитель, триггер) при этом работают в нормальном режиме (в соответствии с их настройками).

В этом режиме значение счётчика изменяется автоматически в соответствии со скоростью и направлением инкрементального энкодера, поэтому его содержимое всегда представляет текущую позицию энкодера. Направление счёта соответствует направлению вращения подключенного датчика. Внешний энкодер может быть подключен прямо к ЦПУ без использования какой-либо внешней логики (однако обычно используются внешние компараторы, значительно снижающие уровень шума), при этом третий выход энкодера, который показывает механическое нулевое положение может быть подключен ко входу внешнего прерывания для организации сброса счётчика.

В таблице ниже приведены возможные комбинации настроек интерфейса энкодера и входных сигналов, а также направления счёта в этих комбинациях.

Настройки режима (SMS) Уровень на другом входе (TI1FP1 для TI2, TI2FP2 для TI1) фронт сигнала TI1FP1 фронт сигнала TI2FP2
растущий падающий растущий падающий
счёт только от TI1 (SMS=’010′) высокий вниз (вычитание) вверх (сложение) нет счёта нет счёта
низкий вверх вниз нет счёта нет счёта
счёт только от TI2 (SMS=’001′) высокий нет счёта нет счёта вверх вниз
низкий нет счёта нет счёта вниз вверх
счёт от TI1 и TI2 (SMS=’011′) высокий вниз вверх вверх вниз
низкий вверх вниз вниз вверх

Режим объединения входов по XOR

Для таймеров TIM2 — TIM5 существует возможность подавать на вход фильтра первого входного канала комбинированный по XOR сигнал от входов TIMx_CH1, TIMx_CH2, TIMx_CH3. Эта фишка используется при подключении интерфейсов датчиков Холла (подробности в RM0008, глава 14.3.18, стр.327).

Для выбора этой опции нужно установить в 1 бит TI1S.

Синхронизация счётчиков по внешним сигналам

Контроллер триггера счётчиков TIM2 — TIM5 имеет встроенный контроллер слэйв-режимов, позволяющий синхронизировать счётчики по сигналам на входах триггера. При этом на вход триггера могут подаваться сигналы от внешних входов или от других таймеров (смотрите выше блок-схему). Контроллер слэйв-режимов позволяет выбрать следующие режимы:

  • Режим сброса (Reset Mode)
  • Режим шлюза (Gated Mode)
  • Режим триггера (Trigger Mode)

Режим сброса (Reset Mode)

В этом режиме счётчик и его предделитель реинициализируются по сигналам на входах триггера. Если при этом сброшен бит URS в регистре TIMx_CR1, то будет сгенерировано событие UEV (при этом произойдёт перегрузка значений буферов в рабочие регистры).

Пример использования Reset Mode для сброса счётчика по растущему фронту на входе TI1:

  1. Настраиваем канал 1 на отслеживание растущего фронта на входе TI1. Для этого сначала настраиваем первый канал на вход TI1 (записываем CC1S=’01’ в регистре TIMx_CCMR1). После этого, если нужно, то настраиваем демпфирование для входного фильтра (в примере мы не будем использовать фильтр и оставим IC1F=’0000′). Ну и, наконец, настраиваем канал на отслеживание растущего фронта (записываем CC1P=’0′ в регистре TIMx_CCER). Поскольку сигнал для триггера не проходит предделитель регистра захвата/сравнения, то этот предделитель не используется и настраивать его не нужно
  2. Настраиваем контроллер слэйв-режимов в режим Reset Mode (записываем SMS=’100′ в регистре TIMx_SMCR) и выбираем сигнал TI1FP1 в качестве входа триггера (записываем TS=’101′ в регистре TIMx_SMCR)
  3. Запускаем счётчик (записываем CEN=’1′ в регистре TIMx_CR1)

Счётчик начинает считать, тактируясь от внутреннего источника, и работает как обычно до тех пор, пока не появится растущий фронт на TI1. При появлении растущего фронта счётчик очищается и стартует с нуля. В это же время устанавливается флаг триггера (бит TIF в регистре TIMx_SR) и генерируется запрос на прерывание и/или запрос к DMA, если таковые разрешены (если установлены биты TIE, TDE в регистре TIMx_DIER).

Режим шлюза (Gated Mode)

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

Пример использования Gated Mode для счёта только при низком уровне на входе TI1:

  1. Настраиваем канал 1 на отслеживание низкого уровня на входе TI1. Для этого сначала настраиваем первый канал на вход TI1 (записываем CC1S=’01’ в регистре TIMx_CCMR1). После этого, если нужно, то настраиваем демпфирование для входного фильтра (в примере мы не будем использовать фильтр и оставим IC1F=’0000′). Ну и, наконец, настраиваем вход на отслеживание падающего фронта/низкого уровня (записываем CC1NP/CC1P=’01’ в регистре TIMx_CCER).
  2. Настраиваем контроллер слэйв-режимов в режим Gated Mode (записываем SMS=’101′ в регистре TIMx_SMCR) и выбираем сигнал TI1FP1 в качестве входа триггера (записываем TS=’101′ в регистре TIMx_SMCR)
  3. Запускаем счётчик (записываем CEN=’1′ в регистре TIMx_CR1). Если бит CEN сброшен, то режиме шлюза счётчик не будет считать независимо от уровня сигнала на входе триггера.

Счётчик будет считать всё то время, пока на входе TI1 будет низкий уровень. При обнаружении высокого уровня на TI1 счётчик будет останавливаться. При этом и при остановке, и при начале или возобновлении счёта будет устанавливаться флаг TIF в регистре TIMx_SR.

Режим триггера (Trigger Mode)

В этом режиме счётчик запускается по сигналу на входе триггера.

Пример использования Trigger Mode для включения счётчика по растущему фронту на входе TI2:

  1. Настраиваем канал 2 на отслеживание растущего фронта на входе TI2. Для этого сначала настраиваем второй канал на вход TI2 (записываем CC2S=’01’ в регистре TIMx_CCMR1). После этого, если нужно, то настраиваем демпфирование для входного фильтра (в примере мы не будем использовать фильтр и оставим IC2F=’0000′). Ну и, наконец, настраиваем вход на отслеживание растущего фронта/высокого уровня (записываем CC2P=’1′ в регистре TIMx_CCER).
  2. Настраиваем контроллер слэйв-режимов в режим Trigger Mode (записываем SMS=’110′ в регистре TIMx_SMCR) и выбираем сигнал TI2FP2 в качестве входа триггера (записываем TS=’110′ в регистре TIMx_SMCR)

Теперь после обнаружения растущего фронта на входе TI2 будет автоматически установлен бит CEN, счётчик включится и начнёт считать, тактируясь от внутреннего источника тактирования (при этом счётчик не сбрасывается, а просто стартует). Одновременно с включением будет установлен флаг TIF (и, соответственно, если разрешено, то сгенерируется прерывание).

Режим триггера + внешнее тактирование

Режим внешнего тактирования 2 может быть использован в дополнение к другому слэйв-режиму (исключая режим внешнего тактирования 1 и режим интерфейса энкодера). В этом случае сигнал ETR используется как вход внешнего тактирования, а другой вход может быть использован как вход триггера для работы в режиме сброса, шлюза или триггера. Рекомендуется не выбирать ETR в качестве источника TRGI через биты TS регистра TIMx_SMCR (режим внешнего тактирования 2 включается установкой бита ECE регистра TIMx_SMCR).

Связанная работа таймеров

Таймеры могут быть запрограммированы на работу в паре (master-slave) для синхронизации или каскадного включения. В этом режиме таймер, настроенный в качестве мастера может сбрасывать, запускать, останавливать или тактировать таймер, настроенный в качестве слэйва. Подробнее можно прочитать в Reference Manual (RM0008) в пункте 15.3.15.

Регистры

TIMx_CR1 — регистр настройки. Содержит биты, определяющие режимы работы таймеров.

регистр TIMx_CR1

  • CEN (counter enable): включение(1)/выключение(0) счётчика.
  • UDIS (update disable): выключение(1)/включение(0) события UEV. Когда событие выключено, то установка бита UG или ресет от слэйв-контроллера вызывает реинициализацию счётчика, но не вызывает генерацию события UEV (соответственно, не происходит синхронизация теневых регистров с буферами и не происходит установка флага UIF).
  • URS (update request source): выбор источников генерирования события UEV. Если этот бит сброшен, то событие UEV генерируется при переполнении счётчика, при установке бита UG или при генерации обновления от слэйв-контроллера. Если бит установлен, то UEV генерируется только при переполнении счётчика.
  • OPM (one pulse mode): если бит установлен, то при наступлении события UEV автоматически сбрасывается бит CEN и счётчик останавливается.
  • DIR (direction): если бит установлен, то значение счётчика при счёте уменьшается (вычитающий счётчик), если сброшен, то значение увеличивается (нарастающий счётчик).
  • CMS[1:0] (center-aligned mode selection): выбо режима.
    • 00 (edge-aligned mode): счётчик считает вверх или вниз, в зависимости от значения бита DIR
    • 01 (central-aligned mode 1): счётчик считает вверх и вниз по очереди, флаг OCIF для выходных каналов устанавливается только при счёте вниз
    • 10 (central-aligned mode 2): счётчик считает вверх и вниз по очереди, флаг OCIF для выходных каналов устанавливается только при счёте вверх
    • 11 (central-aligned mode 3): счётчик считает вверх и вниз по очереди, флаг OCIF для выходных каналов устанавливается при счёте в любом направлении
  • ARPE (auto-reload preload enable): включение(1)/выключение(0) буферизации регистра TIMx_ARR
  • CKD[1:0]: коэффициент деления между внутренней частотой тактирования таймера (CK_INT) и частотой сэмплирования, используемой входными цифровыми фильтрами таймера (ETR, TIx):
    • 00: tDTS = tCK_INT
    • 01: tDTS = 2 x tCK_INT
    • 10: tDTS = 4 x tCK_INT
    • 11: Reserved

TIMx_CR2 — регистр настройки. Содержит биты, определяющие режимы работы таймеров.

регистр TIMx_CR2

  • CCDS (capture/compare DMA selection): 0 — запрос к DMA посылается по событию CCx, 1 — запрос к DMA посылается по событию UEV
  • MMS[2:0] (master mode selection): эти биты определяют, какие события таймера будут использоваться для активации выхода триггера (то есть в качестве события TRGO для подчинённых устройств):
    • 000: Reset — в качестве выхода триггера используется бит UG
    • 001: Enable — в качестве выхода триггера используется бит CEN
    • 010: Update — в качестве выхода триггера используется событие UEV
    • 011: Compare Pulse — на выходе триггера формируется положительный импульс при установке флага CC1IF (даже если он уже был установлен).
    • 100: Compare — в качестве выхода триггера используется сигнал OC1REF
    • 101: Compare — в качестве выхода триггера используется сигнал OC2REF
    • 110: Compare — в качестве выхода триггера используется сигнал OC3REF
    • 111: Compare — в качестве выхода триггера используется сигнал OC4REF
  • TI1S (TI selection): 0 — сигнал TI1 подключен ко входу TIMx_CH1, 1 — сигнал TI1 формируется по XOR от входов TIMx_CH1, TIMx_CH2 и TIMx_CH3

TIMx_SMCR — регистр настройки слэйв-режимов. Содержит биты, определяющие режимы работы таймеров.

регистр TIMx_CR2

  • SMS[2:0] (slave mode selection): эти биты определяют режим работы слэйв-контроллера (что и как будет делать слэйв-контроллер):
    • 000: Disabled — слэйв-контроллер выключен, предделитель тактируется напрямую от внутреннего источника (CK_INT)
    • 001: Encoder Mode 1 — счётчик считает вверх/вниз по фронту на TI2FP2 в зависимости от уровня на TI1FP1
    • 010: Encoder Mode 2 — счётчик считает вверх/вниз по фронту на TI1FP1 в зависимости от уровня на TI2FP2
    • 011: Encoder Mode 3 — счётчик считает вверх/вниз по фронтам обоих сигналов (TI1FP1 и TI2FP2) в зависимости от уровня другого сигнала (TI2FP2 для TI1FP1 и наоборот).
    • 100: Reset Mode — растущий фронт на выбранном входе триггера (TRGI) вызывает событие UEV (если разрешено) и реинициализирует счётчик
    • 101: Gated Mode — счётчик выполняет счёт только при высоком уровне на входе триггера (TRGI), при низком уровне счёт останавливается
    • 110: Trigger Mode — растущий фронт на выбранном входе триггера (TRGI) вызывает включение счётчика (установку бита CEN)
    • 111: External Clock Mode 1 — растущий фронт на выбранном входе триггера (TRGI) тактирует счётчик
  • TS[2:0] (trigger selection): эти биты определяют активный вход триггера (их можно менять только при выключенном слэйв-контроллере):
    • 000: внутренний триггер 0 (ITR0)
    • 001: внутренний триггер 1 (ITR1)
    • 010: внутренний триггер 2 (ITR2)
    • 011: внутренний триггер 3 (ITR3)
    • 100: детектор фронта TI1 (TI1F_ED)
    • 101: отфильтрованный сигнал с внешнего входа 1 (TI1FP1)
    • 110: отфильтрованный сигнал с внешнего входа 2 (TI2FP2)
    • 111: внешний вход триггера (ETRF)
  • MSM (master/slave mode): 0 — нет действия, 1 — эффект события на входе TRGI задерживается для обеспечения идеальной синхронизации между текущим таймером и его ведомым устройством (через TRGO). Это полезно, если мы хотим синхронизировать несколько таймеров по одному внешнему событию.
  • ETF[3:0] (external trigger filter): это битовое поле определяет частоту сэмплирования сигнала ETRP и длину цифрового фильтра, применяемого к ETRP:
    • 0000: без фильтрации, сэмплирование на частоте fDTS
    • 0001: fSAMPLING=fCK_INT, N=2
    • 0010: fSAMPLING=fCK_INT, N=4
    • 0011: fSAMPLING=fCK_INT, N=8
    • 0100: fSAMPLING=fDTS/2, N=6
    • 0101: fSAMPLING=fDTS/2, N=8
    • 0110: fSAMPLING=fDTS/4, N=6
    • 0111: fSAMPLING=fDTS/4, N=8
    • 1000: fSAMPLING=fDTS/8, N=6
    • 1001: fSAMPLING=fDTS/8, N=8
    • 1010: fSAMPLING=fDTS/16, N=5
    • 1011: fSAMPLING=fDTS/16, N=6
    • 1100: fSAMPLING=fDTS/16, N=8
    • 1101: fSAMPLING=fDTS/32, N=5
    • 1110: fSAMPLING=fDTS/32, N=6
    • 1111: fSAMPLING=fDTS/32, N=8
  • ETPS[2:0] (external trigger prescaler): предделитель для внешнего сигнала на входе ETRP. Частота ETRP должна быть не более 1/4 CK_INT. Если внешний сигнал слишком быстрый, то для него нужно использовать предделитель:
    • 00: предделитель выключен
    • 01: частота делится на 2
    • 10: частота делится на 4
    • 11: частота делится на 8
  • ECE (external clock enable): 0 — режим внешнего тактирования 2 выключен, 1 — режим внешнего тактирования 2 включен
  • ETP (external trigger polarity): 0 — ETR не инвертирован, активным считается высокий уровень или растущий фронт, 1 — ETR инвертирован, активным считается низкий уровень или падающий фронт

TIMx_DIER — регистр управления прерываниями.

регистр TIMx_DIER

  • UIE: разрешение(1)/запрет(0) генерирования прерывания по событию UEV
  • CC1IE: включение(1)/выключение(0) генерирования прерывания по захвату/сравнению для канала 1
  • CC2IE: включение(1)/выключение(0) генерирования прерывания по захвату/сравнению для канала 2
  • CC3IE: включение(1)/выключение(0) генерирования прерывания по захвату/сравнению для канала 3
  • CC4IE: включение(1)/выключение(0) генерирования прерывания по захвату/сравнению для канала 4
  • TIE: включение(1)/выключение(0) генерирования прерывания от триггера
  • UDE: включение(1)/выключение(0) генерирования запроса к DMA по событию UEV
  • CC1DE: включение(1)/выключение(0) генерирования запроса к DMA по событию от модуля захвата/сравнения 1
  • CC2DE: включение(1)/выключение(0) генерирования запроса к DMA по событию от модуля захвата/сравнения 2
  • CC3DE: включение(1)/выключение(0) генерирования запроса к DMA по событию от модуля захвата/сравнения 3
  • CC4DE: включение(1)/выключение(0) генерирования запроса к DMA по событию от модуля захвата/сравнения 4
  • TDE: включение(1)/выключение(0) генерирования запроса к DMA по событию от триггера

TIMx_SR — регистр статуса

регистр TIMx_SR

  • UIF: флаг ожидания прерывания по событию обновления счётчика (UEV). Сбрасывается программно, записью нуля.
  • CC1IF: флаг ожидания прерывания по захвату/сравнению для канала 1
    • Если канал CC1 настроен на выход, то этот флаг устанавливается в 1 при совпадении значений счётчика и регистра захвата/сравнения 1 с некоторыми исключениями для центрально-выровненного режима (смотрите описание битов CMS регистра TIMx_CR1). Сбрасывается программно.
    • Если канал CC1 настроен на вход, то этот флаг устанавливается по событию захвата на этом канале, а сбрасывается программно или автоматически при чтении регистра захвата/сравнения 1
  • CC2IF: флаг ожидания прерывания по захвату/сравнению для канала 2. Описание аналогично каналу 1.
  • CC3IF: флаг ожидания прерывания по захвату/сравнению для канала 2. Описание аналогично каналу 1.
  • CC4IF: флаг ожидания прерывания по захвату/сравнению для канала 2. Описание аналогично каналу 1.
  • TIF: флаг ожидания прерывания от триггера. Флаг устанавливается аппаратно по событию триггера. Сбрасывается программно
  • CC1OF: флаг перезахвата для канала 1. Устанавливается аппаратно, если канал настроен в режиме захвата по входу и случился второй захват до того, как обработан первый
  • CC2OF: флаг перезахвата для канала 2. Описание аналогично каналу 1
  • CC2OF: флаг перезахвата для канала 3. Описание аналогично каналу 1
  • CC2OF: флаг перезахвата для канала 4. Описание аналогично каналу 1

TIMx_EGR — регистр генерации события

регистр TIMx_EGR

  • UG: установка этого бита в 1 вызывает обновление регистров и реинициализацию счётчика (а также его предделителя),вызывает программную генерацию события UEV (если не установлен бит UDIS).
  • CC1G: программная генерация события захвата/сравнения для канала 1. Если канал 1 настроен на выход, то устанавливается флаг CC1IF. Если канал 1 настроен на вход, то в регистре захвата/сравнения запоминается текущее значение счётчика, устанавливается флаг CC1IF, а также флаг CC1OF (в случае, если флаг CC1IF уже был установлен)
  • CC2G: программная генерация события захвата/сравнения для канала 2. Описание аналогично каналу 1.
  • CC2G: программная генерация события захвата/сравнения для канала 3. Описание аналогично каналу 1.
  • CC2G: программная генерация события захвата/сравнения для канала 4. Описание аналогично каналу 1.
  • TG: программная генерация события триггера. Вызывает установку флага TIF, в результате чего может сгенерироваться соответствующее прерывание или запрос к DMA (если разрешены). Сбрасывается программно

TIMx_CCMR1 — регистр настройки режимов захвата/сравнения

регистр TIMx_CCMR1

  • CC1S[1:0]: выбор направления для канала 1:
    • 00: канал СС1 настроен как выход
    • 01: канал CC1 настроен как вход, сигнал IC1 подключен к TI1
    • 10: канал CC1 настроен как вход, сигнал IC1 подключен к TI2
    • 11: канал CC1 настроен как вход, сигнал IC1 подключен к TRC (работает только если внутренний вход триггера выбран битами TS[2:0] регистра TIMx_SMCR)
  • CC2S: выбор направления для канала 2:
    • 00: канал СС2 настроен как выход
    • 01: канал CC2 настроен как вход, сигнал IC2 подключен к TI2
    • 10: канал CC2 настроен как вход, сигнал IC2 подключен к TI1
    • 11: канал CC2 настроен как вход, сигнал IC2 подключен к TRC (работает только если внутренний вход триггера выбран битами TS[2:0] регистра TIMx_SMCR)

Биты CCxS[1:0] можно изменять только когда соответствующий канал выключен (ССxE=0 в регистре TIMx_CCER). Назначение остальных битов регистра TIMx_CCMR1 зависит от того, как сконфигурирован соответствующий канал битами CCxS[1:0]. На картинке выше названия битов в нижней строке сответствуют случаю, когда канал настроен в качестве входа (режим захвата по входу), а названия битов в верхней строке соответствуют случаю, когда канал настроен в качестве выхода (управление выходом по сравнению).

Для случая, когда канал настроен в качестве входа:

  • IC1PSC[1:0]: предделитель для входного канала IC1:
    • 00: предделитель выключен, захват выполняется по каждому выбранному фронту входного сигнала
    • 01: захват выполняется каждые 2 выбранных события на входе
    • 10: захват выполняется каждые 4 выбранных события на входе
    • 11: захват выполняется каждые 8 выбранных событий на входе
  • IC1F[3:0]: настройка частоты сэмплирования и времени дэмпфирования для цифрового фильтра входного сигнала канала 1. Время дэмпфирования — это фактически количество сэмплов (N), которые должны иметь одинаковое значение чтобы сигнал был признан валидным. Биты могут принимать следующие значения:
    • 0000: fSAMPLING = fDTS, фильтр выключен
    • 0001: fSAMPLING = fCK_INT, N=2
    • 0010: fSAMPLING = fCK_INT, N=4
    • 0011: fSAMPLING = fCK_INT, N=8
    • 0100: fSAMPLING = fDTS/2, N=6
    • 0101: fSAMPLING = fDTS/2, N=8
    • 0110: fSAMPLING = fDTS/4, N=6
    • 0111: fSAMPLING = fDTS/4, N=8
    • 1000: fSAMPLING = fDTS/8, N=6
    • 1001: fSAMPLING = fDTS/8, N=8
    • 1010: fSAMPLING = fDTS/16, N=5
    • 1011: fSAMPLING = fDTS/16, N=6
    • 1100: fSAMPLING = fDTS/16, N=8
    • 1101: fSAMPLING = fDTS/32, N=5
    • 1110: fSAMPLING = fDTS/32, N=6
    • 1111: fSAMPLING = fDTS/32, N=8
  • IC2PSC[1:0]: предделитель для входного канала IC2. Описание аналогично каналу 1
  • IC2F[3:0]: настройка частоты сэмплирования и времени дэмпфирования для цифрового фильтра входного сигнала канала 2. Описание аналогично каналу 1

Для случая, когда канал настроен в качестве выхода:

  • OC1FE: режим быстрого включения выхода для канала 1. Если этот бит сброшен в 0, то выход CC1 работает в обычном режиме и его значение определяется в зависимости от результатов сравнения счётчика и регистра захвата/сравнения. Минимальная задержка между сработкой триггера и активацией выхода составляет 5 тактов. Если бит установлен в 1, то выход переключается сразу по событию триггера, в этом случае задержка уменьшается до 3-х тактов (работает только для режимов ШИМ 1/2)
  • OC1PE: включение(1)/выключение(0) буфера для регистра захвата/сравнения 1
  • OC1M: настройка выходного режима для канала 1 (эти биты определяют поведение сигнала OC1REF):
    • 000: frozen — выход заморожен и результат сравнения таймера и TIMx_CCR1 никак не влияет на выход
    • 001: переключение в 1 (OC1REF) при совпадении счётчика и регистра захвата/сравнения
    • 010: переключение в 0 (OC1REF) при совпадении счётчика и регистра захвата/сравнения
    • 011: переключение к противоположному уровню при совпадении счётчика и регистра захвата/сравнения
    • 100: принудительная установка OCx_REF=0
    • 101: принудительная установка OCx_REF=1
    • 110: ШИМ-режим 1 — канал 1 будет активен (OC1REF=1) пока TIMx_CNT < TIMx_CCR1, в противном случае канал 1 будет неактивен (OC1REF=0)
    • 111: ШИМ-режим 2 — канал 1 будет неактивен (OC1REF=0) пока TIMx_CNT < TIMx_CCR1, в противном случае канал 1 будет активен (OC1REF=1)
  • OC2FE: режим быстрого включения выхода для канала 2. Работает аналогично каналу 1
  • OC2PE: включение(1)/выключение(0) буфера для регистра захвата/сравнения 2
  • OC2M: настройка выходного режима для канала 2 (эти биты определяют поведение сигнала OC2REF). Настройки аналогичны каналу 1

TIMx_CCMR2 — регистр настройки режимов захвата/сравнения

регистр TIMx_CCMR2

Описание аналогично регистру TIMx_CCMR1 (нужно только заменить каналы 1,2 на 3,4)

TIMx_CCER — регистр управления каналами и полярностью входов/выходов

регистр TIMx_ССER

  • CC1E: включение/выключение канала 1:
    • Когда канал настроен в качестве выхода: 0 — OC1 выключен, 1 — OC1 включен (выход соответствует OC1REF и установленной полярности)
    • Когда канал настроен в качестве входа: 0 — захват выключен, 1 — захват включен
  • CC1P: определение активных полярностей входных и выходных сигналов канала 1:
    • Когда канал настроен в качестве выхода: 0 — на OC1 высокий уровень, когда он активен, 1 — на OC1 низкий уровень когда он активен
    • Когда канал настроен в качестве входа:
      • 0 — входной контур чувствителен к растущему фронту сигналов СС1 (захват), TIxFP1 (триггер)
      • 1 — входной контур чувствителен к падающему фронту сигналов СС1 (захват), TIxFP1 (триггер)
  • CC2E: включение/выключение канала 2 (описание аналогично каналу 1).
  • CC2P: определение активных полярностей входных и выходных сигналов канала 2 (описание аналогично каналу 1).
  • CC3E: включение/выключение канала 3 (описание аналогично каналу 1).
  • CC3P: определение активных полярностей входных и выходных сигналов канала 3 (описание аналогично каналу 1).
  • CC4E: включение/выключение канала 4 (описание аналогично каналу 1).
  • CC4P: определение активных полярностей входных и выходных сигналов канала 4 (описание аналогично каналу 1).

Ну и остались только уже известные нам регистры базового модуля: регистр-счётчик TIMx_CNT, регистр предделителя TIMx_PSC и регистр автоматической перезагрузки TIMx_ARR.

С учётом регистра TIMx_PSC итоговое значение частоты счёта таймера получается равным fCK_PSC/(PSC[15:0]+1), где fCK_PSC — частота тактирования таймера (от внутреннего или внешнего источника).

Следует учесть, что пока в регистре TIMx_ARR записан ноль — работа таймера блокирована.

Техника программирования

Программирование таймеров общего назначения осуществляется по следующей схеме:

  1. Настраиваем выводы контроллера, которые планируется использовать с таймерами, в режиме соответствующих альтернативных функций
  2. Настраиваем тактирование таймера в соответствии с выбранным режимом тактирования:
  3. Настраиваем базовый модуль: предделитель (TIMx_PSC) и регистр автоматической перезагрузки (TIMx_ARR)
  4. Настраиваем события, прерывания и запросы к DMA базового модуля
  5. Настраиваем модуль захвата/сравнения в соответствии с выбранным режимом:
  6. Настраиваем события, прерывания и запросы к DMA модуля захвата/сравнения
  7. Включаем таймер установкой бита CEN регистра TIMx_CR1

Пример настройки таймера для работы в режиме ШИМ

В качестве примера приведу программу, в которой таймер TIM2 будет использоваться для генерации ШИМ-сигнала с частотой 200 кГц и скважностью 2 (ну то есть просто меандр).

Текст программы

#include "stm32f10x.h" /* стандартные хидеры */
/* генерирование сигнала ШИМ на выводе PA1 (TIM2_CH2) */
 
/* сначала всякие переменные (ну а как вы хотели с языками высокого уровня) */
GPIO_InitTypeDef		PORT_Structure;		/* структура для настройки линий порта */
TIM_TimeBaseInitTypeDef		TIM2_Structure;		/* структура для базовой настройки таймера */
TIM_OCInitTypeDef		TIM2_OCStructure;	/* структура для настройки выходов канала */
 
ErrorStatus HSEStartUpStatus;		/* переменная для определения ошибки запуска генератора */
 
/* Прототипы функций */
void RCC_Configuration(void);		/* функция настройки RCC */
void GPIO_Configuration(void);		/* функция настройки GPIO */
void TIM2_Configuration(void);		/* функция настройки TIM2 */
 
/* Основная программа */
int main(void) {
	RCC_Configuration();			/* настраиваем RCC */
	GPIO_Configuration();			/* настраиваем GPIO */
	TIM2_Configuration();			/* настраиваем таймер */
 
Work:	goto Work;
}
 
/* Перенастройка системы тактирования */
void RCC_Configuration(void)
{	RCC_DeInit();	/* выключаем всё, что было настроено по умолчанию */
 
	RCC_HSEConfig(RCC_HSE_ON);			/* включаем внешний генератор */
	HSEStartUpStatus = RCC_WaitForHSEStartUp();	/* ждём пока он стабилизируется */
 
	if(HSEStartUpStatus == SUCCESS)
	{	FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);	/* Enable Prefetch Buffer */
		FLASH_SetLatency(FLASH_Latency_2);			/* Flash 2 wait state */
		RCC_HCLKConfig(RCC_SYSCLK_Div1);			/* HCLK = SYSCLK (56 MHz for DMA) */
		RCC_PCLK2Config(RCC_HCLK_Div1);				/* PCLK2 = HCLK (56 MHz for SPI1, USART1, TIM1, EXTI...) */
		RCC_PCLK1Config(RCC_HCLK_Div1);				/* PCLK1 = HCLK (56 MHz for DAC, PWR, CAN, I2C, TIM2...) */
		RCC_ADCCLKConfig(RCC_PCLK2_Div4);			/* ADCCLK = PCLK2/4 (14 MHz for ADC) */
		RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);	/* PLLCLK = 8MHz * 7 = 56 MHz */
		RCC_PLLCmd(ENABLE);					/* Enable PLL */
 
		/* Wait till PLL is ready */
		while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
		{	}
		RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);		/* Select PLL as system clock source */
 
		/* Wait till PLL is used as system clock source */
		while(RCC_GetSYSCLKSource() != 0x08)
		{	}
	}
	/* включаем тактирование AFIO, GPIOA */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
	/* включаем тактирование TIM2 */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}
 
/* Настройка GPIO */
void GPIO_Configuration(void)
{	/* Configure PA1 (TIM2_CH2) as alternate function push-pull */
	PORT_Structure.GPIO_Pin = GPIO_Pin_1;				/* пин 1, сюда подключена линия TIM2_CH2 */
	PORT_Structure.GPIO_Mode = GPIO_Mode_AF_PP;			/* альтернативная функция push-pull */
	PORT_Structure.GPIO_Speed = GPIO_Speed_50MHz;			/* максимальная скорость 50 МГц */
	GPIO_Init(GPIOA, &PORT_Structure);
}
 
/* настройка таймера */
void TIM2_Configuration(void)
{	TIM2_Structure.TIM_ClockDivision = TIM_CKD_DIV1;		/* делитель частоты на 1 (для дидтаймов и входных цифровых фильтров) */
	TIM2_Structure.TIM_CounterMode = TIM_CounterMode_Up;		/* считать от нуля до максимума */
	TIM2_Structure.TIM_Period = 0x118;				/* период таймера 280 тактов (56000/280 = 200 кГц) */
	TIM2_Structure.TIM_Prescaler = 0;				/* предделитель 1 */
	TIM2_Structure.TIM_RepetitionCounter = 0;			/* считать количество обнулений не нужно */
	TIM_TimeBaseInit(TIM2, &TIM2_Structure);			/* инициализируем базовые настройки таймера */
 
	TIM2_OCStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;	/* состояние выхода в состоянии IDLE = reset (сброшен) */
	TIM2_OCStructure.TIM_OCMode = TIM_OCMode_PWM1;			/* режим PWM1 */
	TIM2_OCStructure.TIM_OCPolarity = TIM_OCPolarity_High;		/* полярность сигнала на выходе */
	TIM2_OCStructure.TIM_OutputState = TIM_OutputState_Disable;	/* состояние в выключенном режиме */
	TIM2_OCStructure.TIM_Pulse = 0x8C;				/* ширина импульса 140 тактов (половина периода) */
	TIM_OC2Init(TIM2, &TIM2_OCStructure);				/* инициализируем ШИМ */
 
	TIM_Cmd(TIM2, ENABLE);						/* включаем таймер */
	TIM_CCxCmd(TIM2, TIM_Channel_2, TIM_CCx_Enable);		/* включаем выход первого канала */
	TIM_CtrlPWMOutputs(TIM2, ENABLE);				/* включаем выходы */
}

[свернуть]

Результат работы программы на экране осциллографа:

ШИМ-сигнал на экране осциллографа

  1. Часть 1. Установка MDK, создание проекта, основы Keil uVision
  2. Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32
  3. Часть 3. Карта памяти контроллеров STM32, методы работы с памятью
  4. Часть 4. Регистры, старт и режимы работы контроллеров STM32
  5. Часть 5. Как залить прошивку в контроллер
  6. Часть 6. Настройка системы тактирования
  7. Часть 7. Работа с портами ввода-вывода
  8. Часть 8. Процедуры на ассемблере для STM32
  9. Часть 9. Система прерываний
  10. Часть 10. CMSIS, использование стандартных библиотек и функций
  11. Часть 11. Подключение и использование драйверов из пакета StdPeriph
  12. Часть 12. Работа с модулями USART и UART.
  13. Часть 13. Работа с модулями ADC
  14. Часть 14. Использование DMA
  15. Часть 15. Таймеры. Глава 1 — Введение. Простейшие таймеры
  16. Часть 15. Таймеры. Глава 2 — Таймеры общего назначения TIM9 — TIM14
  17. Часть 15. Таймеры. Глава 3 — Таймеры общего назначения TIM2 — TIM5
  18. Приложение 1. Набор инструкций THUMB-2 и особенности их использования
  19. Приложение 2. Таблица векторов прерываний для семейств STM32F101, STM32F102, STM32F103
  20. Приложение 3. Драйвера и функции библиотеки StdPeriph

Добавить комментарий