2016-05-20 06:46 PM
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);
2016-05-20 07:09 PM
Must configure
DMA1_Channel6
not
DMA1_Channel5
2016-05-21 12:51 AM
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?2016-05-21 08:23 PM
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).
2016-05-23 01:57 AM
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.