Наш канал в telegram

Программирование ARM-контроллеров STM32 на ядре Cortex-M3. Часть 15. Таймеры. Глава 1 — Введение. Простейшие таймеры

Введение

В микроконтроллерах stm32 есть 14 различных таймеров, которые по своим функциональным возможностям условно делятся на три типа: простейшие (TIM6,7), общего назначения (TIM2-5, TIM9-14) и продвинутые (TIM1,8).

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

В принципе в младших линейках, например, в популярных stm32f103 реализованы всего 4 таймера (1 продвинутый и 3 общего назначения), но я всё равно напишу про все варианты, постепенно продвигаясь от простого к сложному.

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

Простейшие таймеры

Итак, простейшие таймеры TIM6 и TIM7 работают полностью независимо друг от друга, не имея никаких общих ресурсов, и каждый из них обладает следующим функционалом:

  • 16-битный автоматически перезагружаемый нарастающий счётчик (то есть он может считать от нуля до заданного значения)
  • 16-битный программируемый предделитель (позволяет увеличивать счётчик не каждый такт, а через заданное количество тактов)
  • контур синхронизации для управления DAC (событие переполнения таймера может служить триггером для DAC)
  • генерация прерываний/запросов к DMA по событию переполнения

Ниже представлена блок-схема таймеров TIM6,7

блок-схема таймеров TIM6,7

Как видите, основу таймера составляют 3 регистра:

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

Все эти регистры могут быть записаны и прочитаны в любое время без остановки таймера.

Интересной особенностью двух последних регистров является то, что они имеют буферизацию. Что это значит? Это значит, что для каждого из них есть реальный рабочий регистр, — в доке он называется теневым (shadow register) и недоступен для прямого доступа, и есть регистр предварительной загрузки (preload register) — буфер, к которому и осуществляется доступ в операциях чтения/записи. На схеме выше эти два регистра выделены цветом и тенью.

Буферизация позволяет осуществлять загрузку данных из регистра предварительной загрузки в рабочий регистр двумя разными способами: немедленно при операции записи в буфер (сквозная запись) или с привязкой к событию обновления — UEV (отложенная запись). Для регистра TIMx_ARR выбор момента синхронизации осуществляется битом ARPE в регистре настройки TIMx_CR1. Для предделителя синхронизация осуществляется только по событию UEV.

Событие UEV (обновление счётчика) генерируется в двух случаях: 1 — при переполнении счётчика (то есть при достижении им значения, записанного в TIMx_ARR), 2 — при установке бита UG в регистре TIMx_ERG (он может быть установлен программно). По сути, это единственное событие, которое может произойти с простейшими таймерами. Вокруг этого события всё и крутится.

Установкой бита UDIS в регистре TIMx_CR1 можно выключить событие обновления. Это позволяет избежать обновления рабочих регистров при записи новых значений в регистры предварительной загрузки. В этом случае событие обновления не происходит до тех пор, пока бит UDIS не будет сброшен в ноль, хотя счётчик и предделитель при достижении заданных значений по прежнему сбрасываются и начинают отсчёт с нуля.

Дополнительно, если установлен бит бит URS в регистре TIMx_CR1, то установка бита UG вызывает генерацию события обновления (UEV), однако при этом не устанавливается флаг UIF (и, соответственно, не генерируется запрос на прерывание и запрос к DMA).

Регистры

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

регистр TIMx_CR1

  • CEN (counter enable): включение(1)/выключение(0) счётчика.
  • UDIS (update disable): выключение(1)/включение(0) события UEV. Когда событие выключено, то установка бита UG вызывает реинициализацию счётчика, но не вызывает генерацию события UEV (соответственно, не происходит синхронизация теневых регистров с буферами, не происходит установка флага UIF и не генерируется запрос к DMA).
  • URS (update request source): выбор источников генерирования события UEV. Если этот бит сброшен, то событие UEV генерируется при переполнении счётчика (то есть при достижении им значения, записанного в TIMx_ARR) или при установке бита UG. Если бит установлен, то UEV генерируется только при переполнении счётчика.
  • OPM (one pulse mode): если бит установлен, то при наступлении события UEV автоматически сбрасывается бит CEN и счётчик останавливается.
  • ARPE: если бит установлен, то данные, записанные в регистр TIMx_ARR переписываются в рабочий регистр по событию UEV. Когда бит сброшен — используется сквозная запись, то есть данные, записанные в TIMx_ARR сразу записываются в рабочий регистр.

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

регистр TIMx_CR2

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

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

регистр TIMx_DIER

  • UDE: включение(1)/выключение(0) генерирования запроса к DMA по событию UEV
  • UIE: разрешение(1)/запрет(0) генерирования прерывания по событию UEV

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

регистр TIMx_SR

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

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

регистр TIMx_EGR

  • UG: установка этого бита в 1 вызывает программную генерацию события UEV (если не установлен бит UDIS) и в любом случае вызывает реинициализацию счётчика таймера и очистку счётчика предделителя.

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

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

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

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

Программирование простейших таймеров осуществляется по классической схеме:

  1. Включаем тактирование таймера. Оба простейших таймера (TIM6 и TIM7) тактируются от шины APB1, соответственно тактирование включается в регистре APB1_ENR или функцией RCC_APB1PeriphClockCmd (из библиотеки StdPeriph)
  2. Настраиваем предделитель (TIMx_PSC) и регистр автоматической перезагрузки (TIMx_ARR). Значения в обоих регистрах можно настроить функцией TIM_TimeBaseInit (из библиотеки StdPeriph).
  3. Настраиваем режим работы регистра автоматической перезагрузки (бит ARPE): отложенная или сквозная запись нового значения. Для настройки можно использовать функцию TIM_ARRPreloadConfig (из библиотеки StdPeriph).
  4. Настраиваем события: 1) Настраиваем источник события UEV: только счётчик или счётчик и бит UG (определяется битом URS). Для настройки можно использовать функцию TIM_UpdateRequestConfig (из библиотеки StdPeriph); 2) Определяем, должно ли вообще генерироваться событие UEV (определяется битом UDIS). Для настройки можно использовать функцию TIM_UpdateDisableConfig (из библиотеки StdPeriph)
  5. Если нужно, то настраиваем DMA. Для простейших таймеров можно только включить/выключить запросы к DMA (определяется битом UDE). Для настройки можно использовать функцию TIM_DMACmd (из библиотеки StdPeriph)
  6. Если нужно, то настраиваем выход TRGO. Задаем, какое событие будет генерировать сигнал TRGO: reset, enable или update (определяется битами MMS[2:0]). Для настройки можно использовать функцию TIM_SelectOutputTrigger (из библиотеки StdPeriph).
  7. Настраиваем прерывания. Для простейших таймеров можно только включить/выключить прерывание от UEV (определяется битом UIE). Для настройки можно использовать функцию TIM_ITConfig.
  8. Включаем таймер установкой бита CEN регистра TIMx_CR1

Примера работы с простейшими таймерами не будет — тут и так всё очень просто, так что на этом на сегодня всё. О работе с более сложными таймерами читайте в следующих главах.

  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. Приложение 1. Набор инструкций THUMB-2 и особенности их использования
  18. Приложение 2. Таблица векторов прерываний для семейств STM32F101, STM32F102, STM32F103
  19. Приложение 3. Драйвера и функции библиотеки StdPeriph

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