cancel
Showing results for 
Search instead for 
Did you mean: 

How do I get TIM1 generating a PWM output using the repetition counter and DMA properly?

pauljeanneret
Associate II

I don' think the TIM_DMA example in the STM32 F0 V1.10 work as described. I'm trying to use the example as the basis for using DMA to generate a PWM waveform, having each element repeated a number of times.

If you take the example and adjust it to output a sequence of 4 values rather than the 3 it's written with you only get 1 continuous PWM stream with no transitions. The repetition counter is set to 3, so you should see 4 cycles of each PWM waveform.

What I think is happening is that the DMA engine moves the memory pointer on every TIM1 cycle, but only updates the TIM1 register every 4 cycles. Because I've now got 4 items in the array moving on 4 cycles between each update means that there's no change in the value. By playing with the repetition count and number of samples in the array you can see this "aliasing" effect happening. What I was expecting was to have the pointer move on one step every 4 TIM1 cycles and update the PWM output at that point.

Is there something I'm doing wrong or it that just the way the PWM/DMA works on the STM32F0? If so, it seems a very strange way to do it as it really limits what you can do with the DMA.

6 REPLIES 6

> adjust it to output a sequence of 4 values rather than the 3

How?

JW

Hi JW,

Change the line which declares the array to ...

<code>

uint32_t aCCValue_Buffer[4] = {0, 0, 0,0};

</code>

Fill in the extra term with something sensible ...

<code>

 aCCValue_Buffer[3] = (uint32_t)(((uint32_t) 10 * (uwTimerPeriod - 1)) / 100);

</code>

Update the line which kicks off the DMA for the new length ...

<code>

 if (HAL_TIM_PWM_Start_DMA(&TimHandle, TIM_CHANNEL_3, aCCValue_Buffer, 4) != HAL_OK)

{

...

}

</code>

I was expecting that change to give an output of 4 cycles of 75%, 50%, 25% and then 10%. That's not what happens, the output appears stuck at 1 PWM rate.

Hope that makes sense.

Paul

[EDIT]

So you only changed 2 lines and added one?

 

This looks OK.

 

Read out and post the content of timer and DMA registers.

 

JW

Your analysis is correct, and the example is simply wrong and working only coincidentally, thanks to the choice of array size being one less than the number of repetitions. Of course this can be done correctly, and it's easy to do once you know what are you doing (although I have no idea how to get it working using Cube, I don't use Cube).

Only the Update event is bound to the repetition counter.

So, if the DMA is triggered from the CH3, as it is now, it triggers *every period*, transferring the new value to CCR3 and advancing the DMA pointer. But Cube probably switches on the CCR3 preload (you can check either by carefully analyzing Cube's code or reading out the timer registers, CCMR2 in this case) so it is shadowed and the new value only gets applied upon Update - which happens only once per (Repetition+1) cycles.

This is easy to fix - trigger the DMA not from CH3 but from update (i.e. instead of DIER.CC3DE, DIER.UDE shall be set). Maybe that requires to use a different DMA channel - that's then upon you to find out, I don't use the F0.

This is the joy of using "libraries" which do *things* for you.

JW

S.Ma
Principal

If you want a limited number of toggles on a timer output, get the timer freerun and overflow and use DMA to update the output compare channel.

If the table you transfer has 13 values, you get 13 output toggles. The maximum gap between two toggles is roughly the period.

To stop the DMA, just program an impossible value in the last table entry (say the timer overflow at 0xFF00, if the DMA sends 0xFFFF, it will never reach and the transfer holds.

Hi JW,
Thanks for the solution. Changing bit in the DIER register sorted it.
I'm new to trying to use the HAL, I normally prefer to set registers directly. I get why the HAL has been created, but it's really frustrating when we have to spend so long hacking around it or trying to discover where it falls down. You'd also expect ST's examples to work properly rather than work by chance.
Thanks again, really appreciate your help
Paul