cancel
Showing results for 
Search instead for 
Did you mean: 

DMA and timers problem

mpmichal
Associate II
Posted on April 28, 2011 at 18:44

Hi,

I wanted to learn how to ''connect'' DMA and timers, so I am thinking about such application. App will circularly copy data from buffer to timer. Timer is set in PWM mode and in my data buffer are numbers starting from 0 to 99 (those are pulse values). I have LED connected to PA8, and my code gives no errors, however it doesn't work. LED should shine and from time to time changes it's brightness, but nothing happens, it is off all the time. Could anybody help me with this? I also have empty NVIC_Configuration function because I don't really know what should be there. Here is my code:

&sharpinclude ''stm32f10x.h''

&sharpinclude ''STM32vldiscovery.h''

void RCC_Configuration(void);

void GPIO_Configuration(void) ;

void NVIC_Configuration(void) ;

void DMA_Configuration(void) ;

void TIM1_Configuration(void) ;

int i = 0;

u16 PWM_Buffer[100];

/**************************************************************************************/

int main(void)

{

for(i=0 ; i < 100 ; i++) PWM_Buffer[i] = i;

RCC_Configuration();

GPIO_Configuration() ;

NVIC_Configuration() ;

DMA_Configuration();

TIM1_Configuration();

while(1);

}

/**************************************************************************************/

void RCC_Configuration(void)

{

// clock for GPIO

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE);

// clock for DMA

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

// clock for TIM1

RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

}

/**************************************************************************************/

void GPIO_Configuration(void)

{

GPIO_InitTypeDef GPIO_InitStructure ;

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin |= GPIO_Pin_8 ;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

/**************************************************************************************/

void NVIC_Configuration(void)

{

}

/**************************************************************************************/

void DMA_Configuration(void)

{

DMA_DeInit(DMA1_Channel5);

DMA_InitTypeDef DMA_InitStructure ;

DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_BASE;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)PWM_Buffer;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 100;

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);

// turning DMA on

DMA_Cmd(DMA1_Channel5, ENABLE);

}

/**************************************************************************************/

void TIM1_Configuration(void)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;

TIM_TimeBaseStructure.TIM_Period = 99;

TIM_TimeBaseStructure.TIM_Prescaler = 99;

TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseStructure.TIM_RepetitionCounter = 150;

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

// channel 1 configuration

TIM_OCInitTypeDef TIM_OCInitStructure;

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_Pulse = 50;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC1Init(TIM1, &TIM_OCInitStructure);

// ''connecting'' DMA and TIM1

TIM_DMACmd(TIM1, TIM_DMA_Update, ENABLE);

// turning on TIM1 and PWM outputs

TIM_Cmd(TIM1, ENABLE);

TIM_CtrlPWMOutputs(TIM1, ENABLE);

}

/**************************************************************************************/

#dma-timers
5 REPLIES 5
Posted on April 28, 2011 at 23:00

If you want to alter the PWM ON from 0-99% it might help to program the right register in the timer. I might tinker some more, but this seemed to be pretty fatal on a quick review.

  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM1_CCR1_Address;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mpmichal
Associate II
Posted on April 29, 2011 at 12:16

I am using Atollic True Studio and I don't have this defined:

TIM1_CCR1_Address

But I found that this is equal to: 0x40012C34 so I changed that line, but it still doesn't work.

Posted on April 29, 2011 at 18:23

With TIM1_CCR1_Address 0x40012C34

The PA.08 output is 2.4 KHz (from 24 MHz core), and the on duty cycle sweeps from 0 to 99%, repetitively. Stick a scope on it, and observe.

The LEDs built on the board are on PC.08 and PC.09
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 29, 2011 at 20:53

Here is a better example, using the on-board Blue PC.8 LED, and TIM3 CH3 with DMA1 Channel 3 shoveling PWM data on the TIM3 update (10 ms). This example uses a 10 KHz timer clock, a 100 Hz output frequency, with a 0-99% duty cycle phased over 1 second.

// PC.08, TIM3_CH3 (Remapped), DMA1 Channel 3

#define TIM3_CCR3_Address   0x4000043C

void RCC_Configuration(void);

void GPIO_Configuration(void) ;

void NVIC_Configuration(void) ;

void DMA_Configuration(void) ;

void TIM3_Configuration(void) ;

#define PWM_ELEMENTS 100

u16 PWM_Buffer[PWM_ELEMENTS];

/**************************************************************************************/

int main(void)

{

    int i;

  for(i=0 ; i < PWM_ELEMENTS ; i++) PWM_Buffer[i] = i / (PWM_ELEMENTS / 100);

  RCC_Configuration();

  GPIO_Configuration() ;

  NVIC_Configuration() ;

  DMA_Configuration();

  TIM3_Configuration();

  while(1);

}

/**************************************************************************************/

void RCC_Configuration(void)

{

    // clock for GPIO (C, AFIO=REMAP)

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO , ENABLE);

    // clock for DMA

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

    // clock for TIM3

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

}

/**************************************************************************************/

void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure ;

  GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

    GPIO_Init(GPIOC, &GPIO_InitStructure);

}

/**************************************************************************************/

void NVIC_Configuration(void)

{

}

/**************************************************************************************/

void DMA_Configuration(void)

{

    DMA_InitTypeDef DMA_InitStructure ;

    DMA_DeInit(DMA1_Channel3);

    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)TIM3_CCR3_Address;

    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)PWM_Buffer;

    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

    DMA_InitStructure.DMA_BufferSize = PWM_ELEMENTS;

    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_Channel3, &DMA_InitStructure);

    // turning DMA on

    DMA_Cmd(DMA1_Channel3, ENABLE);

}

/**************************************************************************************/

void TIM3_Configuration(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;

    TIM_OCInitTypeDef TIM_OCInitStructure;

    TIM_TimeBaseStructure.TIM_Period = 100-1; // 100 0..99    ON DUTY (100 Hz) Phases over 1 Second

    TIM_TimeBaseStructure.TIM_Prescaler = 2400-1;    // 24 MHz div 2400 (10 KHz tick)

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseStructure.TIM_RepetitionCounter = 1;

    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // channel 3 configuration (PC.08) Remapped

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = 50;

    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    TIM_OC3Init(TIM3, &TIM_OCInitStructure);

    // ''connecting'' DMA and TIM3

    TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE);

    // turning on TIM3 and PWM outputs

    TIM_Cmd(TIM3, ENABLE);

    TIM_CtrlPWMOutputs(TIM3, ENABLE);

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mpmichal
Associate II
Posted on April 30, 2011 at 11:18

Thank you very much! That solves my problem.