cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 DMA Timer interrupt concept question

robertnoble9
Associate III
Posted on May 02, 2016 at 16:41

Hi,

I have a conceptual question about DMA data transfer and timers.  I'm using an STM32f103RBT6 and would like to output a square wave signal that is non repeating.  What I would like to do is to create a buffer of capture compare values, the first of which would placed into the relevant CCR and the timer enabled.  Once the CCR value is reached the timer would enable a digital output and place the next value into the CCR and the timer would be enabled again.  Once reached, the digital output would be disabled, a new CCR value placed into the register etc...

Is it worth using the DMA for this or just would it not be worth it?

Also is it possible to use the DMA in this way?

The timing in question would ideally be a minimum of ~0.2us, which I'm not sure would be possible.

Any info would be greatly appreciated,

Thanks
4 REPLIES 4
Posted on May 02, 2016 at 18:52

You can't enable/disable the timer. DMA will allow you to do one thing effectively, you can modulate the ARR or CCRx, and create a pattern buffer to do that.

200ns is likely doable, but you want a reasonable deep buffer, so you're interrupting below a few hundred KHz.

DMA+TIM can also drive a pattern buffer to GPIO pins (BSRR, or ODR)

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
robertnoble9
Associate III
Posted on May 03, 2016 at 08:49

Thanks for that, if I have understood correctly, then it was very insightful.

Correct me if I have misunderstood.

- Calculate my timing values and place them into a relatively large array (TIM_buffer), the length of which should be set in DMA_BufferSize.

- Configure a timer to generate an interrupt in output compare active mode once CCR value is reached. (Using TIM_OCMode_Active)

- Set required GPIO ODR inside timer OC interrupt.

- Configure TIM_DMAUpdate on the timer to trigger a DMA transfer on update event, i.e. when OC value is reached.

- Configure DMA channel to transfer data from timing buffer (TIM_buffer) to timer CCR, with DMA_MemoryInc enabled in order to increment to next buffer index one transfer is completed.  (This is a memory to peripheral transfer so DMA_M2M should be disabled??)

- While the DMA is working its way through the TIM_buffer, I can be calculating my next set of timing data in the main loop ready to transfer.

- In order to make this as seamless as possible, could I use the DMA half transfer interrupt to work out which half of the TIM_buffer has been used and then replace it with new data while the DMA continues with the rest of the buffer?

Have I understood correctly?

Thanks for the help.

You can't enable/disable the timer. DMA will allow you to do one thing effectively, you can modulate the ARR or CCRx, and create a pattern buffer to do that.

200ns is likely doable, but you want a reasonable deep buffer, so you're interrupting below a few hundred KHz.

DMA+TIM can also drive a pattern buffer to GPIO pins (BSRR, or ODR)

re.wolff9
Senior
Posted on May 03, 2016 at 09:29

I'm not sure if your period is constant. If not, I think I would have the DMA reload the ARR of the timer. Setting a compare at 1 to toggle, you now have an output where you can set each individual low-time or high-time. 

If you reload the CCR, that would mean the period would always be the same. Not sure if you want that. 

With a low-end STM32, you can get single clock cycle resolution: about 20ns if the CPU runs at 48Mhz. It will not work reliably until you have ''a few'' clock cycles for each repetition. Say 200ns, 10 clocks will be fine. But the resolution can easily be 20ns.

If    you need beter resolution you need a slightly faster processor. That could be a 168 or 180 MHz STM32F4 or if you really need resolution, There is an STM32 that is specifically for timing resolution things: The STM32F334. That one can reach a resolution almost 1000 times better than what you said was your requirement.... 

robertnoble9
Associate III
Posted on May 03, 2016 at 10:13

No, the period is not constant.

Try again.

- Calculate my timing values (on timing and off timing) and place them into a relatively large (TIM_buffer), in a alternating fashion, e.g. TIM_ON, TIM_OFF, TIM_ON, TIM_OFF etc... The length of which should be set in DMA_BufferSize.

- Configure DMA channel transfer data from TIM_buffer to timer CCRx and ARRx, with DMA_MemoryInc and DM_PeripheralInc enabled in order to increment to next buffer index one transfer is completed and flick between transfering to CCRx and ARR registers.  (This is a memory to peripheral transfer so DMA_M2M should be disabled??)

- Configure the timer to enable GPIO pin when CCRx value is reached, and disable pin and reset timer when ARR value is reached. This can be done using TIM_OCMode_PWM1. This should remove the requirement for and ISR on overflow or update.

- Enable TIMx_DIER->CCxDE and TIMx_DIER->UDE to trigger DMA transfer on update AND overflow.  (Not sure if this is possible)

- While the DMA is working its way through the TIM_buffer, I can be calculating my next set of timing data in the main loop ready to transfer.

- In order to make this as seamless as possible, could I use the DMA half transfer interrupt to work out which half of the TIM_buffer has been used and then replace it with new data while the DMA continues with the rest of the buffer?

Thanks again