2016-09-21 09:11 PM
Hi all,
I have a most frustrating problem. I am using the ADC1 to sample 5 ADC inputs in sequence, I am also using the DMA2 Sequence 0 to transfer the results to a memory location. I am using a timer to ensure this occurs at precise times as the samples are then �FFT�ed� to get the frequency domain components. This works perfectly the first time through. The ADC results are as expected and the results are in the right location. The second time this executes the results are not appearing in the memory locations. In fact the ADC1 reports that the conversion has resulted in an overrun, so clearly the DMA is not servicing the ADC. The question is why. I am sure I have some setting wrong or in the incorrect sequence. The CPU is a STM32F427This is the initialization code for the ADC
// set up adc
/* *ADC1 GPIO Configuration
PC0 ------> Radar 1 ADC1_IN10
PC1 ------> Radar 2 ADC1_IN11
PA3 ------> Vbatt ADC1_IN03
PA4 ------> LDR ADC1_IN04
PA5 ------> Thermistor ADC1_IN05
*/
// adc clock enable
RCC->APB2ENR|=RCC_APB2ENR_ADC1EN;
// setup CR1
ADC1->CR1&=~(ADC_CR1_RES_1|ADC_CR1_RES_0); // set to 12 bit
ADC1->CR1&=~ADC_CR1_DISCEN; // enable disconinuios mode on regular channels
ADC1->CR1&=~ADC_CR1_EOCIE; // disable end of conversion
ADC1->CR1|=ADC_CR1_DISCNUM_2; // set for five channels
ADC1->CR1&=~ADC_CR1_JDISCEN; // disable injected mode
ADC1->CR1|=ADC_CR1_SCAN; // enable scan mode
// setup CR2
ADC1->CR2|=ADC_CR2_ADON;
ADC1->CR2&=~ADC_CR2_ALIGN;
// set up CCR register
// set clock prescalaer to 2
ADC->CCR&=~ADC_CCR_ADCPRE;
ADC->CCR&=~ADC_CCR_ADCPRE_0;
ADC->CCR&=~ADC_CCR_ADCPRE_1;
/**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
we are doing 5 conversion with sample time of 480 cycles
channel 10 11 3 4 5
*/
ADC1->SQR1&=~ADC_SQR1_L; // clear L[3:0] for 5 conversions
ADC1->SQR1|=ADC_SQR1_L_2;
// set up 1st conversion on channel 10 Radar 1
ADC1->SQR3|=0x000a;
ADC1->SMPR2|=0b0111; // 480 cycles
// set up 2nd conversion on channel 11 Radar 2
ADC1->SQR3|=(0x000b)<<5;
ADC1->SMPR2|=(0b0111<<3); // 480 cycles
// set up 3rd
ADC1->SQR3|=(0x0003)<<10;
ADC1->SMPR2|=0b0111<<6; // 480 cycles
// set up 4th
ADC1->SQR3|=(0x0004)<<15;
ADC1->SMPR2|=0b0111<<9; // 480 cycles
// set up 5th
ADC1->SQR3|=(0x0005)<<20;
ADC1->SMPR2|=0b0111<<12; // 480 cycles
This is the initialization code for the DMA
RCC->AHB1ENR|=RCC_AHB1ENR_DMA2EN;
DMA2_Stream0 ->CR&=~DMA_SxCR_CHSEL; // clear all channels by default set to channel 0
DMA2_Stream0 ->CR&=~DMA_SxCR_CT; // set target memory to memory 0
DMA2_Stream0 ->CR&=~DMA_SxCR_MSIZE_1;
DMA2_Stream0 ->CR|=DMA_SxCR_MSIZE_0; // set to 16 bits
DMA2_Stream0 ->CR&=~DMA_SxCR_PSIZE_1;
DMA2_Stream0 ->CR|=DMA_SxCR_PSIZE_0; // set to 16 bits
DMA2_Stream0 ->CR|=DMA_SxCR_MINC; // increment memory location
DMA2_Stream0 ->CR&=~DMA_SxCR_PINC;
DMA2_Stream0 ->CR|=DMA_SxCR_PL_1;
DMA2_Stream0 ->CR&=~DMA_SxCR_DIR_0; // set direction peripheral to memory
DMA2_Stream0 ->CR&=~DMA_SxCR_DIR_1;
DMA2_Stream0 ->CR|=DMA_SxCR_PFCTRL; // peripheral is the flow control
The timer interrupts on a regular basis and this is the code to start another conversion.
DMA2_Stream0 ->CR&=~DMA_SxCR_EN;
while((DMA2_Stream0->CR&DMA_SxCR_EN)!=0); // wait for DMA sequence to complete
ADC1->CR2&=~ADC_CR2_DMA; // disable ADC DMA interface
DMA2_Stream0 ->PAR=(int32_t)&ADC1->DR; // set source
DMA2_Stream0 ->M0AR=(int32_t)&adc_values[0]; // set destination
DMA2_Stream0 ->NDTR=5; // set number of transfers
DMA2->LISR&=~(DMA_LISR_TEIF0|DMA_LISR_TCIF0); // clear flags
DMA2_Stream0 ->CR|=DMA_SxCR_EN; // enable DMA sequence
ADC1->CR2|=ADC_CR2_DMA; // enable ADC DMA interface
ADC1->CR2|=ADC_CR2_SWSTART; // start next conversion
// clear interrupt
TIM2->SR &=~TIM_SR_UIF;
Any help appreciated.
Thanks
Mark
#adc1-dma22017-11-26 07:49 PM
May be you have set the DMA mode to Normal mode ,so it only work one time. You need to reconfiguration berfore next data collection.