cancel
Showing results for 
Search instead for 
Did you mean: 

Single toggling pulse wave by loading the CCR register using DMA

Posted on June 20, 2016 at 16:12

I'm trying to generate a single pulse wave, having about 20 toggle transitions. I've created such a generator, and the thing that I haven't solved yet is how to stop it. The aim is to have the pulse wave start after programming the CCR register, and stop automatically once a value was loaded from the table that is greater than the timer period. That also works, but the problem is that the DMA sequence restarts on an update event (or reloads a zero into the CCR register) which it shouldn't. The program only enables one CCx event for DMA, and does not enable the update for either DMA or interrupt. The goal is to make the wave generation stop until a value lower than the timer period is programmed into the CCR. Any ideas ?

Another unexpected behaviour is that the IRQ routine is called for CCx or other events, although not enabled.

#dma-timer-pulse-wave
7 REPLIES 7
Posted on June 20, 2016 at 17:08

Not really how the timers function.

I'd use the Update and Repetition Count, so TIM1 or TIM8 on an F2/F4, and have the DMA load the CCRx desired.

The status for the TIM reflects which events have fired, the interrupt enable is used for an AND gate down stream from that to trigger the NVIC with the specific source(s) chosen.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Posted on June 29, 2016 at 18:58

After studying the timer controlled DMA a bit more in detail, I found a solution. The behaviour that I did not understand yet, is that when the CCR from the timer is programmed with a value that is not reached, the DMA still loads a new value on each update event, even when not explicitly enabled. And that is indeed very handy for the generation of a video sync signal that I was trying to make. After a few days of fiddling with the software, and adding a one transistor video buffer amplifier, a working PAL video signal generator was created, running solely on timers and DMA. No CPU interaction needed for the signal generation. Just fill / modify the frame buffer as desired and watch ! Properties: 320 x 240 monochrome resolution. PAL interlaced video using the 8 MHz external oscillator on the STM32L100C Discovery board. Demonstration video here :

 <LINK NO LONGER ACTIVE>

Posted on June 29, 2016 at 19:05

Video is quite impressive

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
knielsen
Associate II
Posted on June 29, 2016 at 22:16

The update event occurs when the timer reaches 0 (downcount mode) or the reload value (upcount mode), so it occurs independently of the CCR value. There is a separate CC1 (,CC2,...) event for when/if the CCR value is reached by the counter. Those can be configured individually to trigger or not trigger DMA in TIMx_DIER.

And agree, nice PAL demo 🙂

 - Kristian.

Posted on June 29, 2016 at 23:52

What I was meant to explain is the following:

I have configured TIM3 to generate both the horizontal and vertical sync pulses, and it has a 64 microsecond period , i.e. running at the line 15625 Hz line frequency. Channel2 produces the horizontal sync pulses in a PWM configuration, and Channel1 is destined to output the vertical sync wave form using a toggling output. Most of the time, during the video output, this output should not toggle but have a steady (high) state. This is achieved by loading 0xFFFF into the CCR1 register. The counter counts from 0 ... 1023, so the CCR1 value never matches, and thus the output doesn't toggle.

But, as the CCR1 register is reloaded from a table by DMA, not the CPU, it was a delight to see that each update event from TIM3, triggers the DMA to fetch the next value from the (circular) table. The update events trigger the DMA, even when only the CCR events were enabled by:

    TIM_DMACmd(TIM3, TIM_DMA_CC1 | TIM_DMA_CC3 | TIM_DMA_CC4, ENABLE);

knielsen
Associate II
Posted on June 30, 2016 at 10:33

Ok, yes, now I understand, seems strange. I would have expected

    TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);

to give the behaviour you describe (and need). But maybe the TIM_DMA_CC3 and/or TIM_DMA_CC4 event trigger every timer cycle, giving the same effect as TIM_DMA_Update? Anyway, great that you got it to work.

Posted on June 30, 2016 at 11:01

> But, as the CCR1 register is reloaded from a table by DMA, not the CPU, it was a delight to

> see that each update event from TIM3, triggers the DMA to fetch the next value from the

> (circular) table. The update events trigger the DMA, even when only the CCR events were enabled

It is because it's *not* the Update event which triggers the DMA, but a genuine CC event.

This is a documented (albeit confusing, I admit) feature, see the description of  TIMx_SR.CC1IF in the RMs:

When the contents of TIMx_CCR1 are greater than the contents of TIMx_ARR, the CC1IF bit

 

goes high on the counter overflow (in upcounting and up/down-counting modes) or underflow

 

(in downcounting mode)

 

 

JW