cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F3Discovery ADC_DMA project

ivanucherdjiev
Associate II
Posted on September 19, 2014 at 14:56

Good afternoon,

I made a project and i set ADC1 in independent mode and DMA1 to read the information from the adc and then write it to the memory. In the Datasheet and in the Reference manual is writen that the ADC can max. have 4.8 MSPS at slow channel but the DMA cannot transfer the data so fast, so it overflow.... it stop overflow when i set the ADC at 2.4MSPS ... is there a way to set the DMA to transfer data faster so i can use the ADC at 4.8MSPS

Thanks you.

Best Regards!
7 REPLIES 7
Posted on September 19, 2014 at 17:58

The ADC+DMA is demonstrably capable of rates exceeding 5.1 MSps. Perhaps you have an unrealistically small sample buffer? Perhaps your bus clocks are non-optimal?

1000 Samples, High Priority, Circular
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ivanucherdjiev
Associate II
Posted on September 24, 2014 at 09:30

Clock frequecy is 72MHz(optimal), the DMA buffer size is set 300 (for 300 samples) . I read the sampling information from the  regular data register when in independent mode and from common data register in dual interleaved mode. The DMA write the information in a array (the array stores 300 halfwords) ...  max sampling rate i could get from 1 ADC is 2.4 Msps on slow channel....and  in dual mode i get 4.8 Msps 

ivanucherdjiev
Associate II
Posted on September 24, 2014 at 09:31

Can you please send me a example code for ADC + DMA working on 5.1 Msps  or tell me where I can send you mine, so you can check what do i do wrong if it is not a problem ... thank you

Posted on September 24, 2014 at 17:14

How you plan to process data at that rate, now that's a whole different kettle of fish...

// STM32 ADC Rapid 5.143 MSps STM32F3-Discovery - sourcer32@gmail.com
// Conversion + Sample time, 5 + 1.5 Cycles = 14
// 72 MHz / 14 = 5.142857 MHz
/**************************************************************************************/
// FAST ADC1_IN1, ADC1_IN2, ADC1_IN3, ADC1_IN4, ADC1_IN5
// SLOW ADC12_IN6, ADC12_IN7, ADC12_IN8, ADC12_IN9, ADC12_IN10
/**************************************************************************************/
#include ''stm32f3_discovery.h''
#include ''stm32f30x.h''
#include <
stdio.h
>
/**************************************************************************************/
#define BUFSIZE 1000
volatile uint16_t ADCConvertedValues[BUFSIZE];
uint16_t CalibrationValue;
/**************************************************************************************/
void ADC_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA and GPIOB Periph clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
/* ADC Channels configuration */
/* Configure as analog input */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**************************************************************************************/
void ADC12_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA configuration */
/* DMA1 Channel1 Init Test */
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; // The register of a singular ADC
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValues[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BUFSIZE;
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_Channel1, &DMA_InitStructure); // ADC1
}
/**************************************************************************************/
void ADC_Configuration(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
volatile int i;
/* Configure the ADC clocks */
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div1);
/* Enable ADC1/2 clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE);
/* ADC GPIO configuration */
ADC_GPIO_Configuration();
/* ADC DMA Channel configuration */
ADC12_DMA_Configuration();
/* ADC Calibration procedure */
ADC_VoltageRegulatorCmd(ADC1, ENABLE);
/* Insert delay equal to 10 µs */
for(i=0; i<
10000
; i++);
ADC_SelectCalibrationMode(ADC1, ADC_CalibrationMode_Single);
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1) != RESET);
CalibrationValue
= 
ADC_GetCalibrationValue
(ADC1);
/* ADC configuration */
ADC_CommonInitStructure.ADC_Mode
= 
ADC_Mode_Independent
;
ADC_CommonInitStructure.ADC_Clock
= 
ADC_Clock_AsynClkMode
;
ADC_CommonInitStructure.ADC_DMAAccessMode
= 
ADC_DMAAccessMode_Disabled
; // Not Multi Mode
ADC_CommonInitStructure.ADC_DMAMode
= 
ADC_DMAMode_Circular
;
ADC_CommonInitStructure.ADC_TwoSamplingDelay
= 
10
;
ADC_CommonInit(ADC1, &ADC_CommonInitStructure);
/* */
ADC_InitStructure.ADC_ContinuousConvMode
= 
ADC_ContinuousConvMode_Enable
; // Full On
ADC_InitStructure.ADC_Resolution
= 
ADC_Resolution_12b
;
ADC_InitStructure.ADC_ExternalTrigEventEdge
= 
ADC_ExternalTrigEventEdge_None
;
ADC_InitStructure.ADC_ExternalTrigConvEvent
= 
ADC_ExternalTrigConvEvent_3
; // Not used here
ADC_InitStructure.ADC_DataAlign
= 
ADC_DataAlign_Right
;
ADC_InitStructure.ADC_OverrunMode
= 
ADC_OverrunMode_Disable
;
ADC_InitStructure.ADC_AutoInjMode
= 
ADC_AutoInjec_Disable
;
ADC_InitStructure.ADC_NbrOfRegChannel
= 
1
;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 1, ADC_SampleTime_1Cycles5); // PA1 - ADC1_IN2
/* Configures the ADC DMA */
ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);
/* Enable the ADC DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* wait for ADC1 ADRDY */
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
/* Enable the DMA channel */
DMA_Cmd(DMA1_Channel1, ENABLE);
/* Start ADC1 Software Conversion */
ADC_StartConversion(ADC1);
}
/**************************************************************************************/
void DMA1_Channel1_IRQHandler(void) // 5.143 KHz (1000 Samples at 5.143 MSps)
{
/* Test on DMA1 Channel1 Transfer Complete interrupt */
if (DMA_GetITStatus(DMA1_IT_TC1))
{
/* Clear DMA1 Channel1 Half Transfer, Transfer Complete and Global interrupt pending bits */
DMA_ClearITPendingBit(DMA1_IT_GL1);
STM_EVAL_LEDToggle(LED3); // 2.571 KHz
}
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the DMA1 CH1 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel
= 
DMA1_Channel1_IRQn
;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority
= 
0
;
NVIC_InitStructure.NVIC_IRQChannelSubPriority
= 
1
;
NVIC_InitStructure.NVIC_IRQChannelCmd
= 
ENABLE
;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
int main(void)
{
/* Initialize LEDs available on STM32F-Discovery board */
STM_EVAL_LEDInit(LED3);
STM_EVAL_LEDInit(LED4);
/* Turn on LD3 */
STM_EVAL_LEDOn(LED3);
STM_EVAL_LEDOn(LED4);
NVIC_Configuration();
ADC_Configuration();
/* Enable DMA1 Channel1 Transfer Complete interrupt */
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
while(1) // Don't want to exit
{
if (ADCConvertedValues[0] != 0xFFFF)
{
printf(''%03X %03X %03
X'', ADCConvertedValues[0], ADCConvertedValues[1], ADCConvertedValues[2]);
ADCConvertedValues[0] = 0xFFFF;
}
}
}
//******************************************************************************
// Rough SWV support in Keil, STM32F3-Discovery, Make SB10 to connect PB3/SWO
//******************************************************************************
#include <rt_misc.h>
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
ITM_SendChar(ch);
return(ch);
}
int fgetc(FILE *f)
{
char ch;
ch = 1;
return((int)ch);
}
int ferror(FILE *f)
{
/* Your implementation of ferror */
return EOF;
}
void _ttywrch(int ch)
{
ITM_SendChar(ch);
}
void _sys_exit(int return_code)
{
label: goto label; /* endless loop */
}
//******************************************************************************
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
//******************************************************************************

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ivanucherdjiev
Associate II
Posted on September 25, 2014 at 09:17

Thank you very much for the replay! I'am going to try the example and post a replay little bit later. Thank you very much again!

ivanucherdjiev
Associate II
Posted on September 25, 2014 at 14:37

Thank you very much for your support. I saw where was my mistake and i fixed it. I made it working at dual interleaved mode + DMA with 9Msps. Thank you very much again. 

Best regards!
xaionaro
Associate
Posted on August 09, 2015 at 20:55

Hello. Can you share with the full code (via GitHub or so)?