hex.pp.ua

Использование 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.

система комментирования CACKLE

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


Разделы сайта
Главная
Блог
Native API
NTFS и ReFS
Микроконтроллеры
Справочник NTDLL
Коды NTSTATUS
Разное

Избранное
NTFS Stream Explorer
Native Shell
Тенгвар

Остальное
nvpnhcknn (архив)
English pages
Контакты

Ленты atom
Лента Atom сайта Лента Atom блога



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