STM32 ШИМ.

STM32 ШИМ.

Генерация ШИМ у STM32 осуществляется с помощью таймеров, про них в документации написано много, но ШИМ оказалось настроить достаточно просто. Генерировать ШИМ будем с помощью 4-го канала первого таймера.

Первым делом надо найти какой вывод отвечает за 4-й канал первого таймера, для этого открываем Technical DataSheet на свой МК, у меня STM32F103VET6, и находим альтернативной функцией какого вывода является TIM1_CH4.
STM32 ШИМ.


Для использования таймера вывод надо настроить как push-pull.
STM32 ШИМ.


Давайте рассмотрим регистры, которые нам понадобятся.

TIMx_PSC – входной предварительный делитель частоты, его значение можно рассчитать по формуле

F = fCK_PSC / (PSC[15:0] + 1)

  • F – частота с которой тактируется таймер
  • fCK_PSC — частота таймера до делителя
  • PSC[15:0] — значение регистра PSC

TIMx_ARR – регистр автоматической перезагрузки, счётчик считает от 0 до TIMx_ARR, или наоборот в зависимости от направления счёта, изменяя это значение, мы изменяем частоту ШИМ.

TIMx_CCRy[x – номер таймера, y – номер канала] – определяет коэффициент заполнения ШИМ. То есть, если в ARR мы запишем 1000, а в CCRy 300, то коэффициент заполнения при положительном активном уровне и прямом ШИМ будет равен 0.3 или 30%.

TIMx_CNT – счётный 16-битный регистр, изменяет своё значение на ±1 с приходом каждого импульса, в зависимости от направления счёта.

TIMx_CR1 ->DIR – регистр направления счёта, при установке '0' счётчик считает вверх, при установки '1' - вниз. Когда счётчик сконфигурирован в режиме выравнивания по центру, бит доступен только для чтения.

TIMx_CCER->CCyE[x – номер таймера, y – номер канала] – установка '1' в этот бит разрешает использовать соответствующий канал таймера как выход, в том числе и для генерации ШИМ.

TIMx_BDTR->MOE – установка единицы в этот бит разрешает использовать выводы таймера как выходы.

Биты OCyM[2:0], где y — номер канала, в регистре TIMx_CCMR позволяют выбрать режим ШИМ, прямой или инверсный.
STM32 ШИМ.

Надо сказать, что первый и второй канал настраиваются в регистре CCMR1, а третий и четвёртый в регистре CCMR2.

TIMx_CCER->CCyP[x - номер таймера, y - номер канала] - этот бит позволяет выбирать каким будет активный уровень, '0' - высокий, '1' - низкий.

TIMx_CR1 ->CMS[1:0] - позволяет выбрать режим выравнивания по фронту или по центру, что аналогично Fast PWM и Phase Correct PWM у AVR.
  • 00: Режим выравнивания по фронту. Счетчик считает вверх или вниз в зависимости от бита направления(DIR).
  • 01: Режим 1 выравнивания по центру. Счетчик считает вверх и вниз. Флаги прерывания устанавливаются от каналов настроенных на выход(CCxS=00 в TIMx_CCMRx), только тогда, когда счетчик считает вниз.
  • 10: Режим 2 выравнивания по центру. Счетчик считает вверх и вниз. Флаги прерывания устанавливаются от каналов настроенных на выход(CCxS=00 в TIMx_CCMRx), только тогда, когда счетчик считает вверх.
  • 11: Режим 3 выравнивания по центру. Счетчик считает вверх и вниз. Флаги прерывания устанавливаются от каналов настроенных на выход(CCxS=00 в TIMx_CCMRx), когда счетчик считает вверх и вниз.

TIMx_CRx->CEN – установка '1' в этот бит, запускает счётчик.

Давайте напишем код для генерации ШИМ с выравниванием по фронту.

#include "stm32f10x.h"

int main (void)
{
	// Тактирование  GPIOA , TIM1, альтернативных функций порта
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_AFIOEN;
        
        //PA11 push-pull
	GPIOA->CRH &= ~GPIO_CRH_CNF11;
	GPIOA->CRH |= GPIO_CRH_CNF11_1;

	GPIOA->CRH	&= ~GPIO_CRH_MODE11;
	GPIOA->CRH	|= GPIO_CRH_MODE11_1;
	
	//делитель
	TIM1->PSC = 72;
	//значение перезагрузки
        TIM1->ARR = 1000;
	//коэф. заполнения
	TIM1->CCR4 = 300;
	//настроим на выход канал 4, активный уровень низкий 
	TIM1->CCER |= TIM_CCER_CC4E | TIM_CCER_CC4P;
	//разрешим использовать выводы таймера как выходы
	TIM1->BDTR |= TIM_BDTR_MOE;
	//PWM mode 1, прямой ШИМ 4 канал
         TIM1->CCMR2 = TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1; 
        //если надо настроить первый канал, это можно сделать так
        //TIM1->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
	//считаем вверх
	TIM1->CR1 &= ~TIM_CR1_DIR;
	//выравнивание по фронту, Fast PWM
	TIM1->CR1 &= ~TIM_CR1_CMS;
	//включаем счётчик
	TIM1->CR1 |= TIM_CR1_CEN;
}

Смотрим, что получилось.
STM32 ШИМ.

Изменяем активный уровень, на высокий.
STM32 ШИМ.

STM32 ШИМ.

Изменяем прямой ШИМ на инверсный.
STM32 ШИМ.

STM32 ШИМ.

Всё стало как было раньше, ничего сложного.
комментарии
3