cancel
Showing results for 
Search instead for 
Did you mean: 

AD at higest posible speed with DMA

finnb
Associate II
Posted on August 22, 2009 at 07:52

AD at higest posible speed with DMA

3 REPLIES 3
finnb
Associate II
Posted on May 17, 2011 at 13:20

Hi folks, im trying to get the the stm32 to sample at 1M Samples/sec but only getting max the half .... what is wrong ???

I use Timer1 and DMA to trigger Ad converter. The timer is triggering at 1MHz in this config. I have a scope on the OC1 to check with a scope, that im getting triggered at 1MHz.

i have a 8MHz Xtal, at the pll multiplier is set to 7 = 56Mhz

/f

void InitTIM1(void)

{

TIM_TimeBaseInitTypeDef TIM1_TimeBaseStructure;

TIM_OCInitTypeDef TIM1_OCInitStructure;

TIM1_TimeBaseStructure.TIM_Prescaler = 0;

TIM1_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM1_TimeBaseStructure.TIM_Period = 55; //

TIM1_TimeBaseStructure.TIM_ClockDivision = 0x0;

TIM1_TimeBaseStructure.TIM_RepetitionCounter = 0x0;

TIM_TimeBaseInit(TIM1, &TIM1_TimeBaseStructure);

// using a scope to see the frequency ...

TIM1_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM1_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM1_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;

TIM1_OCInitStructure.TIM_Pulse = 10;

TIM1_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;

TIM_OC1Init(TIM1,&TIM1_OCInitStructure);

// TIM1 counter enable

TIM_Cmd(TIM1,ENABLE);

// TIM1 main Output Enable

TIM_CtrlPWMOutputs(TIM1,ENABLE);

}

AD Setup...

void ADC_init(void)

{

ADC_InitTypeDef ADC_InitStructure;

ADC_DeInit(ADC1);

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

ADC_InitStructure.ADC_ScanConvMode = DISABLE;

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_NbrOfChannel = 1;

ADC_Init( ADC1, &ADC_InitStructure );

// ADC1 Regular Channel 2 Configuration

ADC_RegularChannelConfig( ADC1, ADC_Channel_8, 1, ADC_SampleTime_1Cycles5);

// Enable ADC1 DMA

ADC_DMACmd(ADC1, ENABLE);

// Enable ADC1 external trigger

ADC_ExternalTrigConvCmd(ADC1, ENABLE);

// Enable ADC1

ADC_Cmd(ADC1, ENABLE);

}

DMA setup :

void DMA_init(void)

{

DMA_InitTypeDef DMA_InitStructure;

// Reconfig the DMA channel 1

//DMA_DeInit(DMA1);

DMA_DeInit(DMA1_Channel1_BASE );

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;

DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ECG_Buff[0];

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = ECG_BUFF_SIZE;

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

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init( DMA1_Channel1_BASE, &DMA_InitStructure );

// Enable DMA Channel1 Transfer half and Complete interrupt

// DMA_ITConfig(DMA1_Channel1_BASE, DMA_IT_TC | DMA_IT_HT, ENABLE);

DMA_ITConfig(DMA1_Channel1_BASE, DMA_IT_TC , ENABLE);

// Enable DMA Channel1

DMA_Cmd( DMA1_Channel1_BASE, ENABLE );

}

void RCC_Configuration(void)

{

RCC_DeInit();

RCC_HSEConfig(RCC_HSE_ON);

HSEStartUpStatus = RCC_WaitForHSEStartUp();

if(HSEStartUpStatus == SUCCESS)

{

FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

FLASH_SetLatency(FLASH_Latency_2);

RCC_HCLKConfig(RCC_SYSCLK_Div1);

RCC_PCLK2Config(RCC_HCLK_Div1);

RCC_PCLK1Config(RCC_HCLK_Div2);

RCC_ADCCLKConfig(RCC_PCLK2_Div4);

RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7);

RCC_PLLCmd(ENABLE);

while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

{

}

RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

while(RCC_GetSYSCLKSource() != 0x08)

{

}

}

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_TIM1 | RCC_APB2Periph_USART1|

RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);

}

16-32micros
Associate III
Posted on May 17, 2011 at 13:20

Hi,

Try this in your ADC configuration :

ADC_InitStructure.ADC_ScanConvMode = ENABLE;

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

Hope this helps you

Cheers,

STOne-32.

guyvo67
Associate II
Posted on May 17, 2011 at 13:20

ADC_InitStructure.ADC_ScanConvMode = ENABLE;

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

Yes that can help a lot 😉

But if you start the conversion from within a timer interrupt event like:

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

and you only want to threat 1 value at the time in the ADC EOC interrupt handler than enabling the ADC_ContinuousConvMode isn't necessary.

cheers

Guy