cancel
Showing results for 
Search instead for 
Did you mean: 

How Do I set a Timer output compare high or low?

JMala.3
Associate III

I am working on a project that uses a PWM on a timer to drive a buzzer.  When the buzzer stops I need to set the output compare signal high.  The timer set ARR to 250, and the compare value to 125, giving a 4kHz square wave with a 50% duty cycle.   I start the timer by enabling it (TIM2->CR1 &= ~TIM_CR1_CEN), and stop the timer by disabling it. (TIM2->CR1 |= TIM_CR1_CEN).  What I need to do is make sure the output is high when it is disabled.  I tried setting the count value (TIM2->CNT = x) and thought that if I set the count below the 125 threshold, the output would stay low, and if i set the count above the 125 threshold, the count would stay high, However setting the count seems to make no difference to the output compare level.

Anyone have any idea how I can stop the count with the output compare in a defined state?

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Are you sure? It should be working how you expect it to, if the channel is in PWM mode. Is it possible it's in toggle mode?

Alternatively, you can set CCR1 to either 0 or 251 to get the state you want prior to, or as an alternative to, stopping the timer.

Also alternatively, you can set the channel to active or inactive via the OC1M register. But again, it should be working how you expect.

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

3 REPLIES 3
TDK
Guru

Are you sure? It should be working how you expect it to, if the channel is in PWM mode. Is it possible it's in toggle mode?

Alternatively, you can set CCR1 to either 0 or 251 to get the state you want prior to, or as an alternative to, stopping the timer.

Also alternatively, you can set the channel to active or inactive via the OC1M register. But again, it should be working how you expect.

 

If you feel a post has answered your question, please click "Accept as Solution".

While solution is - as TDK said above - to change the compare mode to one of the "always active/inactive"; or, maybe even simpler, change given pin in GPIO_MODER from AF to Out; changing CNT in stopped timer indeed may not result in the expected change.

The description of PWM mode as "high when < CCRx and low when > CCRx" is somewhat simplistic. As so often ST, instead of giving a precise description of given subcircuit (and as timing diagram or schematics instead of narrative, where appropriate), it just gives a dumbed down description of "what usually happens", assuming that the audience is too *** to comprehend the grand picture.

Here's the hint of what really happens:

waclawekjan_1-1720768139309.png

Now, characteristically to the state of documentation, there is one word missing, making it incomprehensible. Here's the same description from an older STM32 family:

waclawekjan_2-1720768226047.png

Also characteristically, this narrative is missing from TIM1/TIM15 etc. chapter, where the picture is probably even more complex (and not described properly/fully either).

Note that what comparison is performed depends on direction; and even if it is not said there, that's not the full picture and truth is that changing CNT in the opposite direction simply has no effect. Most probably, the comparator can only set OCREF and it's cleared by Update (or opposite polarity given by PWM mode etc.)

JW

JMala.3
Associate III

Thanks I have it working. As TDK suggested, I force the OC pin high when I turn the buzzer off, and switch back to PWM mode when I turn the buzzer back on.  The code is

 

#define BUZZER_OFF    TIM2->CR1 &= ~TIM_CR1_CEN; \
                      TIM2->CCMR1 &= ~TIM_CCMR1_OC2M_Msk;  \
                      TIM2->CCMR1 |= (0x04 << TIM_CCMR1_OC2M_Pos)

#define BUZZER_ON     TIM2->CR1 |= TIM_CR1_CEN; \
                      TIM2->CCMR1 &= ~TIM_CCMR1_OC2M_Msk;  \
                      TIM2->CCMR1 |= (0x06 << TIM_CCMR1_OC2M_Pos)