Search This Blog

Tuesday, February 14, 2023

STM8 - Generating 2 phase PWM

A push pull converter uses two drivers that are 180 degrees out of phase.

It is possible to generate PWM on 2 channels that are 180 degrees out of phase in  TIM1on a STM8S003.  All the register settings are from the reference manual, but you won't find an example.

TIM1 is set up as an up/down counter in Center-aligned mode. This spaces out the 2 phase PWM signal evenly.

Since the timer is counting both up and down in 1 PWM cycle,  auto-reload value for TIM1 should be set as 1/2 of the value to generate PWM frequency. I used TIM1_FREQ of 27kHz in my code.

#define CPU_CLOCK 16000000UL
#define TIM1_FREQ 27000L
#define TIM1_PSCR 1
#define TIM1_CLK (CPU_CLOCK/TIM1_PSCR)
#define TIM1_ARR (TIM1_CLK/TIM1_FREQ/2)
#define TIM1_PSCRH ((TIM1_PSCR-1)>>8)
#define TIM1_PSCRL ((TIM1_PSCR-1)&0xff)
#define TIM1_ARRH ((TIM1_ARR)>>8)
#define TIM1_ARRL ((TIM1_ARR)&0xff) 

// Clk = 16MHz
CLK->CKDIVR = 0;
 
TIM1->PSCRH = TIM1_PSCRH;
TIM1->PSCRL = TIM1_PSCRL;
TIM1->ARRH = TIM1_ARRH;
TIM1->ARRL = TIM1_ARRL; 

// TIM1 enable, Center-aligned mode 3
TIM1->CR1 = TIM1_CR1_CEN|TIM1_CR1_CMS; 

Output enable (and polarity) bits of the corresponding TIM1 channels can be set in TIM1 CCERx.  I use CH3 and CH4.

// CH3, CH4 output enable, polarity active high
TIM1->CCER2 = TIM1_CCER2_CC4E|TIM1_CCER2_CC3E;

From the Reference Manual:

110: PWM mode 1 - In up-counting, channel 1 is active as long as TIM1_CNT < TIM1_CCR1, otherwise, the channel is inactive. In down-counting, channel 1 is inactive (OC1REF = 0) as long as TIM1_CNT > TIM1_CCR1, otherwise, the channel is active (OC1REF = 1).

PWM Mode 1 when ARR =8 and CCR = 4

PWM mode 2 works similarly, but with the output polarity inverted.

111: PWM mode 2 - In up-counting, channel 1 is inactive as long as TIM1_CNT < TIM1_CCR1, otherwise, the channel is active. In down-counting, channel 1 is active as long as TIM1_CNT > TIM1_CCR1, otherwise, the channel is inactive. 

One can generate a PWM signal using a sawtooth wave and a comparator.  

 

PWM generation using analog circuit - Sawtooth wave and a comparator

The modulating signal level is the CCR value, the TIM1 counter is the sawtooth wave. The PWM modes 1 and 2 are just the polarity setting on the comparator.


PWM generation using TIM1

 One of the TIM1 channel (CH3) is set up with PWM Mode 1 while another channel (Ch4) as PWM Mode 2.

// CH3: PWM mode 1, preload, output
TIM1->CCMR3 = (6<<4)|TIM1_CCMR_OCxPE;
// CH4: PWM mode 2, preload, output
TIM1->CCMR4 = (7<<4)|TIM1_CCMR_OCxPE;

Use PWM Mode 1 for one of the channels to center an output around Timer count = 0 and Mode 2 on the other to center around Timer count = ARR. This is how you can generate the 2 phase PWM signals.

The CCR values could be set independently. In some applications, you want them to have the same PWM duty cycles. The granularity of the PWM signal is 2 TIM1 clocks. (125ns in my code)

void Set_PWM(uint16_t Value)
{
Value >>=1;
// CCR3 = n/2
TIM1->CCR3H = Value >>8;
TIM1->CCR3L = Value & 0xff;

// CCR4 = TIM1_ARR - n/2
Value = TIM1_ARR - Value;
TIM1->CCR4H = Value >>8;
TIM1->CCR4L = Value & 0xff;
}

Turn on the MOE (Main Output Enable) bit in TIM1 BKR (Break Register). An external signal can be used to disable the TIM1 outputs in the case of a hardware fault. e.g. over-current or over-temperature condition

// Master output enable
TIM1->BKR = TIM1_BKR_MOE;

This are some the output of PWM waveform at 27kHz captured on my logic analyzer.

2 phase PWM at 27kHz

Set_PWM(2) - 27kHz close to 0% duty cycle

2 Set_PWM(294) - 27kHz close to 50% duty cycle

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.