Использование PWM (ШИМ) в STM8

Широтно-импульсная модуляция на STM8




С помощью микроконтроллера STM8 можно генерировать заданную частоту с порта ввода-вывода. Для этого не обязательно вручную переключать туда-сюда пин на порту. Можно воспользоваться одним из таймеров, а именно задействовать в нём функцию PWM. Это режим широтно-импульсной модуляции (ШИМ). В нём можно генерировать заданную частоту и регулировать скважность этой частоты.

Код, приведённый в этой статье относится к компилятору Raisonance.

Для работы с ШИМ я использую следующие макросы (ниже будет показано во что они разворачиваются, так как сложно воспринимать код, написанный в виде макросов):


// timer == TIM2, TIM3
#define InitTimer_PWM(timer) \
  timer##_DeInit(); \
  timer##_TimeBaseInit(timer##_PRESCALER_1, uPeriod); \  
  timer##_ARRPreloadConfig(ENABLE);  \
  timer##_Cmd(ENABLE);

#define InitChannel_PWM(timer, channel) \  
  timer##_OC##channel##Init(timer##_OCMODE_PWM1, timer##_OUTPUTSTATE_ENABLE, \
                            uPulse, timer##_OCPOLARITY_HIGH); \
  timer##_OC##channel##PreloadConfig(ENABLE);

#define ChangePulse_PWM(timer, channel) \
  timer##->CCR##channel##H = (u8)(uPulse >> 8); \
  timer##->CCR##channel##L = (u8)(uPulse);

#define DisableChannel_1_PWM(timer) \
  timer->CCER1 &= (u8)(~timer##_CCER1_CC1E)
#define DisableChannel_2_PWM(timer) \
  timer->CCER1 &= (u8)(~timer##_CCER1_CC2E)
#define DisableChannel_3_PWM(timer) \
  timer->CCER2 &= (u8)(~timer##_CCER2_CC3E)

Последние три макроса нужны на тот случай, если нужно отключить выдачу частоты с канала таймера.

Макрос InitTimer_PWM инициализирует режим PWM для заданного таймера. Вызывать его нужно так: InitTimer_PWM(TIM3); Но, поскольку это макрос, где-то перед ним нужно рассчитать, во-первых, генерируемую частоту, во-вторых, её скважность. Частоту берём из параметра функции uFreq, а скважность будет в переменной uPulse, рассчитанной из параметра fPulse. Параметр fPulse это заполнение в процентах. То есть для скважности 50 % туда надо поместить значение (float)50.


static bool bTimerInitialized = false;

void SetFreqChannel_3(u16 uFreq, float fPulse)
{
  u16 uPulse, uPeriod;
  float fCoeff, fNewPulse;
  
  static bool bChannelInitialized = false;
  
  uPeriod = (u16)(CLK_GetClockFreq() / uFreq); 
  fCoeff = fPulse / 100.;
  fNewPulse = (float)uPeriod * fCoeff;  
  uPulse  = (u16)( fNewPulse );

  if (!bTimerInitialized)
  {
    // Таймер ещё не был инициализирован
    InitTimer_PWM(TIM2);
    bTimerInitialized = true;
  }
  
  if (!bChannelInitialized)
  {
    // Канал ещё не был инициализирован
    InitChannel_PWM(TIM2, 3);
    bChannelInitialized = true;  
  } else
  {
    // Поменять параметры ШИМ
    ChangePulse_PWM(TIM2, 3);       
  }        
}

То есть пишем, например SetFreqChannel_3(200, 45.); и получаем на третьем канале таймера TIM2 частоту 200 Гц и скважность 45 %. Почему у меня в примере функция только для канала 3? А потому, что иначе не получится использовать макрос ChangePulse_PWM, которому во втором параметре нужно именно число (ведь оно подставляется в имя регистра). Модифицировать функцию так, чтобы она работала со всеми каналами сразу, предлагаю вам самостоятельно, если вам это нужно.

Теперь, что касается макросов, они разворачиваются так:


// InitTimer_PWM(TIM2) =
  TIM2_DeInit();
  TIM2_TimeBaseInit(TIM2_PRESCALER_1, uPeriod);  
  TIM2_ARRPreloadConfig(ENABLE);
  TIM2_Cmd(ENABLE);

// InitChannel_PWM(TIM2, 1) =  
  TIM2_OC1Init(TIM2_OCMODE_PWM1, TIM2_OUTPUTSTATE_ENABLE, uPulse, TIM2_OCPOLARITY_HIGH);
  TIM2_OC1PreloadConfig(ENABLE);

// ChangePulse_PWM(TIM2, 1)
  TIM2->CCR1H = (u8)(uPulse >> 8);
  TIM2->CCR1L = (u8)(uPulse);

// DisableChannel_1_PWM(TIM2) =
  TIM2->CCER1 &= (u8)(~TIM2_CCER1_CC1E)
  
// DisableChannel_2_PWM(TIM2) =
  TIM2->CCER1 &= (u8)(~TIM2_CCER1_CC2E)
  
// DisableChannel_3_PWM(TIM2) =
  TIM2->CCER2 &= (u8)(~TIM2_CCER2_CC3E)

Это — либо обращения к регистрам микроконтроллера, либо вызовы функций библиотеки из состава пакета STM8-RKIT.



Автор: амдф
Дата: 12.10.2012


При копировании материалов хорошим тоном будет указание авторства и ссылка на сайт.