Наш магазин на eBay Наш магазин на AliExpress Наш канал в telegram

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

Особенности

Таймеры общего назначения TIM9 — TIM14 работают полностью независимо друг от друга, не имея никаких общих ресурсов, при этом они обладают следующим функционалом:

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

Блок-схемы

Блок-схема таймеров TIM10/11, TIM13/14:

блок-схема счётчиков TIM10/11, TIM13/14

Блок-схема таймеров TIM9, TIM12:

блок-схема счётчиков TIM9, TIM12

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

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

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

  • 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-режима — выключен). Для TIM10/11 и TIM13/14 это единственный вариант тактирования. Если выбран такой режим, то тактирование начинается сразу после установки в 1 бита CEN.
  • внешнее тактирование (только для TIM9 и TIM12). Для использования этого способа битами SMS[2:0] должен быть выбран режим внешнего тактирования 1. Источник тактового сигнала в этом случае выбирается битами TS[2:0]. Таким источником могут быть:
    • внешние входы (TIx) — передний или задний фронт на выбранном выходе
    • внутренние входы триггера (ITRx) — каскадно подключенные к выходам других таймеров)

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

  1. Настроить TI2 в качестве входа для канала CC2 (записать CC2S=’01’ в регистре TIMx_CCMR1)
  2. Настроить время демпфирования для входного фильтра (записать IC2F[3:0] в регистре TIMx_CCMR1, если демпфирование не нужно, то IC2F[3:0]=’0000′)
  3. Выбрать счёт по переднему фронту для канала CC2 (записать CC2P/CC2NP=’00’ в регистре TIMx_CCER)
  4. Настроить таймер на режим внешнего тактирования 1 (записать SMS=’111′ в регистре TIMx_SMCR)
  5. Выбрать TI2 в качестве источника входного сигнала для триггера (записать TS=’110′ в регистре TIMx_SMCR)
  6. Включить таймер (записать CEN=’1′ в регистре TIMx_CR1)

Обратите внимание, что предделитель регистра захвата/сравнения не используется для триггера и, соответственно, настраивать его в данном примере не нужно.

Теперь при возникновении растущего фронта на входе TI2, счётчик будет произведить очередной отсчёт и устанавливать флаг TIF.

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

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

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

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

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

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

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

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

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

Когда происходит «захват» — устанавливается соответствующий флаг CCxIF (в регистре TIMx_SR). Если «захват» случился в тот момент, когда флаг 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) (только для TIM9/12)

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

  • Один и тот же физический вход (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 (записать CC1NP/CC1P=’00’ в регистре TIMx_CCER). По этому фронту будет происходить захват значения таймера в регистр TIMx_CCR1 и сброс таймера (то есть по нему будет отсчитываться период)
  3. Настроить TI1 в качестве входа для канала CC2 (записать CC2S=’10’ в регистре TIMx_CCMR1)
  4. Выбрать падающий фронт активным фронтом сигнала TI1FP2 (записать CC2P/CC2NP=’11’ в регистре 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′) состояние. Далее итоговый выходной сигнал (OCx) устанавливается в соответствии со значением сигнала OCxREF и запрограммированной полярностью выходного сигнала (бит CCxP регистра TIMx_CCER)
  • Устанавливается флаг ожидания прерывания от модуля захвата/сравнения (CCxIF) в регистре статуса (TIMx_SR)
  • Генерируется прерывание, если оно разрешено соответствующим битом (CCxIE=’1′ в регистре TIMx_DIER)

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

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

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

  1. Настраиваем источник тактирования таймеров (внутренний, внешний) и предделитель
  2. Записываем нужные значения в регистры TIMx_ARR и TIMx_CCRx
  3. Если нужно — разрешаем прерывание от нужного канала модуля захвата/сравнения (установкой бита CCxIE)
  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.

Например, пусть мы выбрали ШИМ-режим 1. В этом случае базовый выходной сигнал (OCxREF) будет активным (и, соответственно, высоким) до тех пор, пока TIMx_CNT меньше TIMx_CCRx, в противном случае он станет неактивным (и, соответственно, низким). Если значение в регистре TIMx_CCRx больше, чем значение в регистре TIMx_ARR тогда сигнал OCxREF будет постоянно удерживаться в активном состоянии. Если значение в регистре TIMx_CCRx = 0, то сигнал OCxREF будет постоянно удерживаться в неактивном состоянии.

Режим одиночного импульса (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/CC2NP=’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).

Синхронизация счётчиков по внешним сигналам (только для TIM9/12)

Контроллер триггера счётчиков TIM9/12 имеет встроенный контроллер слэйв-режимов, позволяющий синхронизировать счётчики по сигналам на входах триггера. При этом на вход триггера могут подаваться сигналы от внешних входов (TI1FP1, TI2FP2) или от других таймеров (ITR0-3) (смотрите выше блок-схему таймеров TIM9/12). Контроллер слэйв-режимов позволяет выбрать следующие режимы:

  • Режим сброса (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′). Ну и, наконец, настраиваем канал на отслеживание растущего фронта/высокого уровня (записываем CC1NP/CC1P=’00’ в регистре TIMx_CCER). Поскольку сигнал для триггера не проходит предделитель регистра захвата/сравнения, то этот предделитель не используется и настраивать его не нужно
  2. Настраиваем контроллер слэйв-режимов в режим Reset Mode (записываем SMS=’100′ в регистре TIMx_SMCR) и выбираем сигнал TI1FP1 в качестве входа триггера (записываем TS=’101′ в регистре TIMx_SMCR)
  3. Запускаем счётчик (записываем CEN=’1′ в регистре TIMx_CR1)

Счётчик начинает считать, тактируясь от внутреннего источника, и работает как обычно до тех пор, пока не появится растущий фронт на TI1. При появлении растущего фронта счётчик очищается и стартует с нуля. В это же время устанавливается флаг триггера (бит TIF в регистре TIMx_SR) и генерируется запрос на прерывание, если оно разрешено (если установлен бит TIEв регистре 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′). Ну и, наконец, настраиваем вход на отслеживание растущего фронта/высокого уровня (записываем CC2NP/CC2P=’00’ в регистре TIMx_CCER).
  2. Настраиваем контроллер слэйв-режимов в режим Trigger Mode (записываем SMS=’110′ в регистре TIMx_SMCR) и выбираем сигнал TI2FP2 в качестве входа триггера (записываем TS=’110′ в регистре TIMx_SMCR)

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

Каскадное включение таймеров

Во всех приведённых выше примерах мы использовали сигнал с внешнего входа в качестве синхросигнала для выбранного слэйв-режима, однако в качестве такого синхросигнала можно использовать также и выход TRGO от контроллера триггера другого таймера (для которого в этом случае нужно настроить режим мастера). В таблице ниже показано, выходы TRGO каких таймеров могут быть подключены ко входам триггеров таймеров TIM9/12:

Slave TIM ITR0 (TS=000) ITR1 (TS=001) ITR2 (TS=010) ITR3 (TS=011)
TIM9 TIM2 TIM3 TIM10 TIM11
TIM12 TIM4 TIM5 TIM13 TIM14

Регистры

Поскольку функционал таймеров TIM9/12 и TIM10/11/13/14 несколько отличается, то и набор доступных регистров, а также битов в одних и тех же регистрах, у них тоже отличается. На картинках ниже регистры и биты, доступные только для TIM9/12, будут выделены светло-зелёным цветом, а регистры и биты, доступные только для TIM10/11/13/14, будут выделены голубым цветом. Общие регистры и биты никак выделены не будут.

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 и счётчик останавливается.
  • ARPE: включение(1)/выключение(0) буферизации регистра TIMx_ARR
  • CKD[1:0]: коэффициент деления между внутренней частотой тактирования таймера (CK_INT) и частотой сэмплирования, используемой входными цифровыми фильтрами таймера:
    • 00: tDTS = tCK_INT
    • 01: tDTS = 2 x tCK_INT
    • 10: tDTS = 4 x tCK_INT
    • 11: Reserved

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

регистр TIMx_CR2

  • MMS[2:0] (master mode selection): эти биты определяют, какие события таймера будут использоваться для активации выхода триггера (то есть в качестве события TRGO для подчинённых устройств):
    • 000: Reset — в качестве выхода триггера используется бит UG
    • 001: Enable — в качестве выхода триггера используется бит CEN
    • 010: Update — в качестве выхода триггера используется событие UEV
    • 011: Compare Pulse — на выходе триггера формируется положительный импульс при установке флага CC1IF (даже если он уже был установлен).
    • 100: Compare — в качестве выхода триггера используется сигнал OC1REF

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

регистр TIMx_CR2

  • SMS[2:0] (slave mode selection): эти биты определяют режим работы слэйв-контроллера (что и как будет делать слэйв-контроллер):
    • 000: Disabled — слэйв-контроллер выключен, предделитель тактируется напрямую от внутреннего источника (CK_INT)
    • 100: Reset Mode — растущий фронт на выбранном входе триггера (TRGI) вызывает событие UEV (если разрешено) и реинициализирует счётчик
    • 101: Gated Mode — счётчик выполняет счёт только при высоком уровне на входе триггера (TRGI), при низком уровне счёт останавливается
    • 011: Trigger Mode — растущий фронт на выбранном входе триггера (TRGI) вызывает включение счётчика (установку бита CEN)
  • 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)

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

регистр TIMx_DIER

  • UIE: разрешение(1)/запрет(0) генерирования прерывания по событию UEV
  • CC1IE: включение(1)/выключение(0) генерирования прерывания по захвату/сравнению для канала 1
  • CC2IE: включение(1)/выключение(0) генерирования прерывания по захвату/сравнению для канала 2
  • TIE: включение(1)/выключение(0) генерирования прерывания от триггера

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

регистр TIMx_SR

  • UIF: флаг ожидания прерывания по событию обновления счётчика (UEV). Этот флаг устанавливается аппаратно в случае переполнения (ну то есть обновления) счётчика при сброшенном бите UDIS или в случае реинициализации счётчика, вызванного установкой бита UG или контроллером слэйв-режимов при сброшенных битах URS и UDIS. Сбрасывается программно, записью нуля.
  • CC1IF: флаг ожидания прерывания по захвату/сравнению для канала 1
    • Если канал CC1 настроен на выход, то этот флаг устанавливается в 1 при совпадении значений счётчика и регистра захвата/сравнения 1. Если содержимое регистра захвата/сравнения 1 больше содержимого регистра автоматической перезагрузки, флаг устанавливается при переполнении счётчика. Сбрасывается программно.
    • Если канал CC1 настроен на вход, то этот флаг устанавливается по событию захвата на этом канале, а сбрасывается программно или автоматически при чтении регистра захвата/сравнения 1
  • CC2IF: флаг ожидания прерывания по захвату/сравнению для канала 2. Всё аналогично каналу 1 (кроме номера канала)
  • TIF: флаг ожидания прерывания от триггера. Флаг устанавливается аппаратно по событию триггера: по положительному фронту сигнала TRGI во всех слэйв-режимах, кроме режима шлюза, и при старте/останове счёта в режиме шлюза. Сбрасывается программно
  • CC1OF: флаг перезахвата для канала 1. Устанавливается аппаратно, если канал настроен в режиме захвата по входу и случился второй захват до того, как обработан первый
  • CC2OF: флаг перезахвата для канала 2. Всё аналогично каналу 1

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

регистр TIMx_EGR

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

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

регистр TIMx_EGR

  • 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_CCER — регистр управления каналами и полярностью входов/выходов

регистр TIMx_EGR

  • CC1E: включение/выключение канала 1:
    • Когда канал настроен в качестве выхода: 0 — OC1 выключен, 1 — OC1 включен (выход соответствует OC1REF и установленной полярности)
    • Когда канал настроен в качестве входа: 0 — захват выключен, 1 — захват включен
  • CC1P: определение активных полярностей входных и выходных сигналов канала 1:
    • Когда канал настроен в качестве выхода: 0 — на OC1 высокий уровень, когда он активен, 1 — на OC1 низкий уровень когда он активен
    • Когда канал настроен в качестве входа — пара CC1NP/CC1P определяет активные полярности входных сигналов TI1FP1 и TI2FP1:
      • 00 — входной контур чувствителен к растущему фронту сигналов TIxFP1 (захват, триггер)
      • 01 — входной контур чувствителен к падающему фронту сигналов TIxFP1 (захват, триггер)
      • 10 — reserved
      • 11 — входной контур чувствителен к обоим фронтам сигналов TIxFP1
  • CC1NP: определение активных полярностей входных и выходных сигналов канала 1:
    • Когда канал настроен в качестве выхода: должен оставаться сброшенным
    • Когда канал настроен в качестве входа: используется совместно с битом CC1P
  • CC2E: включение/выключение канала 1 (настройки аналогичны каналу 1)
  • CC1P: определение активных полярностей входных и выходных сигналов канала 2 (настройки аналогичны каналу 1)
  • CC1NP: определение активных полярностей входных и выходных сигналов канала 2 (настройки аналогичны каналу 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. Настраиваем события и прерывания базового модуля
  5. Настраиваем модуль захвата/сравнения в соответствии с выбранным режимом:
  6. Настраиваем события и прерывания модуля захвата/сравнения
  7. Включаем таймер установкой бита CEN регистра TIMx_CR1

Вот в общем-то на сегодня и всё. Примера опять не будет, — всё равно этих таймеров нет в младших линейках, так же как и простейших. Ладно, ладно, не бросайтесь помидорами, — в следующей статье про TIM2-5 пример обязательно будет.

  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. Часть 15. Таймеры. Глава 4 — Продвинутые таймеры TIM1, TIM8
  19. Часть 16. Создание устройства USB HID в Keil uVision при помощи библиотечного компонента USB
  20. Приложение 1. Набор инструкций THUMB-2 и особенности их использования
  21. Приложение 2. Таблица векторов прерываний для семейств STM32F101, STM32F102, STM32F103
  22. Приложение 3. Драйвера и функции библиотеки StdPeriph

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