Аппаратный таймер отсчитывает такты, поделённые предделителем, и формирует событие — прерывание или период ШИМ — каждые TOP + 1 отсчётов. Задача сводится к тому, чтобы подобрать предделитель и значение регистра периода так, чтобы частота событий была как можно ближе к нужной.
Формулы
Для ATmega328P в режиме CTC (сброс по совпадению) и в Fast PWM с регистром периода:
где N — предделитель, TOP — значение OCRnA (или ICR1 у Timer1), fOCnA — частота меандра на выводе OCnA, когда вывод переключается при каждом совпадении. У Timer0 и Timer1 предделители 1, 8, 64, 256 и 1024, у Timer2 добавлены 32 и 128.
Для таймера STM32 событие обновления происходит каждые (PSC + 1) · (ARR + 1) тактов:
PSC и ARR 16-битные; у TIM2 и TIM5 во многих семействах ARR 32-битный.
Как выбирается предделитель
Калькулятор перебирает предделители и для каждого находит ближайшее значение регистра периода. Из вариантов с наименьшей ошибкой выбирается тот, где предделитель меньше: регистр периода тогда больше, а значит, у ШИМ больше шагов скважности. Остальные варианты показаны списком — иногда удобнее «круглый» отсчёт, например 1 МГц.
Пример: несущая 38 кГц для ИК-передатчика на выводе OC2A ATmega328P при 16 МГц. Меандр на выводе вдвое медленнее событий, поэтому нужна частота событий 76 кГц: предделитель 1, OCR2A = 210, на выводе получится 37 915 Гц — на 0,22 % ниже 38 кГц, что приёмники ИК-сигналов допускают.
Тактирование таймеров STM32
Частоту fTIM берите из настройки тактирования, а не из частоты ядра. Если делитель шины APB, к которой подключён таймер, больше 1, таймеры этой шины тактируются удвоенной частотой шины. У STM32F103 на 72 МГц шина APB1 работает на 36 МГц, а TIM2–TIM4 — на 72 МГц.
Селектор «Таймер из атласа» подставляет частоты таймеров STM32F103 и STM32F407 при обычной максимальной настройке тактирования: у F103 все таймеры получают 72 МГц, у F407 таймеры на шине APB2 (TIM1, TIM8–TIM11) — 168 МГц, на APB1 — 84 МГц, причём у TIM2 и TIM5 регистр ARR 32-битный (таблица 4 даташитов DS5319 и DS8626).
Все поля регистров таймера — PSC, ARR, режимы каналов в CCMR, ШИМ, захват, энкодер — разобраны на страницах регистров таймеров STM32F1 и STM32F4.
Мёртвое время TIM1 и TIM8
У расширенных таймеров TIM1 и TIM8 каналы 1–3 имеют комплементарные выходы CHxN для полумоста. Между выключением одного ключа и включением другого таймер выдерживает мёртвое время, которое задаёт поле DTG[7:0] регистра BDTR в периодах t_DTS (RM0008, 14.4.18):
| DTG[7:5] | Мёртвое время | Шаг |
|---|---|---|
| 0xx | DTG[7:0] · t_DTS | t_DTS |
| 10x | (64 + DTG[5:0]) · 2 · t_DTS | 2 · t_DTS |
| 110 | (32 + DTG[4:0]) · 8 · t_DTS | 8 · t_DTS |
| 111 | (32 + DTG[4:0]) · 16 · t_DTS | 16 · t_DTS |
Период t_DTS — такт таймера, умноженный на 1, 2 или 4 по полю CKD регистра CR1, наибольшее мёртвое время — 1008 · t_DTS. Пример RM0008 для t_DTS = 125 нс: 0–15 875 нс с шагом 125 нс, 16–31,75 мкс с шагом 250 нс, 32–63 мкс с шагом 1 мкс и 64–126 мкс с шагом 2 мкс — он служит эталоном тестов калькулятора.
Калькулятор выбирает наименьшее DTG, при котором мёртвое время не короче заданного: для силовых ключей короткая пауза опаснее длинной. Макрос __LL_TIM_CALC_DEADTIME из драйвера LL STM32Cube отбрасывает дробную часть и может дать значение на шаг меньше — если результаты расходятся, калькулятор это показывает. Подробнее о комплементарных выходах, BRK и MOE — в статье о таймерах STM32.
Энкодер
В режиме энкодера таймер считает фронты двух сигналов A и B, подключённых к входам TI1 и TI2, а направление определяет по их порядку (RM0008, раздел 14.3.16 и таблица 81). В режимах 1 и 2 считаются фронты одного входа — 2 отсчёта на период сигнала, в режиме 3 (SMS = 011) — фронты обоих, 4 отсчёта. Энкодер с N периодами на оборот даёт 2N или 4N отсчётов; если записать в ARR число отсчётов на оборот минус 1, счётчик будет проходить ровно круг за оборот.
Калькулятор показывает частоту сигналов на входах при наибольшей скорости и время, за которое счётчик проходит круг 0…ARR. Если читать CNT реже, чем за половину этого круга, по разности двух отсчётов уже нельзя однозначно понять, в какую сторону и на сколько повернулся вал.
Пример для ATmega328P
#include <avr/io.h>
#include <avr/interrupt.h>
volatile uint32_t ms_ticks;
ISR(TIMER1_COMPA_vect)
{
ms_ticks++; /* called every 1 ms */
}
int main(void)
{
TCCR1A = 0;
TCCR1B = (1 << WGM12) | (1 << CS11); /* CTC, clk/8 */
OCR1A = 1999; /* 16 MHz / 8 / 2000 = 1 kHz */
TIMSK1 = (1 << OCIE1A);
sei();
for (;;) {
}
}
Типичные ошибки
- Забыли глобально разрешить прерывания (
sei()): таймер считает, флаг совпадения ставится, но обработчик не вызывается. - Заняли таймер Arduino. Timer0 используют millis() и delay(), Timer1 — библиотека Servo, Timer2 — tone(). Перенастройка ломает эти функции.
- Не тот режим. В обычном режиме (Normal) счётчик досчитывает до максимума, и OCRnA задаёт только момент совпадения, а не период.
- Неверная частота таймера STM32 из-за удвоения на шине APB — частота получается вдвое выше или ниже ожидаемой.
- Ошибка частоты из-за кварца. Расчёт точен настолько, насколько точна тактовая частота; на внутреннем RC-генераторе ошибка доходит до процентов. Подбор конденсаторов для кварца — в калькуляторе конденсаторов для кварца, скорость UART — в калькуляторе скорости UART.
Частые вопросы
Как настроить прерывание таймера раз в 1 мс на ATmega328P при 16 МГц?
Timer1 в режиме CTC: предделитель 1 и OCR1A = 15999 или предделитель 8 и OCR1A = 1999 — оба варианта дают ровно 1 кГц. Для 8-битного Timer0 подходит предделитель 64 и OCR0A = 249. Учтите, что в Arduino Timer0 занят функциями millis() и delay().
Как рассчитать PSC и ARR для STM32?
Частота события f = fTIM / ((PSC + 1) · (ARR + 1)), где fTIM — частота тактирования таймера. Для 1 кГц при 72 МГц произведение (PSC + 1) · (ARR + 1) должно быть 72 000: например, PSC = 71 и ARR = 999 (счёт идёт с частотой 1 МГц) или PSC = 1 и ARR = 35 999 — так у ШИМ больше шагов.
Почему частота таймера STM32 вдвое больше частоты шины APB?
Так устроено тактирование: если делитель шины APB больше 1, таймеры на этой шине получают удвоенную частоту. Например, у STM32F103 на 72 МГц шина APB1 работает на 36 МГц, а таймеры TIM2–TIM4 тактируются от 72 МГц.
Как рассчитать мёртвое время STM32 (поле DTG)?
Мёртвое время задаётся в периодах t_DTS: такт таймера, умноженный на 1, 2 или 4 по полю CKD. Значения DTG до 0x7F дают DTG · t_DTS, от 0x80 — (64 + DTG[5:0]) · 2 · t_DTS, от 0xC0 — (32 + DTG[4:0]) · 8 · t_DTS, от 0xE0 — (32 + DTG[4:0]) · 16 · t_DTS (RM0008, 14.4.18). Для 1 мкс на STM32F103 с таймером 72 МГц это DTG = 72 (0x48), на TIM1 STM32F407 при 168 МГц — 0x94.
Чем режим CTC отличается от переполнения таймера?
При переполнении счётчик всегда досчитывает до максимума — 255 или 65 535, — и частота выбирается только предделителем. В CTC счётчик сбрасывается при совпадении с OCRnA, и период задаётся точно, с шагом в один такт после предделителя.
Источники
- Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet (DS40002061B) — Timer/Counter0, 1 и 2: режим CTC, частота на выводе OCnA, Fast PWM, коды предделителя CSn2:0
- STMicroelectronics. RM0008 Reference manual STM32F101xx–STM32F107xx — предделитель PSC и регистр ARR таймеров, частота тактирования таймеров от шины APB; 14.4.18 — кодирование DTG[7:0] и пример диапазонов при t_DTS = 125 нс (эталон тестов); 14.3.16 и таблица 81 — режимы энкодера
- STMicroelectronics. STM32CubeF1: драйвер LL (stm32f1xx_ll_tim.h) — макрос __LL_TIM_CALC_DEADTIME и TIM_CALC_DTS — второй источник тестов мёртвого времени; LL_TIM_ENCODERMODE_X2_TI1, X2_TI2, X4_TI12 — 2 и 4 отсчёта на период
- STMicroelectronics. DS5319 Rev 20 (STM32F103x8/B) и DS8626 Rev 12 (STM32F405/407) — таблица 4 обоих даташитов — таймеры, их разрядность и шины; пресеты частот таймеров
Где пригодится
- Таймеры AVRTimer0/1/2, режимы WGM, предделители, формулы ШИМ, захват, примеры
- avr-gcc и avr-libcКомпилятор, binutils, avr-libc, avrdude: установка, команды сборки, Makefile, заголовки, ошибки
- Архитектура 8051Память, SFR, машинный цикл, порты, таймеры, UART и прерывания
- Arduino и AVRЧто делают init(), millis(), analogWrite(), analogRead() и загрузчик
- Конечные автоматы на Cswitch-case, таблица переходов, функции-состояния, таймауты, очередь событий
- Энкодеры: инкрементальные и абсолютныеКвадратурный сигнал, x1/x2/x4, EC11, HEDS-5540, AS5600, таймер STM32, дребезг, код
Встроить калькулятор на свой сайт
Скопируйте код и вставьте его в HTML страницы, статьи или вики. Виджет бесплатный, без рекламы, счётчиков и cookie. Условие одно — ссылка на GAW под рамкой остаётся на месте. Подробнее о виджетах
<iframe src="https://gaw.ru/embed/mcu-timer/" title="Калькулятор таймера AVR и STM32" width="100%" height="640" style="border:1px solid #e3e5e9;border-radius:8px" loading="lazy" allow="clipboard-write"></iframe>
<p style="margin:6px 0 0;font-size:14px">Калькулятор: <a href="https://gaw.ru/tools/mcu-timer/">Калькулятор таймера AVR и STM32</a> — GAW.ru</p>Автоподстройка высоты рамки
Если сайт разрешает скрипты, добавьте этот код один раз в любом месте страницы: рамка будет менять высоту вместе с результатом расчёта.
<script>window.addEventListener("message",function(e){if(e.origin!=="https://gaw.ru"||!e.data||e.data.type!=="gaw:embed-height")return;var f=document.querySelectorAll('iframe[src^="https://gaw.ru/embed/"]');for(var i=0;i<f.length;i++)if(f[i].contentWindow===e.source)f[i].style.height=e.data.height+"px"})</script>Обновлено .
Нашли ошибку в расчёте?