cancel
Showing results for 
Search instead for 
Did you mean: 

TIM1 one-pulse PWM mode with four outputs -- I would like the pulses to start HIGH immediately when I enable the timer, so that they can go LOW individually at different times depending on each comparison.

konbaasiang
Associate II

I'm a beginner at STM8 programming. I'm designing a quad trailing-edge dimmer as my first STM8S003F3 project. I have a zero crossing pulse tied to a pin and generating an interrupt, and on this interrupt I want to trigger pulses on four output that end at the correct time (to achieve mains PWM dimming).

So far I am testing with a very slow one-pulse timer and an LED, initialized as follows:

TIM1_DeInit();
  TIM1_TimeBaseInit(2000, TIM1_COUNTERMODE_UP, 0x7FF, 0);
  TIM1_OC3Init(TIM1_OCMODE_PWM2, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, 0x3FF, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_HIGH, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_RESET);
  TIM1_SelectOnePulseMode(TIM1_OPMODE_SINGLE);
  TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);
  TIM1_CtrlPWMOutputs(ENABLE);
  TIM1_Cmd(ENABLE);

Then once per second I call TIM1_Cmd(ENABLE); and get one pulse -- but the start of the pulse is of course delayed (pulse length 3ff).

By setting pulse length 1, the delay goes away and I can adjust the pulse length in TimeBaseInit, but then I of course cannot set the four TIM1 outputs differently.

I've tried many different things but I'm in over my head, just starting out.

If there's a way to set the output HIGH and let it stay HIGH until the comparison brings it LOW then this would solve my problem.

I would really appreciate any pointers in the right direction. Thanks in advance!

5 REPLIES 5
konbaasiang
Associate II

Okay, I found a workaround to get me past this issue. Rather than letting the timer control the output pins, I enable the output compare interrupt for all four capcom channels and set the output pins high myself. Then, I simply clear the output pins in the interrupt handler.

On timer init:

TIM1->IER	= TIM1_IER_CC1IE | TIM1_IER_CC2IE | TIM1_IER_CC3IE | TIM1_IER_CC4IE;  // enable the compare interrupt for all four capcom channels

To set all four pins high and then trigger timer:

GPIOC->ODR = GPIOC->ODR | (0xF<<3);
			TIM1_Cmd(ENABLE);

In the interrupt handler:

GPIOC->ODR = GPIOC->ODR & ~((TIM1->SR1 & (0xF << 1))<<2);	//clear GPIOC bit 3-7 if TIM1->SR1 bit 1-4 is set
	TIM1->SR1  = 0;    // clear any pending interrupts;

This does exactly what I need it to do, but it's not as elegant as the timer controlling the pins directly. If anyone knows a better solution, please let do me know. =)

Cristian Gyorgy
Senior III

It should be quite simple and basic. You just need to configure tim1 in PWM mode 1 not 2. In PWM mode 1 the outputs (OCi) are high until the timer reaches the TIM_CCR value and then it resets the outputs. And every time you want another cycle you set TIM_CR1/CEN.

But of course you need to configure all 4 channels - I see you only configure channel 3.

konbaasiang
Associate II

Thanks for replying, Cristian!

That would have been too easy :)

PWM mode 1 does not actually produce the behaviour I'm looking for.

Here's what I'm seeing:

0693W000004KR9VQAW.png 

Cristian Gyorgy
Senior III

Well, then after you start the timer pulse by setting CEN bit, change the OCiM bits to 010: Set channel to inactive level on match - OCiREF signal is forced low. This should keep then the low level after the timer period.

konbaasiang
Associate II

While doing bit-manipulation of timer registers during each particular timer event might technically work, I feel like it would be inviting a race condition. It also hardly qualifies as elegant -- it rather defeats the purpose of using the timer outputs directly, I might as well set the GPIOs myself and clear them on an interrupt at that point.

But, are there other timer modes that may be applicable? Due to their behavior, it seems like the PWM modes aren't designed to be used for AC synchorized dimming.

The behavior I'm looking for seems like something that "should" be natively supported by some timer mode, because it's such a basic thing -- "keep the output lit while we're counting".