В этом разделе мы рассмотрим пример использования PWM выхода. Для этого нам необходимо будет использовать таймеры. Таймеры общего назначения состоят из 16-разрядного счетчика с автоперезагрузкой, управляемого программируемым прескалером. Они могут использоваться для различных целей, включая измерение длительности импульсов входных сигналов (захват входного сигнала) или генерацию выходных сигналов (сравнение выходных сигналов и ШИМ — что нам и нужно). Длины импульсов и периоды колебаний могут быть модулированы от нескольких микросекунд до нескольких миллисекунд с использованием прескалера таймера и прескалера регулятора тактового сигнала RCC. Таймеры полностью независимы и не делятся никакими ресурсами. Они могут быть синхронизированы вместе.
Основные функции TIMx:
Функции таймера общего назначения TIMx включают в себя:
• 16-битный счетчик автоматической перезагрузки вверх, вниз, вверх / вниз.
• 16-разрядный программируемый прескалер, используемый для деления (также «на лету») тактовой частоты счетчика на любой коэффициент от 1 до 65536.
• До 4 независимых каналов
Основным блоком программируемого таймера является 16-разрядный счетчик с соответствующим регистром автоперезагрузки. Счетчик может считать вверх, вниз или одновременно вверх и вниз. Счетчик часов можно разделить на прескалер.
Счетчик, регистр автоматической перезагрузки и регистр предварительного масштабирования могут быть записаны или считаны программным обеспечением. Это верно, даже когда счетчик работает.
Единица времени включает в себя:
• Счетчик регистров (TIMx_CNT)
• Предварительный регистр (TIMx_PSC):
• Автозагрузка регистра (TIMx_ARR)
Для более глубокого и детального изучения можно открыть Reference manual раздел PWM Mode.
Мы же для примера возьмем пин PA6. Для наглядного примера можем открыть CubeMX, но выгружать оттуда ничего не будем:
Видим, что на пину PA6 сидит таймер TIM3. Теперь необходимо посмотреть на какой шине сидит наш таймер — для определения максимальной частоты работы. Смотрим все тот же Reference Manual:
Максимальная частота TIM3 не выше 36 МГц, значит и делители необходимо настраивать не выше данной частоты).
Напишем код:
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
void InitPWM(void) //Функция инициализации и настройки ШИМ на порту А
{
// Включаем тактирование таймера и порта A
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// Конфигурируем порт А6
GPIO_InitTypeDef GPIO_Config;
GPIO_Config.GPIO_Pin = GPIO_Pin_6;
// Альтернативная функция (в нашем случае - выход таймера), Push-Pull
GPIO_Config.GPIO_Mode = GPIO_Mode_AF_PP;
// Частота - 50 MHz
GPIO_Config.GPIO_Speed = GPIO_Speed_50MHz;
// Инициализируем порт A
GPIO_Init(GPIOA, &GPIO_Config);
// Конфигурация таймера
TIM_TimeBaseInitTypeDef TIM_BaseConfig;
// Конфигурация выхода таймера
TIM_OCInitTypeDef TIM_OCConfig;
// Конфигурируем таймер
// PWM frequency = 100 Гц
// Запускаем таймер на тактовой частоте в 100 Hz
TIM_BaseConfig.TIM_Prescaler = SystemCoreClock/100000 - 1; // 0..239;
// Период - 1000 тактов => 100000/1000 = 100 Hz //0...36 MHz
TIM_BaseConfig.TIM_Period = 1000 - 1; // 0..999
TIM_BaseConfig.TIM_ClockDivision = 0;
// Отсчет от нуля до TIM_Period
TIM_BaseConfig.TIM_CounterMode = TIM_CounterMode_Up;
// Инициализируем таймер 3
TIM_TimeBaseInit(TIM3, &TIM_BaseConfig);
// Конфигурируем выход таймера, режим - PWM1
TIM_OCConfig.TIM_OCMode = TIM_OCMode_PWM1;
// Выход включен
TIM_OCConfig.TIM_OutputState = TIM_OutputState_Enable;
// Пульс длинной 100 тактов => 100/1000 = 90%
TIM_OCConfig.TIM_Pulse = 100 - 1; //0...999
// Полярность => пульс - это единица (+3.3V)
TIM_OCConfig.TIM_OCPolarity = TIM_OCPolarity_High;
// Инициализируем первый выход таймера 3
TIM_OC1Init(TIM3, &TIM_OCConfig);
// Включаем таймер
TIM_Cmd(TIM3, ENABLE);
}
int main(void)
{
InitPWM();
while(1)
{
}
return 0;
}
В коде показаны этапы, необходимые для настройки таймера 3 для работы с периодом 100 Гц и 1000 шагов тактового генератора. Это позволяет нам определять ширину импульса на выходе от 0 до 100% с точностью до 0,1%. Основными параметрами конфигурации являются Prescaler, период и count mode (режим подсчета (up!)). Выходной канал сконфигурирован в режиме PWM (на самом деле есть две вариации — выровненные по краям и выровненные по центру — здесь мы выбираем выровненные по краям. Импульсная ширина pw (0..999) также может быть установлена с помощью следующей команды — TIM_SetCompare2
TIM_SetCompare2(TIM2, pw); //(0..999)

