2014-01-09 06:19 AM
How is the DMA supposed to work with Triple-ADC Regulare mode? The documentation shows an ADC stream for each ADC, but it also seems to indicate that it will be working with a single DMA stream for this process.
#adc #stm32f4 #dma2014-01-09 06:35 AM
It uses a register CDR (Common Data Register) outside of the 3 ADC which sequences the data from a single register, at a single address, using a single DMA stream
2014-01-09 07:21 AM
So if I choose any of the ADC DMA streams, and point it to the address of the CDR, it will receive a transfer request at the EOC? Assuming that the rest of the ADC is configured correctly.
2014-01-09 08:01 AM
I'm not sure it works that way, with the Dual/Triple mode one ADC (1) acts as the master, and the other(s) operate in lock step. And you chose a CDR address, and DMA Access Mode to reflect the way the data gets accessed. The data goes to a single buffer, and multiple sequential DMA requests are sent to clear all the pending samples.
You could, I would imagine, also use all three ADC, with their own DMA stream, to their own memory buffer, and tied them together with a common trigger source. I posted a triple ADC example2014-01-09 08:54 AM
I see. I want to be using the DMA stream from ADC1 because it is the master.
The problem that I see with trying to get 3 ADCs working with 3 DMA requests (not in multi-adc mode) is that you will need to trigger all three such that you can guarantee no conflicts. If 3 DMA triggers went out at the same time, could you gaurantee that they would always grab the same data? In that case, would they not all be grabbing from the same ADC-DR?2014-01-09 09:17 AM
You'd trigger the start of conversion using a common TIM trigger, the EOC and the order in which the DMA service should be pretty much irrelevant as each ADC has it's own ADCx->DR and each DMA unit is servicing a different memory buffer.
Pretty sure I've posted an example with multiple ADC firing from the same TIM. The Dual/Triple are different, use a common register (with multiple states), and a single DMA2014-01-09 12:23 PM
Talking specifically about the STM32F407xx series, I am now rather confused as to how the ADCx-DR setup works.
If you look at the , in Section 13.13.18, It indicates that there is:1 ADC->DR4 ADC->JDRx1 ADC->CDRWhich, to me, indicates that you can only actually pull from a single ADC->DR if you are using multiple ADCs that are converting at the same time.On the other hand, if you look at the , sm32f4xx_adc.c, and stm32f4xx.h, they seem to indicate that there are 3 different data registers.Which is it?2014-01-09 01:58 PM
There is ONE ADCx->DR for each of the THREE ADC. Your may use these INDEPENDENTLY.
-- OR -- There is a COMMON area when you COMBINE TWO or THREE ADC in a DUAL and TRIPLE mode respectively.2014-01-09 02:07 PM
Ahh, Okay. This actually makes sense. I couldn't understand why they would design a system without independent data registers.
2015-08-17 05:42 AM
Hi dear friend ... it's not true
every ADC has it's own independent data registerand you can have different DMA stream and three different buffer with various buffer sizes that can trig by one trigger sourceas an example : you can sent timer 2 in 1 MHz and as a trigger source like this:TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
/* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = (84000000 / 1000000) - 1; // 200 KHz, from 84 MHz TIM2CLK (ie APB1 = HCLK/4, TIM2CLK = HCLK/2)
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
/* TIM2 TRGO selection */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T2_TRGO
/* TIM2 enable counter */
TIM_Cmd(TIM2, ENABLE);
and then config your 3 ADCs with DMA like this:
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* ADC Common Init */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_15Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 1 Channel
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // Conversions Triggered
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
//ADC1
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_15Cycles); // PC1
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
for(int i=55000;i--;);
//ADC2*//*
ADC_Init(ADC2, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC2, ADC_Channel_12, 1, ADC_SampleTime_15Cycles); // PC2
ADC_DMARequestAfterLastTransferCmd(ADC2, ENABLE);
ADC_DMACmd(ADC2, ENABLE);
ADC_Cmd(ADC2, ENABLE);
//ADC3
for(int i=55000;i--;);
ADC_Init(ADC3, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 1, ADC_SampleTime_15Cycles); // PC3
ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);
ADC_DMACmd(ADC3, ENABLE);
ADC_Cmd(ADC3, ENABLE);don't forget you only can set corresponding stream for each ADC.
DMA2->STREAM0->CH0 for ADC1 DMA2->STREAM2->CH1 for ADC2 DMA2->STREAM1->CH2 for ADC3.............. its completely tested and OK ... now i captured 3*2 Milion sample per second from 3 different channels with 10kB /channel buffer----Good luckEhsan Dan