В микроконтроллерах 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
Как видите, основу таймера составляют 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 — регистр настройки. Содержит биты, определяющие режимы работы таймеров.
- 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 — регистр настройки. Содержит биты, определяющие режимы работы таймеров.
- MMS[2:0] (master mode selection): эти биты определяют, какие события таймера будут использоваться для активации выхода триггера (то есть в качестве события TRGO для подчинённых устройств):
- 000: Reset — в качестве выхода триггера используется бит UG
- 001: Enable — в качестве выхода триггера используется бит CEN
- 010: Update — в качестве выхода триггера используется событие UEV
TIMx_DIER — регистр управления прерываниями и DMA.
- UDE: включение(1)/выключение(0) генерирования запроса к DMA по событию UEV
- UIE: разрешение(1)/запрет(0) генерирования прерывания по событию UEV
TIMx_SR — регистр статуса
- UIF: флаг ожидания прерывания по событию обновления счётчика (UEV). Этот флаг устанавливается аппаратно в случае переполнения (ну то есть обновления) счётчика при сброшенном бите UDIS или в случае реинициализации счётчика, вызванного установкой бита UG при сброшенных битах URS и UDIS. Сбрасывается программно, записью нуля.
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 записан ноль — работа таймера блокирована.
Программирование простейших таймеров осуществляется по классической схеме:
- Включаем тактирование таймера. Оба простейших таймера (TIM6 и TIM7) тактируются от шины APB1, соответственно тактирование включается в регистре APB1_ENR или функцией RCC_APB1PeriphClockCmd (из библиотеки StdPeriph)
- Настраиваем предделитель (TIMx_PSC) и регистр автоматической перезагрузки (TIMx_ARR). Значения в обоих регистрах можно настроить функцией TIM_TimeBaseInit (из библиотеки StdPeriph).
- Настраиваем режим работы регистра автоматической перезагрузки (бит ARPE): отложенная или сквозная запись нового значения. Для настройки можно использовать функцию TIM_ARRPreloadConfig (из библиотеки StdPeriph).
- Настраиваем события: 1) Настраиваем источник события UEV: только счётчик или счётчик и бит UG (определяется битом URS). Для настройки можно использовать функцию TIM_UpdateRequestConfig (из библиотеки StdPeriph); 2) Определяем, должно ли вообще генерироваться событие UEV (определяется битом UDIS). Для настройки можно использовать функцию TIM_UpdateDisableConfig (из библиотеки StdPeriph)
- Если нужно, то настраиваем DMA. Для простейших таймеров можно только включить/выключить запросы к DMA (определяется битом UDE). Для настройки можно использовать функцию TIM_DMACmd (из библиотеки StdPeriph)
- Если нужно, то настраиваем выход TRGO. Задаем, какое событие будет генерировать сигнал TRGO: reset, enable или update (определяется битами MMS[2:0]). Для настройки можно использовать функцию TIM_SelectOutputTrigger (из библиотеки StdPeriph).
- Настраиваем прерывания. Для простейших таймеров можно только включить/выключить прерывание от UEV (определяется битом UIE). Для настройки можно использовать функцию TIM_ITConfig.
- Включаем таймер установкой бита CEN регистра TIMx_CR1
Примера работы с простейшими таймерами не будет — тут и так всё очень просто, так что на этом на сегодня всё. О работе с более сложными таймерами читайте в следующих главах.
- Часть 1. Установка MDK, создание проекта, основы Keil uVision
- Часть 2. Команды и директивы ассемблера, структура и синтаксис программы. Первая программа для STM32
- Часть 3. Карта памяти контроллеров STM32, методы работы с памятью
- Часть 4. Регистры, старт и режимы работы контроллеров STM32
- Часть 5. Как залить прошивку в контроллер
- Часть 6. Настройка системы тактирования
- Часть 7. Работа с портами ввода-вывода
- Часть 8. Процедуры на ассемблере для STM32
- Часть 9. Система прерываний
- Часть 10. CMSIS, использование стандартных библиотек и функций
- Часть 11. Подключение и использование драйверов из пакета StdPeriph
- Часть 12. Работа с модулями USART и UART.
- Часть 13. Работа с модулями ADC
- Часть 14. Использование DMA
- Часть 15. Таймеры. Глава 1 — Введение. Простейшие таймеры
- Часть 15. Таймеры. Глава 2 — Таймеры общего назначения TIM9 — TIM14
- Часть 15. Таймеры. Глава 3 — Таймеры общего назначения TIM2 — TIM5
- Часть 15. Таймеры. Глава 4 — Продвинутые таймеры TIM1, TIM8
- Часть 16. Создание устройства USB HID в Keil uVision при помощи библиотечного компонента USB
- Приложение 1. Набор инструкций THUMB-2 и особенности их использования
- Приложение 2. Таблица векторов прерываний для семейств STM32F101, STM32F102, STM32F103
- Приложение 3. Драйвера и функции библиотеки StdPeriph