cancel
Showing results for 
Search instead for 
Did you mean: 

DMA transfer using three ADC’s, 24 channels, and three streams

dlafreniere
Associate II
Posted on August 21, 2014 at 03:37

I am trying to get 24 ADC channels to transfer using DMA. The following code works for ADC2 and ADC3, but ADC1 the data stored in the DMA buffer is random. The data for ADC1 can sometimes appear correct, but the data is in the wrong position (e.g. ADCConvertedValue[0] data is located at ADCConvertedValue[3]). It is like the DMA is out of sync with the buffer positioning. ADC2 and ADC3 data appears valid and is not scrambled.

I have tried many different combinations of DMA and ADC settings, but can’t seem to get the whole thing working.

I don’t need an interrupt or an external trigger when the converstions are complete. I just need all 24 ADC channels continually transferring data to the DMA buffer in the background.

Any ideas on how to reliably get all 24 channels working? Why would the DMA transfer loose position synchronization with the data buffer?

Thanks in advance for any assistance.

const INT ADC_BUFFER_SIZE = 8; 
static __IO uint16_t ADCConvertedValue[ADC_BUFFER_SIZE*3] __attribute__((at(0x20002000))); 
struct ADC_ConfigData 
{ 
uint16_t GPIO_Pin; 
GPIO_TypeDef* GPIO_Port; 
ADC_TypeDef* ADCx; 
uint8_t ADC_Channel; 
}; 
// ADC1 configurations 
const ADC_ConfigData ADC1_CONFIG[] = 
{ 
{GPIO_Pin_0, GPIOA, ADC1, ADC_Channel_0 }, 
{GPIO_Pin_1, GPIOA, ADC1, ADC_Channel_1 }, 
{GPIO_Pin_2, GPIOA, ADC1, ADC_Channel_2 }, 
{GPIO_Pin_3, GPIOA, ADC1, ADC_Channel_3 }, 
{GPIO_Pin_0, GPIOC, ADC1, ADC_Channel_10 }, 
{GPIO_Pin_1, GPIOC, ADC1, ADC_Channel_11 }, 
{GPIO_Pin_2, GPIOC, ADC1, ADC_Channel_12 }, 
{GPIO_Pin_3, GPIOC, ADC1, ADC_Channel_13 } 
}; 
// ADC2 configurations 
const ADC_ConfigData ADC2_CONFIG[] = 
{ 
{GPIO_Pin_6, GPIOA, ADC2, ADC_Channel_6 }, 
{GPIO_Pin_7, GPIOA, ADC2, ADC_Channel_7 }, 
{GPIO_Pin_5, GPIOA, ADC2, ADC_Channel_5 }, 
{GPIO_Pin_4, GPIOA, ADC2, ADC_Channel_4 }, 
{GPIO_Pin_5, GPIOC, ADC2, ADC_Channel_15 }, 
{GPIO_Pin_0, GPIOB, ADC2, ADC_Channel_8 }, 
{GPIO_Pin_1, GPIOB, ADC2, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOC, ADC2, ADC_Channel_14 } 
}; 
// ADC3 configurations 
const ADC_ConfigData ADC3_CONFIG[] = 
{ 
{GPIO_Pin_5, GPIOF, ADC3, ADC_Channel_15 }, 
{GPIO_Pin_10,GPIOF, ADC3, ADC_Channel_8 }, 
{GPIO_Pin_3, GPIOF, ADC3, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOF, ADC3, ADC_Channel_14 }, 
{GPIO_Pin_6, GPIOF, ADC3, ADC_Channel_4 }, 
{GPIO_Pin_7, GPIOF, ADC3, ADC_Channel_5 }, 
{GPIO_Pin_8, GPIOF, ADC3, ADC_Channel_6 }, 
{GPIO_Pin_9, GPIOF, ADC3, ADC_Channel_7 } 
}; 
static const INT ADC1_SENSORS = sizeof(ADC1_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC2_SENSORS = sizeof(ADC2_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC3_SENSORS = sizeof(ADC3_CONFIG)/sizeof(ADC_ConfigData); 
//------------------------------------------------------------------------------ 
// AdcInitialize 
//------------------------------------------------------------------------------ 
void AdcInitialize() 
{ 
DMA_Config(); 
ADC_Config(); 
} 
//------------------------------------------------------------------------------ 
// ADC_Config 
//------------------------------------------------------------------------------ 
static void ADC_Config() 
{ 
// Enable peripheral clocks 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE); 
// ADC common initialization 
ADC_CommonInitTypeDef ADC_CommonInitStructure; 
ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; 
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; 
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; 
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 
ADC_CommonInit(&ADC_CommonInitStructure); 
ADC_InitTypeDef ADC_InitStructure; 
ADC_StructInit(&ADC_InitStructure); 
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; 
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
// Initialize all ADC's 
ADC_InitStructure.ADC_NbrOfConversion = ADC1_SENSORS; 
ADC_Init(ADC1, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC2_SENSORS; 
ADC_Init(ADC2, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC3_SENSORS; 
ADC_Init(ADC3, &ADC_InitStructure); 
// Configure the GPIO pin for ADC input 
GPIO_InitTypeDef GPIO_InitStructure; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
// Configure ADC1 GPIO's 
for (INT sensor=0; sensor<
ADC1_SENSORS
; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC1_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC1_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC1_CONFIG[sensor].ADCx, ADC1_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_15Cycles); 
} 
// Configure ADC2 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC2_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC2_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC2_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC2_CONFIG[sensor].ADCx, ADC2_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_15Cycles); 
} 
// Confifure ADC3 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC3_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC3_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC3_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC3_CONFIG[sensor].ADCx, ADC3_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_15Cycles); 
} 
// Enable DMA request after last transfer 
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); 
ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE); 
ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE); 
// Enable ADC DMA 
ADC_DMACmd(ADC1, ENABLE); 
ADC_DMACmd(ADC2, ENABLE); 
ADC_DMACmd(ADC3, ENABLE); 
// Enable all ADC's 
ADC_Cmd(ADC1, ENABLE); 
ADC_Cmd(ADC2, ENABLE); 
ADC_Cmd(ADC3, ENABLE); 
// Start all ADC conversions 
ADC_SoftwareStartConv(ADC1); 
ADC_SoftwareStartConv(ADC2); 
ADC_SoftwareStartConv(ADC3); 
} 
//------------------------------------------------------------------------------ 
// DMA_Config 
//------------------------------------------------------------------------------ 
static void DMA_Config(void) 
{ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
DMA_InitTypeDef DMA_InitStructure; 
DMA_StructInit(&DMA_InitStructure); 
// ADC1, DMA2, Channel0, Stream0 configuration 
DMA_DeInit(DMA2_Stream0); 
DMA_InitStructure.DMA_Channel
= 
DMA_Channel_0
; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[0]; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
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_FIFOMode = DMA_FIFOMode_Enable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; 
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_InitStructure.DMA_BufferSize = ADC1_SENSORS; 
DMA_Init(DMA2_Stream0, &DMA_InitStructure); 
DMA_Cmd(DMA2_Stream0, ENABLE); 
// ADC2, DMA2, Channel1, Stream2 configuration 
DMA_DeInit(DMA2_Stream2); 
DMA_InitStructure.DMA_Channel = DMA_Channel_1; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[ADC_BUFFER_SIZE]; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC2->DR; 
DMA_InitStructure.DMA_BufferSize = ADC2_SENSORS; 
DMA_Init(DMA2_Stream2, &DMA_InitStructure); 
DMA_Cmd(DMA2_Stream2, ENABLE); 
// ADC3, DMA2, Channel2, Stream1 configuration 
DMA_DeInit(DMA2_Stream1); 
DMA_InitStructure.DMA_Channel = DMA_Channel_2; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[ADC_BUFFER_SIZE*2]; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC3->DR; 
DMA_InitStructure.DMA_BufferSize = ADC3_SENSORS; 
DMA_Init(DMA2_Stream1, &DMA_InitStructure); 
DMA_Cmd(DMA2_Stream1, ENABLE); 
} 

7 REPLIES 7
Posted on August 21, 2014 at 04:18

Isn't the point of triple mode to lock step the ADCs, use a single DMA stream, and read from the common data register, not the ADCx->DR? If you want it to work in Independent Mode, configure it that way.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
dlafreniere
Associate II
Posted on August 21, 2014 at 16:15 Thanks for the quick response. I was not aware that the triple modes were only usable on one data stream. I did try various combinations of the ADC->CDR with the DMA without success. The table below seems to suggest that the a single stream cannot be used for all three ADC's. For instance, stream 0 channel 0 can be used for ADC1 and ADC3. Is that correct? I have tried changing:

ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult;

To:

ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

Which did notwork. I don't really care if the ADC's are in lock step, just that the ADC conversions are occurring in the background. 0690X0000060MmcQAE.gif
dlafreniere
Associate II
Posted on August 21, 2014 at 17:10

Let me clarify. When I say this line of code does not work.

ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

I mean it works in the same way as the ADC_TripleMode_RegSimult does. The ADC1 values are all random and the ADC2 and ADC3 values are correct. I have even tried other examples with external triggers, only two channels on ADC1 and ADC2 with one stream, and it has the same problem: The DMA seems to loose sync with the buffer such that it can't load the correct ADC converted values into the correct memory buffer location. I am at a loss on how to make the DMA-to-buffer transfers stay consistenton ADC1.
dlafreniere
Associate II
Posted on August 22, 2014 at 00:47

I've changed the code to correctly (I think) implement the Triple_Mode_RegSimult. Now I'm using one DMA stream and reading data from the three ADC's using ADC->CDC (common data register). And it works... for a while. Within a minute or two the DMA loses sync with the buffer and the data in my DMA destination buffer shifts upward by one. Wait a little longer, then is shift upwards again.

The DMAtransfers don'tstay sync'ed with the ADCConvertedValue[] buffer. It is off by 1, then by 2, such that the data isn't in the right spot. Any ideas? Has anyone ever got a full 24-channel DMA setup towork? Thanks again for any help.

const INT ADC_BUFFER_SIZE = 8; 
static __IO uint16_t ADCConvertedValue[ADC_BUFFER_SIZE*3] __attribute__((at(0x20002000))); 
struct ADC_ConfigData 
{ 
uint16_t GPIO_Pin; 
GPIO_TypeDef* GPIO_Port; 
ADC_TypeDef* ADCx; 
uint8_t ADC_Channel; 
}; 
// ADC1 configurations 
const ADC_ConfigData ADC1_CONFIG[] = 
{ 
{GPIO_Pin_0, GPIOA, ADC1, ADC_Channel_0 }, 
{GPIO_Pin_1, GPIOA, ADC1, ADC_Channel_1 }, 
{GPIO_Pin_2, GPIOA, ADC1, ADC_Channel_2 }, 
{GPIO_Pin_3, GPIOA, ADC1, ADC_Channel_3 }, 
{GPIO_Pin_0, GPIOC, ADC1, ADC_Channel_10 }, 
{GPIO_Pin_1, GPIOC, ADC1, ADC_Channel_11 }, 
{GPIO_Pin_2, GPIOC, ADC1, ADC_Channel_12 }, 
{GPIO_Pin_3, GPIOC, ADC1, ADC_Channel_13 } 
}; 
// ADC2 configurations 
const ADC_ConfigData ADC2_CONFIG[] = 
{ 
{GPIO_Pin_6, GPIOA, ADC2, ADC_Channel_6 }, 
{GPIO_Pin_7, GPIOA, ADC2, ADC_Channel_7 }, 
{GPIO_Pin_5, GPIOA, ADC2, ADC_Channel_5 }, 
{GPIO_Pin_4, GPIOA, ADC2, ADC_Channel_4 }, 
{GPIO_Pin_5, GPIOC, ADC2, ADC_Channel_15 }, 
{GPIO_Pin_0, GPIOB, ADC2, ADC_Channel_8 }, 
{GPIO_Pin_1, GPIOB, ADC2, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOC, ADC2, ADC_Channel_14 } 
}; 
// ADC3 configurations 
const ADC_ConfigData ADC3_CONFIG[] = 
{ 
{GPIO_Pin_5, GPIOF, ADC3, ADC_Channel_15 }, 
{GPIO_Pin_10,GPIOF, ADC3, ADC_Channel_8 }, 
{GPIO_Pin_3, GPIOF, ADC3, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOF, ADC3, ADC_Channel_14 }, 
{GPIO_Pin_6, GPIOF, ADC3, ADC_Channel_4 }, 
{GPIO_Pin_7, GPIOF, ADC3, ADC_Channel_5 }, 
{GPIO_Pin_8, GPIOF, ADC3, ADC_Channel_6 }, 
{GPIO_Pin_9, GPIOF, ADC3, ADC_Channel_7 } 
}; 
static const INT ADC1_SENSORS = sizeof(ADC1_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC2_SENSORS = sizeof(ADC2_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC3_SENSORS = sizeof(ADC3_CONFIG)/sizeof(ADC_ConfigData); 
//------------------------------------------------------------------------------ 
// AdcInitialize 
//------------------------------------------------------------------------------ 
void AdcInitialize() 
{ 
DMA_Config(); 
ADC_Config(); 
} 
//------------------------------------------------------------------------------ 
// ADC_Config 
//------------------------------------------------------------------------------ 
static void ADC_Config() 
{ 
// Enable peripheral clocks 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE); 
// ADC common initialization 
ADC_CommonInitTypeDef ADC_CommonInitStructure; 
ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; 
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; 
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; 
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles; 
ADC_CommonInit(&ADC_CommonInitStructure); 
ADC_InitTypeDef ADC_InitStructure; 
ADC_StructInit(&ADC_InitStructure); 
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; 
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
// Initialize all ADC's 
ADC_InitStructure.ADC_NbrOfConversion = ADC1_SENSORS; 
ADC_Init(ADC1, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC2_SENSORS; 
ADC_Init(ADC2, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC3_SENSORS; 
ADC_Init(ADC3, &ADC_InitStructure); 
// Configure the GPIO pin for ADC input 
GPIO_InitTypeDef GPIO_InitStructure; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; //TODO - GPIO_PuPd_NOPULL; 
// Configure ADC1 GPIO's 
for (INT sensor=0; sensor<
ADC1_SENSORS
; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC1_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC1_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC1_CONFIG[sensor].ADCx, ADC1_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_480Cycles); 
} 
// Configure ADC2 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC2_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC2_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC2_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC2_CONFIG[sensor].ADCx, ADC2_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_480Cycles); 
} 
// Confifure ADC3 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC3_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC3_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC3_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC3_CONFIG[sensor].ADCx, ADC3_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_480Cycles); 
} 
// Enable multi-mode DMA request after last transfer 
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); 
// Enable all ADC's 
ADC_Cmd(ADC1, ENABLE); 
ADC_Cmd(ADC2, ENABLE); 
ADC_Cmd(ADC3, ENABLE); 
// Start ADC1 (master) conversion. ADC2 and ADC3 will convert as slaves. 
ADC_SoftwareStartConv(ADC1); 
} 
//------------------------------------------------------------------------------ 
// DMA_Config 
//------------------------------------------------------------------------------ 
static void DMA_Config(void) 
{ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
DMA_InitTypeDef DMA_InitStructure; 
DMA_StructInit(&DMA_InitStructure); 
// ADC common data register, DMA2, Channel0, Stream0 configuration 
DMA_DeInit(DMA2_Stream0); 
DMA_InitStructure.DMA_Channel
= 
DMA_Channel_0
; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[0]; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR; 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
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_FIFOMode = DMA_FIFOMode_Enable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; 
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_InitStructure.DMA_BufferSize = ADC1_SENSORS + ADC2_SENSORS + ADC3_SENSORS; 
DMA_Init(DMA2_Stream0, &DMA_InitStructure); 
DMA_Cmd(DMA2_Stream0, ENABLE); 
} 

dlafreniere
Associate II
Posted on August 25, 2014 at 18:17

For future reference, the code below seems to be working correctly. TIM8 is used to control the rate of ADC conversions by using the timer TRGO output.

//static const uint32_t SystemCoreClock = 168000000; 
#define TIM_FREQUENCY 1000 // 1mS ADC sampling of all 24 channels 
#define TIM_PERIOD 1000 
#define TIM_PRESCALER (SystemCoreClock/2)/(TIM_PERIOD*TIM_FREQUENCY) 
const INT ADC_BUFFER_SIZE = 8; 
static __IO uint16_t ADCConvertedValue[ADC_BUFFER_SIZE*3] __attribute__((at(0x20002000))); 
struct ADC_ConfigData 
{ 
uint16_t GPIO_Pin; 
GPIO_TypeDef* GPIO_Port; 
ADC_TypeDef* ADCx; 
uint8_t ADC_Channel; 
}; 
// ADC1 configurations 
const ADC_ConfigData ADC1_CONFIG[] = 
{ 
{GPIO_Pin_0, GPIOA, ADC1, ADC_Channel_0 }, 
{GPIO_Pin_1, GPIOA, ADC1, ADC_Channel_1 }, 
{GPIO_Pin_2, GPIOA, ADC1, ADC_Channel_2 }, 
{GPIO_Pin_3, GPIOA, ADC1, ADC_Channel_3 }, 
{GPIO_Pin_0, GPIOC, ADC1, ADC_Channel_10 }, 
{GPIO_Pin_1, GPIOC, ADC1, ADC_Channel_11 }, 
{GPIO_Pin_2, GPIOC, ADC1, ADC_Channel_12 }, 
{GPIO_Pin_3, GPIOC, ADC1, ADC_Channel_13 } 
}; 
// ADC2 configurations 
const ADC_ConfigData ADC2_CONFIG[] = 
{ 
{GPIO_Pin_6, GPIOA, ADC2, ADC_Channel_6 }, 
{GPIO_Pin_7, GPIOA, ADC2, ADC_Channel_7 }, 
{GPIO_Pin_5, GPIOA, ADC2, ADC_Channel_5 }, 
{GPIO_Pin_4, GPIOA, ADC2, ADC_Channel_4 }, 
{GPIO_Pin_5, GPIOC, ADC2, ADC_Channel_15 }, 
{GPIO_Pin_0, GPIOB, ADC2, ADC_Channel_8 }, 
{GPIO_Pin_1, GPIOB, ADC2, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOC, ADC2, ADC_Channel_14 } 
}; 
// ADC3 configurations 
const ADC_ConfigData ADC3_CONFIG[] = 
{ 
{GPIO_Pin_5, GPIOF, ADC3, ADC_Channel_15 }, 
{GPIO_Pin_10,GPIOF, ADC3, ADC_Channel_8 }, 
{GPIO_Pin_3, GPIOF, ADC3, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOF, ADC3, ADC_Channel_14 }, 
{GPIO_Pin_6, GPIOF, ADC3, ADC_Channel_4 }, 
{GPIO_Pin_7, GPIOF, ADC3, ADC_Channel_5 }, 
{GPIO_Pin_8, GPIOF, ADC3, ADC_Channel_6 }, 
{GPIO_Pin_9, GPIOF, ADC3, ADC_Channel_7 } 
}; 
static const INT ADC1_SENSORS = sizeof(ADC1_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC2_SENSORS = sizeof(ADC2_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC3_SENSORS = sizeof(ADC3_CONFIG)/sizeof(ADC_ConfigData); 
//------------------------------------------------------------------------------ 
// AdcInitialize 
//------------------------------------------------------------------------------ 
void AdcInitialize() 
{ 
DMA_Config(); 
ADC_Config(); 
TIM_Config(); 
} 
//------------------------------------------------------------------------------ 
// ADC_Config 
//------------------------------------------------------------------------------ 
static void ADC_Config() 
{ 
// Enable peripheral clocks 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE); 
// ADC common initialization 
ADC_CommonInitTypeDef ADC_CommonInitStructure; 
ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; 
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; 
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; 
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 
ADC_CommonInit(&ADC_CommonInitStructure); 
ADC_InitTypeDef ADC_InitStructure; 
ADC_StructInit(&ADC_InitStructure); 
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; 
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T8_TRGO; 
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
// Initialize all ADC's 
ADC_InitStructure.ADC_NbrOfConversion = ADC1_SENSORS; 
ADC_Init(ADC1, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC2_SENSORS; 
ADC_Init(ADC2, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC3_SENSORS; 
ADC_Init(ADC3, &ADC_InitStructure); 
// Configure the GPIO pin for ADC input 
GPIO_InitTypeDef GPIO_InitStructure; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
// Configure ADC1 GPIO's 
for (INT sensor=0; sensor<
ADC1_SENSORS
; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC1_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC1_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC1_CONFIG[sensor].ADCx, ADC1_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_144Cycles); 
} 
// Configure ADC2 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC2_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC2_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC2_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC2_CONFIG[sensor].ADCx, ADC2_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_144Cycles); 
} 
// Configure ADC3 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC3_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC3_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC3_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC3_CONFIG[sensor].ADCx, ADC3_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_144Cycles); 
} 
// Enable multi-mode DMA request after last transfer 
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); 
// Enable all ADC's 
ADC_Cmd(ADC1, ENABLE); 
ADC_Cmd(ADC2, ENABLE); 
ADC_Cmd(ADC3, ENABLE); 
// Start ADC1 (master) conversion. ADC2 and ADC3 will convert as slaves. 
ADC_SoftwareStartConv(ADC1); 
} 
//------------------------------------------------------------------------------ 
// DMA_Config 
//------------------------------------------------------------------------------ 
static void DMA_Config(void) 
{ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
DMA_InitTypeDef DMA_InitStructure; 
DMA_StructInit(&DMA_InitStructure); 
// ADC common data register, DMA2, Channel0, Stream0 configuration 
DMA_DeInit(DMA2_Stream0); 
DMA_InitStructure.DMA_Channel
= 
DMA_Channel_0
; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[0]; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR; 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
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_FIFOMode = DMA_FIFOMode_Enable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; 
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_InitStructure.DMA_BufferSize = ADC1_SENSORS + ADC2_SENSORS + ADC3_SENSORS; 
DMA_Init(DMA2_Stream0, &DMA_InitStructure); 
DMA_Cmd(DMA2_Stream0, ENABLE); 
} 
//------------------------------------------------------------------------------ 
// TIM_Config 
//------------------------------------------------------------------------------ 
static void TIM_Config() 
{ 
// TIM8 clock enable 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); 
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
// Time base configuration 
TIM_TimeBaseStructure.TIM_Period = TIM_PERIOD-1; 
TIM_TimeBaseStructure.TIM_Prescaler = TIM_PRESCALER; 
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; 
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; 
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); 
TIM_SelectOutputTrigger(TIM8, TIM_TRGOSource_Update); 
// TIM8 enable counter 
TIM_Cmd(TIM8, ENABLE); 
}

dlafreniere
Associate II
Posted on August 26, 2014 at 18:06

The code above still has the DMA memory loss of sync problem. However, it is only a problem when running in the debugger (I'm usingKeil uVision). Running full speed the ADC DMA transfers work perfectly.

For the debugger, I have a hack that gets it to work when executing in the debugger. See the code below. I thought I'd post the final solution as there seems to be no mention of this problem on any forums.

const INT ADC_BUFFER_SIZE = 8; 
static __IO uint16_t ADCConvertedValue[ADC_BUFFER_SIZE*3] __attribute__((at(0x20002000))); 
struct ADC_ConfigData 
{ 
uint16_t GPIO_Pin; 
GPIO_TypeDef* GPIO_Port; 
ADC_TypeDef* ADCx; 
uint8_t ADC_Channel; 
}; 
// ADC1 configurations 
const ADC_ConfigData ADC1_CONFIG[] = 
{ 
{GPIO_Pin_0, GPIOA, ADC1, ADC_Channel_0 }, 
{GPIO_Pin_1, GPIOA, ADC1, ADC_Channel_1 }, 
{GPIO_Pin_2, GPIOA, ADC1, ADC_Channel_2 }, 
{GPIO_Pin_3, GPIOA, ADC1, ADC_Channel_3 }, 
{GPIO_Pin_0, GPIOC, ADC1, ADC_Channel_10 }, 
{GPIO_Pin_1, GPIOC, ADC1, ADC_Channel_11 }, 
{GPIO_Pin_2, GPIOC, ADC1, ADC_Channel_12 }, 
{GPIO_Pin_3, GPIOC, ADC1, ADC_Channel_13 } 
}; 
// ADC2 configurations 
const ADC_ConfigData ADC2_CONFIG[] = 
{ 
{GPIO_Pin_6, GPIOA, ADC2, ADC_Channel_6 }, 
{GPIO_Pin_7, GPIOA, ADC2, ADC_Channel_7 }, 
{GPIO_Pin_5, GPIOA, ADC2, ADC_Channel_5 }, 
{GPIO_Pin_4, GPIOA, ADC2, ADC_Channel_4 }, 
{GPIO_Pin_5, GPIOC, ADC2, ADC_Channel_15 }, 
{GPIO_Pin_0, GPIOB, ADC2, ADC_Channel_8 }, 
{GPIO_Pin_1, GPIOB, ADC2, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOC, ADC2, ADC_Channel_14 } 
}; 
// ADC3 configurations 
const ADC_ConfigData ADC3_CONFIG[] = 
{ 
{GPIO_Pin_5, GPIOF, ADC3, ADC_Channel_15 }, 
{GPIO_Pin_10,GPIOF, ADC3, ADC_Channel_8 }, 
{GPIO_Pin_3, GPIOF, ADC3, ADC_Channel_9 }, 
{GPIO_Pin_4, GPIOF, ADC3, ADC_Channel_14 }, 
{GPIO_Pin_6, GPIOF, ADC3, ADC_Channel_4 }, 
{GPIO_Pin_7, GPIOF, ADC3, ADC_Channel_5 }, 
{GPIO_Pin_8, GPIOF, ADC3, ADC_Channel_6 }, 
{GPIO_Pin_9, GPIOF, ADC3, ADC_Channel_7 } 
}; 
static const INT ADC1_SENSORS = sizeof(ADC1_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC2_SENSORS = sizeof(ADC2_CONFIG)/sizeof(ADC_ConfigData); 
static const INT ADC3_SENSORS = sizeof(ADC3_CONFIG)/sizeof(ADC_ConfigData); 
//------------------------------------------------------------------------------ 
// AdcInitialize 
//------------------------------------------------------------------------------ 
void AdcInitialize() 
{ 
DMA_Config(); 
ADC_Config(); 
} 
//---------------------------------------------------------------------------- 
// ADC_IRQHandler 
//---------------------------------------------------------------------------- 
extern ''C'' void ADC_IRQHandler() 
{ 
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); 
DMA_Cmd(DMA2_Stream0, DISABLE); 
// When using the uVision debugger the DMA controller loses sync with 
// the destination memory location within the array: ADCConvertedValue[]. 
// Running full speed without the debugger this ISR hack is not required. 
// Setting the stream number of data registers at the ADC end of 
// conversion fixes a problem with the DMA controller losing sync. Initially 
// the data loaded into the array is correctly positioned, then over time it 
// loses sync and starts copying the data to the wrong array index causing bad 
// ADC readings. Using a lower sample time with ADC_RegularChannelConfig() 
// exacerbates the problem, so ADC_SampleTime_480Cycles is the most stable when 
// using this debugger fix. However, this code will re-sync the DMA so the 
// out of sync readings are transitory and not permanent. 
DMA2_Stream0->NDTR = ADC1_SENSORS + ADC2_SENSORS + ADC3_SENSORS; 
DMA_Cmd(DMA2_Stream0, ENABLE); 
} 
//------------------------------------------------------------------------------ 
// ADC_Config 
//------------------------------------------------------------------------------ 
static void ADC_Config() 
{ 
// Enable peripheral clocks 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE); 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOA, ENABLE); 
// ADC common initialization 
ADC_CommonInitTypeDef ADC_CommonInitStructure; 
ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult; 
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; 
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1; 
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 
ADC_CommonInit(&ADC_CommonInitStructure); 
ADC_InitTypeDef ADC_InitStructure; 
ADC_StructInit(&ADC_InitStructure); 
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; 
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
// Initialize all ADC's 
ADC_InitStructure.ADC_NbrOfConversion = ADC1_SENSORS; 
ADC_Init(ADC1, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC2_SENSORS; 
ADC_Init(ADC2, &ADC_InitStructure); 
ADC_InitStructure.ADC_NbrOfConversion = ADC3_SENSORS; 
ADC_Init(ADC3, &ADC_InitStructure); 
// Configure the GPIO pin for ADC input 
GPIO_InitTypeDef GPIO_InitStructure; 
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; 
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; 
// Configure ADC1 GPIO's 
for (INT sensor=0; sensor<
ADC1_SENSORS
; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC1_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC1_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC1_CONFIG[sensor].ADCx, ADC1_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_480Cycles); 
} 
// Configure ADC2 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC2_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC2_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC2_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC2_CONFIG[sensor].ADCx, ADC2_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_480Cycles); 
} 
// Configure ADC3 GPIO's 
for (INT 
sensor
=
0
; sensor<ADC3_SENSORS; sensor++) 
{ 
GPIO_InitStructure.GPIO_Pin
= 
ADC3_CONFIG
[sensor].GPIO_Pin; 
GPIO_Init(ADC3_CONFIG[sensor].GPIO_Port, &GPIO_InitStructure); 
ADC_RegularChannelConfig(ADC3_CONFIG[sensor].ADCx, ADC3_CONFIG[sensor].ADC_Channel, sensor+1, ADC_SampleTime_480Cycles); 
} 
// Enable multi-mode DMA request after last transfer 
ADC_MultiModeDMARequestAfterLastTransferCmd(ENABLE); 
// Enable the ADC IRQ 
NVIC_InitTypeDef nvicStructure; 
nvicStructure.NVIC_IRQChannel
= 
ADC_IRQn
; 
nvicStructure.NVIC_IRQChannelPreemptionPriority
= 
0
; 
nvicStructure.NVIC_IRQChannelSubPriority
= 
0
; 
nvicStructure.NVIC_IRQChannelCmd
= 
ENABLE
; 
NVIC_Init(&nvicStructure); 
// Enable ADC end of conversion interrupt 
// (only required for DMA ''sync'' errors, see comment above) 
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); 
// Enable all ADC's 
ADC_Cmd(ADC1, ENABLE); 
ADC_Cmd(ADC2, ENABLE); 
ADC_Cmd(ADC3, ENABLE); 
// Start ADC1 (master) conversion. ADC2 and ADC3 will convert as slaves. 
ADC_SoftwareStartConv(ADC1); 
} 
//------------------------------------------------------------------------------ 
// DMA_Config 
//------------------------------------------------------------------------------ 
static void DMA_Config(void) 
{ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
DMA_InitTypeDef DMA_InitStructure; 
DMA_StructInit(&DMA_InitStructure); 
// ADC common data register, DMA2, Channel0, Stream0 configuration 
DMA_DeInit(DMA2_Stream0); 
DMA_InitStructure.DMA_Channel
= 
DMA_Channel_0
; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue[0]; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR; 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
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_FIFOMode = DMA_FIFOMode_Enable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; 
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; 
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_InitStructure.DMA_BufferSize = ADC1_SENSORS + ADC2_SENSORS + ADC3_SENSORS; 
DMA_Init(DMA2_Stream0, &DMA_InitStructure); 
DMA_Cmd(DMA2_Stream0, ENABLE); 
}

Posted on August 26, 2014 at 18:48

Debuggers are invasive, whenever you try to observe things which are occurring in real time, and in the background (TIM, DMA, USART, Peripherals, etc), do so indirectly via diagnostic/telemetry information streaming from the system.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..