Практически все таймеры, за исключением базовых, имеют каналы сравнения, которые, в частности, умеют делать ШИМ. До четырёх штук на таймер. А именно:
много всего
TIM1: 4 канала (+инверсные);
TIM2: 4 канала;
TIM3: 4 канала;
TIM4: 4 канала;
TIM5: 4 канала;
TIM6: 0 каналов;
TIM7: 0 каналов;
TIM8: 4 канала (+инверсные);
TIM9: 2 канала;
TIM10: 1 канал;
TIM11: 1 канал;
TIM12: 2 канала;
TIM13: 1 канал;
TIM14: 1 канал;
То есть очень дофига.32 канала в сумме для всех таймеров, если я правильно посчитал.
читать дальшеДля примера возьмём обычный таймер TIM4, выводы которого подключены к светодиодам(PD12-PD15).
Сразу смотрим, куда можно его вывести:
TIM4_CH1: PB6, PD12
TIM4_CH2: PB7, PD13
TIM4_CH3: PB8, PD14
TIM4_CH4: PB9, PD15
Номер альтернативной функции для таймеров TIM3-TIM5: 2.
Настройка самого таймера такая же, как описывалась ранее.
Только что на выбор предделителя и предела счёта накладывают ограничения итоговое разрешение и частота ШИМ.
Сначала определим предел счёта согласно выбранному разрешению:
Предделитель определяется отношением частоты шины APB1 к итоговой частоте и ARR:
Пример. Частота тактирования контроллера 16 МГц, предделителя на APB1 нет. Разрешение шима хотим 16 бит, частоту порядка 50 Гц (например, чтоб серву крутить, но тут светодиод):
Правда, из-за низкой частоты тактирования (для такого высокого разрешения) получим большую погрешность по частоте ШИМ:
Fpwm = 16 МГц / (ARR + 1) / (PSC + 1) = 16000000 / 0x10000 / 4 = 61 Гц.
Впрочем, серве на это должно быть пофиг.
Итак, таймер с заданными параметрами запустить можем. Посмотрим новые регистры, которые связанны с генерацией ШИМ:
TIMx_SR — регистр статуса, можно посмотреть, было ли срабатывание по сравнению или переполнение счётчика;
TIMx_CCER — включение каналов и настройка полярности выходного сигнала (в т.ч. ШИМ);
TIMx_CCMR1 — настройка 1 и 2 канала захвата/сравнения;
TIMx_CCMR2 — настройка 3 и 4 канала захвата/сравнения;
TIMx_CCR1 — регистр сравнения 1 канала;
TIMx_CCR2 — регистр сравнения 2 канала;
TIMx_CCR3 — регистр сравнения 3 канала;
TIMx_CCR4 — регистр сравнения 4 канала;
Таймер управляет состоянием какого-то внутреннего сигнала (OCxREF), который может выводиться наружу прямо как есть или же инвертированно (настраивается в TIMx_CCER).
Активное состояние — когда OCxREF равен 1, неактивное, соответственно, — когда OCxREF равен 0.
В общем-то, чтобы ШИМ вышел наружу, достаточно включить канал, выбрать нужный режим сравнения, задать скважность и настроить альтернативную функцию порта.
Канал включается флагами CCxE в регистра CCER.
Выбрать режим генерации ШИМ можно в регистрах CCMRx, там есть поля OCxM размером в три бита:
000 — выключено;
001 — установить выход в активное состояние по сравнению;
010 — установить выход в неактивное состояние по сравнению;
011 — переключить состояние по сравнению;
100 — насильно установить неактивный уровень на выходе;
101 — насильно установить активный уровень на выходе;
110 — ШИМ, режим 1 (из активного уровня по сравнению переходит в неактивный);
111 — ШИМ, режим 2 (из неактивного уровня по сравнению переходит в активный);
В режиме ШИМ необходимо выставить ещё и флаг OCxPE (буферизация значения сранения) в этом же регистре.
Так как все значения буферизуются и загружаются во внутренние регистры только при сбросе счётчика, перед запуском (после записи чисел в CCR) сделаем же это, выставив флаг UG в регистре TIMx_EGR. Флаг сбросится тут же, но значения попадут куда надо. Возможно, всё будет хорошо, даже если так не сделать. Флаг выставится сам при первом переполнении счётчика.
Код:
Если сделать так, то на ножке PВ12 будет ШИМ с частотой 61 Гц (погрешность же) и скважностью 50%, как на картинке внизу:

В проекте скважность меняется постоянно и светодиод мерцает. Так нагляднее:
Кстати, по канону на светодиоды надо заводить ШИМ с частотой в 600 Гц, не иначе. Но здесь на это пофиг.
UPD от 29.03.2013: ШИМ перенесён с ножки PA5 на PD12 (TIM2->TIM4), где его можно увидеть невооружённым глазом по яркости светодиода.
Интересные файлы:
pwm.c
Проект целиком.
<< Предыдущее Следующее >>
@темы:
arm,
программизмы,
электроника,
stm32f4discovery,
stm32