Таймеры: прерывание по переполнению и ШИМ
Таймер общего назначения считает такты сам, без участия ядра: может раз в заданное время вызывать прерывание, а может выдавать на вывод ШИМ, пока программа занята другим. Настроим TIM2 на прерывание дважды в секунду, а TIM3 — на ШИМ 1 кГц для плавного изменения яркости светодиода.
Обновлено Редакция GAW
STM32 с нуляурок 7 из 840 мин
Цель урока: Рассчитывать PSC и ARR для нужной частоты, получать прерывание таймера по переполнению и выдавать ШИМ с регулируемой скважностью на выход канала таймера.
У STM32F103C8 четыре таймера: расширенный TIM1 и три таймера общего назначения TIM2, TIM3 и TIM4 (таблица 2 DS5319). Все они построены вокруг одного и того же блока — 16-битного счётчика с делителем и регистром перезагрузки (RM0008, разд. 15.3.1). Обзор режимов — захвата, энкодера, одиночного импульса, мёртвого времени — в статье «Таймеры STM32», а здесь — два базовых применения.
Откуда частота таймера
TIM2–TIM4 сидят на шине APB1. После урока 4 она работает на 36 МГц, потому что предел APB1 — 36 МГц. Но таймеры получают не 36, а 72 МГц: по разделу 7.2 RM0008 (с. 94), если делитель шины APB не равен 1, частота таймеров на ней вдвое выше частоты шины. Эту деталь легко пропустить и получить таймер, который идёт вдвое быстрее расчёта. Тактирование таймера включают в RCC_APB1ENR: биты TIM2EN и TIM3EN.
Делитель PSC и перезагрузка ARR
Тактовый сигнал таймера проходит через делитель PSC: частота счёта CK_CNT = fCK_PSC / (PSC + 1) (разд. 15.4.11), то есть делить можно на 1–65 536. В режиме счёта вверх счётчик CNT идёт от 0 до значения ARR, затем начинает снова с нуля и формирует событие обновления — UEV (разд. 15.3.2, с. 369). Отсюда частота событий:
f = fTIM / ((PSC + 1) × (ARR + 1))
Для TIM2 и двух событий в секунду (расчёт наш): PSC = 7199 даёт 72 МГц / 7200 = 10 кГц, ARR = 4999 — 10 кГц / 5000 = 2 Гц. Пар PSC и ARR с одним произведением обычно много; подобрать их для любой частоты и сразу увидеть погрешность поможет калькулятор таймера МК.
Регистры PSC и ARR буферизованы. Новое значение PSC начинает действовать только со следующего события обновления (разд. 15.3.1), ARR — тоже, если включена предзагрузка ARPE. При первом запуске события ещё не было, поэтому программа вызывает его сама — записью бита UG в TIMx_EGR. Побочный эффект: UG тоже ставит флаг UIF (разд. 15.4.5, при URS = 0), так что флаг после UG нужно сбросить, иначе прерывание сработает сразу после разрешения.
Прерывание TIM2 по переполнению
Флаг UIF в TIMx_SR имеет тип rc_w0: бит сбрасывается записью нуля, запись единицы ничего не меняет (разд. 2.2 RM0008). Поэтому флаг сбрасывают так:
TIM2->SR = ~TIM_SR_UIF; /* 0 into UIF, 1 (no effect) into the other flags */
а не TIM2->SR &= ~TIM_SR_UIF. Чтение-изменение-запись здесь опасно: если между чтением и записью таймер поставит другой флаг, например CC1IF, запись прочитанного нуля сбросит и его. Запись единиц во все остальные биты ни на что не влияет — так же сбрасывает флаги макрос __HAL_TIM_CLEAR_FLAG из HAL.
Прерывание по обновлению разрешает бит UIE регистра TIMx_DIER, а в NVIC — TIM2_IRQn = 28, позиция 28 таблицы векторов (табл. 63).
ШИМ на TIM3
Широтно-импульсная модуляция — прямоугольный сигнал постоянной частоты с изменяемой долей единицы. Что это даёт светодиоду и двигателю и как выбрать частоту, рассказано в статье глоссария ШИМ и в калькуляторе ШИМ. Каналы таймера сравнивают CNT с регистрами CCRx и управляют выходом. В режиме PWM mode 1 при счёте вверх опорный сигнал OCxREF равен единице, пока CNT < CCRx, и нулю дальше (разд. 15.3.9, с. 388). Скважность — CCRx / (ARR + 1); при CCRx = 0 выход постоянно в нуле, при CCRx больше ARR — постоянно в единице.
Настройка канала 1 по разделу 15.3.9:
TIMx_CCMR1: поле OC1M = 110 — PWM mode 1, бит OC1PE — предзагрузка CCR1 (новое значение скважности применяется только на границе периода, без укороченных импульсов). Поле CC1S после сброса равно 00 — канал работает на выход;TIMx_CCER: бит CC1E включает выход, CC1P = 0 — активный уровень высокий;TIMx_CR1: ARPE — предзагрузка ARR;- перед запуском — UG, чтобы все предзагруженные регистры переписались в рабочие.
Выход TIM3_CH1 без переназначения — вывод PA6 (DS5319, табл. 5; RM0008, разд. 9.4.2). Режим вывода по таблице 23 RM0008 — альтернативная функция push-pull. Подключите к PA6 внешний светодиод через резистор 330 Ом к земле: при прямом напряжении красного светодиода около 2 В ток составит примерно (3,3 − 2) / 330 ≈ 4 мА (расчёт наш), а выводы STM32F103, кроме PC13–PC15, отдают до 8 мА (DS5319, разд. 5.3.13). Резистор под другой светодиод посчитает калькулятор резистора для светодиода.
Для TIM3 возьмём PSC = 71: счётчик идёт с частотой 1 МГц, и при ARR = 999 период — 1000 мкс, то есть ШИМ 1 кГц со скважностью от 0 до 100 % шагами по 0,1 % (расчёт наш).
Программа
/* main.c, lesson 7: TIM2 interrupt toggles PC13 at 2 Hz, TIM3 PWM fades an LED on PA6 */
#include "stm32f1xx.h"
#include "clock.h"
void TIM2_IRQHandler(void)
{
if (TIM2->SR & TIM_SR_UIF) {
TIM2->SR = ~TIM_SR_UIF; /* rc_w0: write 0 to clear */
if (GPIOC->ODR & GPIO_ODR_ODR13)
GPIOC->BSRR = GPIO_BSRR_BR13;
else
GPIOC->BSRR = GPIO_BSRR_BS13;
}
}
static void tim2_init_2hz(void)
{
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
TIM2->PSC = 7200u - 1u; /* 72 MHz / 7200 = 10 kHz */
TIM2->ARR = 5000u - 1u; /* 10 kHz / 5000 = 2 Hz */
TIM2->EGR = TIM_EGR_UG; /* load PSC and ARR now */
TIM2->SR = ~TIM_SR_UIF; /* UG has set UIF: clear it */
TIM2->DIER = TIM_DIER_UIE;
NVIC_SetPriority(TIM2_IRQn, 3u);
NVIC_EnableIRQ(TIM2_IRQn);
TIM2->CR1 = TIM_CR1_CEN;
}
static void tim3_pwm_init(void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
/* PA6 = TIM3_CH1: alternate function push-pull, 2 MHz (CNF = 10, MODE = 10) */
GPIOA->CRL = (GPIOA->CRL & ~(GPIO_CRL_CNF6 | GPIO_CRL_MODE6))
| (0x2u << GPIO_CRL_CNF6_Pos) | (0x2u << GPIO_CRL_MODE6_Pos);
TIM3->PSC = 72u - 1u; /* 1 MHz counter */
TIM3->ARR = 1000u - 1u; /* 1 kHz PWM, 1000 steps */
TIM3->CCR1 = 0u;
TIM3->CCMR1 = (TIM3->CCMR1 & ~(TIM_CCMR1_OC1M | TIM_CCMR1_CC1S))
| (0x6u << TIM_CCMR1_OC1M_Pos) /* PWM mode 1 */
| TIM_CCMR1_OC1PE; /* CCR1 preload */
TIM3->CCER |= TIM_CCER_CC1E; /* output on, active high */
TIM3->CR1 |= TIM_CR1_ARPE;
TIM3->EGR = TIM_EGR_UG; /* move PSC, ARR, CCR1 to the shadow registers */
TIM3->CR1 |= TIM_CR1_CEN;
}
int main(void)
{
uint32_t hclk = clock_init();
systick_init(hclk);
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
GPIOC->CRH = (GPIOC->CRH & ~(GPIO_CRH_MODE13 | GPIO_CRH_CNF13))
| (0x2u << GPIO_CRH_MODE13_Pos);
tim2_init_2hz();
tim3_pwm_init();
uint32_t duty = 0;
int32_t step = 5;
for (;;) {
TIM3->CCR1 = duty; /* applied at the next period */
delay_ms(10u);
if (duty == 0u && step < 0)
step = -step;
else if (duty >= 1000u && step > 0)
step = -step;
duty = (uint32_t)((int32_t)duty + step);
}
}
Расчёты PSC и ARR в программе верны только для частоты таймеров 72 МГц, то есть когда clock_init() вернула 72 МГц; при работе от HSI все частоты будут в 9 раз ниже. Светодиод PC13 мигает раз в секунду (переключение дважды в секунду) — и это делает прерывание, а не основной цикл. Внешний светодиод на PA6 плавно разгорается за 2 секунды и так же гаснет: 200 шагов по 10 мс в каждую сторону (расчёт наш). Основной цикл только меняет CCR1 раз в 10 мс, а сами импульсы формирует таймер.
Обработчик TIM2_IRQHandler — единственный, кто меняет PC13, поэтому чтение ODR и запись в BSRR в нём безопасны.
На STM32F4
У STM32F411 есть те же TIM2–TIM5, но TIM2 и TIM5 там 32-битные, а TIM3 и TIM4 — 16-битные (RM0383, с. 313): на TIM2 при 100 МГц и PSC = 0 период до 2³² / 100 МГц ≈ 43 с (расчёт наш). Правило удвоения частоты то же — при делителе APB, не равном 1, TIMxCLK = 2 × PCLKx (RM0383, с. 95; бит TIMPRE после сброса равен нулю). Выход TIM3_CH1 на PA6 включают номером альтернативной функции AF2 в GPIOA->AFR[0] и режимом MODER = 10. Регистры каналов — CCMR1, CCER, CCR1 — и биты PWM mode 1 те же.
Задание
- Как получить на PA6 ШИМ 20 кГц — вне слышимого диапазона, чтобы обмотка мотора не пищала? Какой будет шаг регулировки скважности?
- Что изменится, если убрать бит OC1PE?
Ответ и решение
-
72 МГц / 20 кГц = 3600 тактов на период. Можно взять PSC = 0 и ARR = 3599: тогда скважность меняется шагами 1/3600 ≈ 0,028 %. Или PSC = 3 (18 МГц) и ARR = 899 — шаг 1/900. Чем меньше PSC, тем мельче шаг скважности (расчёт наш).
-
Без предзагрузки новое значение CCR1 начинает действовать сразу, в середине периода: по разделу 15.3.9 RM0008 (с. 387) таймер сравнивает CNT и CCRx постоянно. Возможны два сбоя. Если выход ещё в единице, а новое значение меньше текущего CNT, условие CNT < CCR1 перестаёт выполняться, и импульс обрывается раньше — в этом периоде он короче и старого, и нового. Если выход уже упал, а новое значение больше текущего CNT, условие снова выполняется, и в том же периоде появляется второй, лишний импульс. На светодиоде это незаметно, а на мосту двигателя или в источнике питания может быть опасно. С OC1PE значение переносится в рабочий регистр только по событию обновления, на границе периода, и каждый период получается целым.
Что дальше
В уроке 8 АЦП будет непрерывно измерять два канала, а DMA — складывать результаты в массив без участия ядра. Регистры таймеров STM32F1 с битами — на странице атласа регистров TIM STM32F1. Термины урока — в статьях глоссария «Предделитель», «Захват и сравнение» и «Прерывание по переполнению таймера». Готовый код таймера в режиме ШИМ для любого канала и вывода сделает генератор инициализации STM32.
Частые вопросы
Почему таймер на шине APB1 считает от 72 МГц, а не от 36 МГц?
Так устроено дерево тактирования STM32F1: если делитель шины APB не равен 1, частота таймеров на этой шине автоматически удваивается (RM0008, разд. 7.2). При HCLK = 72 МГц и делителе APB1 = 2 шина работает на 36 МГц, а TIM2, TIM3 и TIM4 получают 72 МГц. Если же делитель равен 1, таймеры тактируются частотой шины.
Почему прерывание таймера срабатывает сразу после запуска?
Запись UG в TIMx_EGR, которой загружают PSC и ARR, сама вызывает событие обновления и ставит флаг UIF, если бит URS равен нулю. Если прерывание UIE уже разрешено, обработчик вызовется сразу. Сбросьте UIF после UG и только потом разрешайте прерывание — или установите URS = 1, чтобы прерывание шло только от переполнения.
Можно ли делать ШИМ на TIM1 так же, как на TIM3?
Почти так же, но у TIM1 — таймера с расширенным управлением — выходы дополнительно включает бит MOE регистра TIM1_BDTR. Пока MOE = 0, выходы каналов отключены или находятся в неактивном состоянии, даже если CC1E установлен. После настройки каналов TIM1 нужно записать TIM1->BDTR |= TIM_BDTR_MOE.
Источники
- STMicroelectronics. RM0008 Rev 21. Reference manual STM32F101xx–STM32F107xx — разд. 2.2: rc_w0 — бит сбрасывается записью 0, запись 1 не действует; разд. 7.2 (с. 94): при делителе APB, не равном 1, частота таймеров вдвое выше частоты шины; табл. 23 (с. 166): выход канала TIM2–TIM5 — альтернативная функция push-pull; разд. 9.4.2: TIM3_REMAP = 00 — CH1 на PA6; разд. 15.3.1 (с. 368–369): 16-битный счётчик, ARR с предзагрузкой (ARPE), PSC делит на 1–65 536 и буферизован — новое значение действует со следующего события обновления; разд. 15.3.2 (с. 369): в режиме счёта вверх счётчик идёт от 0 до ARR и формирует переполнение, событие обновления можно вызвать битом UG; разд. 15.3.9 (с. 387–388): PWM mode 1 — OCxM = 110, нужна предзагрузка OCxPE, перед запуском — UG; CNT и CCRx сравниваются всегда; в режиме 1 при счёте вверх OCxREF = 1, пока CNT < CCRx, CCRx > ARR — постоянно 1, CCRx = 0 — постоянно 0; разд. 15.4.5 (с. 410–411): UIF ставится при переполнении и при UG, если URS = 0; разд. 15.4.9: CC1E — включение выхода, CC1P — полярность; разд. 15.4.11: CK_CNT = fCK_PSC / (PSC + 1); табл. 63: TIM2 — позиция 28
- STMicroelectronics. DS5319 Rev 20. STM32F103x8, STM32F103xB datasheet — табл. 5: PA6 — ADC12_IN6, SPI1_MISO, TIM3_CH1 (по умолчанию), вывод без отметки FT; разд. 5.3.13: вывод отдаёт до ±8 мА
- STMicroelectronics. cmsis-device-f1 v4.3.5 (stm32f103xb.h) и stm32f1xx-hal-driver v1.1.10 (stm32f1xx_hal_tim.h) — TIM_SR_UIF, TIM_DIER_UIE, TIM_EGR_UG, TIM_CR1_ARPE, TIM_CR1_CEN, TIM_CCMR1_OC1M (позиция 4), TIM_CCMR1_OC1PE, TIM_CCER_CC1E, TIM2_IRQn = 28; макрос __HAL_TIM_CLEAR_FLAG пишет в SR значение ~(флаг)
- STMicroelectronics. RM0368 Rev 6 (STM32F401) и RM0383 Rev 4 (STM32F411); STM32_open_pin_data — RM0368 с. 316 и RM0383 с. 313: TIM3 и TIM4 16-битные, TIM2 и TIM5 32-битные; RM0383 с. 95: при TIMPRE = 0 и делителе APB, не равном 1, TIMxCLK = 2 × PCLKx; для STM32F411 TIM3_CH1 на PA6 — AF2
Нашли ошибку?
Смотрите также
- Таймеры STM32Тактирование, PSC/ARR, ШИМ, мёртвое время, захват, энкодер, OPM, синхронизация
- Таймер AVR и STM32Предделитель, OCRnA, PSC и ARR под частоту, мёртвое время, энкодер
- ЦАП на ШИМПульсации после RC, установление, разрешение
- ШИМPWM: среднее напряжение через коэффициент заполнения
- Предделитель таймераPrescaler: делитель тактов перед счётчиком таймера