cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 DMA transfer trigger with output compare

robertnoble9
Associate III
Posted on May 21, 2016 at 03:46

Hi,

I am trying to configure timer 1 channel 3 to output a varying signal in output compare toggle mode and driving the CCR with DMA1 channel 5. Thus far I can get the DMA transfer triggering using the TIM_DMA_Update request, but when changing the request to TIM_DMA_CC3 it stops working and the DMA requests are no longer triggered. The output compare interrupt is firing, tested that with a serial print, but no DMA transfer and the DMA_GetCurrentDataCounter never changes. Below is my timer, GPIO and DMA configuration code. I'm clearly missing something, but a can't for the life of me find what it is. Just to double check, is this possible? The result I am after is to be able to toggle the output pin for the timer multiple time before a reset. E.g start with pin off and timer at 0, then turn on at 1000, off at 2000, on at 3000, off at 4000. (This is just an example, the real sequence is more complicated). Any info would be great. Thanks in advance


uint16_t SRC_Buffer[4] = {1000,2000,3000,4000};

uint16_t TimerPeriod = 10000;


GPIO_InitTypeDef GPIO_InitStructure;

DMA_InitTypeDef DMA_InitStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;


/* TIM 1 */

/* channel 3 pin configuration as outputs for PWM mode */

/* Maple pin D8 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA, &GPIO_InitStructure);


/* DMA1 Channel5 Config */

DMA_DeInit(DMA1_Channel5);


DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM1->CCR3;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SRC_Buffer;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 4;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;


DMA_Init(DMA1_Channel5, &DMA_InitStructure);


/* DMA1 Channel5 enable */

DMA_Cmd(DMA1_Channel5, ENABLE);


/* TIM1 Peripheral Configuration --------------------------------------------*/

/* Time Base configuration */

TIM_TimeBaseStructure.TIM_Prescaler = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_Period = TimerPeriod;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;


TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);


/* Channel 3 Configuration in PWM mode */

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

TIM_OCInitStructure.TIM_Pulse = SRC_Buffer[0];

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;

TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;

TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;


TIM_OC3Init(TIM1, &TIM_OCInitStructure);

//--------//

TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Disable);


/* TIM1 Update DMA Request enable */

TIM_DMACmd(TIM1, TIM_DMA_CC3, ENABLE);


/* TIM1 counter enable */

TIM_Cmd(TIM1, ENABLE);


TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);


/* Main Output Enable */

TIM_CtrlPWMOutputs(TIM1, ENABLE);

4 REPLIES 4
Posted on May 21, 2016 at 04:09

Must configure

DMA1_Channel6

not

DMA1_Channel5

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 21, 2016 at 09:51

Hi clive1,

Apologies, that was a typo.  I have configured channel 5 not channel 6.  The code 'snippet' does have channel 5 in it.  Is there some preload settings I have missing or something that I need to allow the capture compare request to work?

mark239955_stm1
Associate II
Posted on May 22, 2016 at 05:23

It looks to me like you're configuring DMA to trigger from the TIM1_UP signal (on DMA channel 5), but configuring TIM1 to generate DMA requests to TIM1_CC3 (on DMA channel 6).

robertnoble9
Associate III
Posted on May 23, 2016 at 10:57

markt, ah what a fool I am.  Over the weekend I changed my code to use TIMER 3 channel 3 instead, following the table of request mapping for DMA 1 I got it working as expected, using DMA 1 channel 2. I now realise what I have done.  I have used TIMER 1 channel 3 UP on DMA1 channel 5.  I should be using DMA 1 channel 6 (as you say) to get TIMER 1 channel 3 requests working. I feel like an idiot, haha.  I can now change back to TIMER 1 knowing what I did wrong.  I will have to go to TIMER 1 channel 1 using DMA 1 channel 2 as I am already using DMA 1 channel 6 for USART2 RX data transfers.

Thanks again for the help guys.