STM32F405RG ADC problem - Page 1
Forum section: electronics / general

author: syntax333
author_rank: Regular Contributor
timestamp: September 07, 2020, 07:41:04 am
content: Hi I am trying to sample an external signal with the ADC inside STM32F405RG MCU.You can see the code below.Code:#include "main.h"#include "SysClockConfiguration.h"uint16_t ADC_Buffer0;uint16_t ADC_Buffer1;void Dummy_Delay(uint32_t x){while(x){x--;}}void Initialization(){//---------Clock Configuration---------//RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable ADC ClockRCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //Enable GPIOA ClocksRCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; //Enable DMA2 Clock//---------GPIO Configuration---------//GPIOA->MODER |= GPIO_MODER_MODE2; //Set PA2 as Analog//---------ADC Configuration---------//ADC1->CR2 &= ~(ADC_CR2_ADON); //Disable ADCADC->CCR |= (0b01<<ADC_CCR_ADCPRE_Pos);//ADC clock divided by 4ADC1->CR2 |= ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_DDS; //Enable DMA and Set ADC mode as Continuous, DMA requests are issued as long as data are converted and DMA=1/**Fadcclk* Sampling Time = -----------------------------------------------*Sampling Cycle(3 Default) + 12 Cycle Conversion*/ADC1->SQR3 |= (2<<ADC_SQR3_SQ1_Pos);ADC1->CR2 |= ADC_CR2_ADON; //Enable ADCDummy_Delay(505); //Wait until tstab//---------DMA Configuration---------//DMA2_Stream0->CR &= ~(DMA_SxCR_EN); //Disable DMA2_Stream0//Double Buffer VHigh Prio.16bit data transfer Mem. 16bit data transfer Periph. Increment Mem. Circular Mode Transfer Complete Interrupt enable.DMA2_Stream0->CR |= DMA_SxCR_DBM | DMA_SxCR_PL | (0b01<<DMA_SxCR_MSIZE_Pos) | (0b01<<DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC | DMA_SxCR_CIRC | DMA_SxCR_TCIE;DMA2_Stream0->NDTR = 1000; //Number of Data to transferDMA2_Stream0->PAR = (uint32_t) &ADC1->DR; //Peripheral AddressDMA2_Stream0->M0AR = (uint32_t) ADC_Buffer0; //First BufferDMA2_Stream0->M1AR = (uint32_t) ADC_Buffer1; //Second BufferDMA2_Stream0->CR |= DMA_SxCR_EN; //Enable DMA2_Stream0//---------NVIC Configuration---------//NVIC_EnableIRQ(DMA2_Stream0_IRQn); //Enable DMA2 Stream0 Interrupt}int main(void){HAL_Init();SystemClock_Config();Initialization();ADC1->CR2 |= ADC_CR2_SWSTART; //Start Conversion of regular channels.while (1){}}void DMA2_Stream0_IRQHandler(){if(DMA2->LISR & DMA_LISR_TCIF0) //Check Transfer Complete Interrupt Flag{DMA2->LIFCR |= DMA_LIFCR_CTCIF0; //Clear Transfer complete Interrupt flag}}ADCCLK = Peripheral clock 84MHz/4 = 21MHz. Sampling rate = 21MHz/15 =1.4MspsADC is set 12bit configuration.DMA is in Double buffer Mode.I have two problems.I. When I debug the code and set breakpoint inside the DMA interrupt, both buffers are full with data, despite DMA triggering for the first time. Shouldn't only one buffer be full?II. ADC reads the signal wrong. When I don't give any input signal ADC reads approximately 980. When I set the ADC in scan mode with two channels ADC reads 450 for one and 65 for the other channel(Again with no input). Something seems to be wrong.Has anyone encountered this type of problem?Thank you

author: MosherIV
author_rank: Super Contributor
timestamp: September 07, 2020, 07:56:16 am
content: HiIt is difficult to debug isr with break points and stepping through.Humans just do not operate at the speed of micros.It is likely that the 2nd buffers filled up in the time that it took to go look.

author: syntax333
author_rank: Regular Contributor
timestamp: September 07, 2020, 08:58:11 am
content: Quote from: MosherIV on September 07, 2020, 07:56:16 amYes it seems like so. I set and reset the GPIO pin in ISR and observed right timing in Oscilloscope.What about ADC configuration? Why am I reading wrong data?

author: MosherIV
author_rank: Super Contributor
timestamp: September 07, 2020, 11:44:10 am
content: Leaving inputs floating is not going to give you anything sensible.They are high impeadance whuch means when left floating, they will just pick up random noise.Put some know voltage and see if the ADC value gives somethung sensible.Does short to 0V give 0 adc count? Etc.

author: Alti
author_rank: Frequent Contributor
timestamp: September 07, 2020, 04:20:07 pm
content: If you want to debug this ISR then you have to halt ADC while stepping through breakpoints, otherwise it triggers DMA requests continuously. This halt can be made by triggering each single conversion of ADC by a timer event and setting the timer to stop when in debug mode. Otherwise each time you read DMA buffer you get different values.If you have problems with connecting ADC to an IO pin then STM32 micros have several ADC channels wired inside of the chip (do not require any IOs). I am sure your chip has some channels tied to Temp sensor, Aref, maybe even Vbat or Vcc/2.

author: syntax333
author_rank: Regular Contributor
timestamp: September 10, 2020, 12:49:35 pm
content: After connecting pins to sources voltage reads are close to real values but wrong.For example I have a voltage divider circuit which has 100k and 10k resistors. I apply 18.5V to voltage divider and get 1.7V at ADC pin (I check this with oscilloscope). ADC must read 1.7/3(Vref)*4096 = 2321 but it reads 2595 which corresponds to higher voltages.When I apply 5V to voltage divider I get 0.454V at ADC pin. ADC reads 631 which corresponds to 631/4096*3 = 0.462 also corresponds 5.08V at voltage divider input. Value is close enough for low voltage levels but as the voltage level increases the error is increasing also.I am sampling 8 channels in scan mode at 800ksps (100ksps for each channel).Is this error due to ADC?

author: iMo
author_rank: Super Contributor
timestamp: September 10, 2020, 01:56:11 pm
content: QuoteWhere your Vref=3V comes from?

author: syntax333
author_rank: Regular Contributor
timestamp: September 11, 2020, 04:55:29 am
content: Vdd is connected to Vdda and Vdd is connected to 3V

author: mikerj
author_rank: Super Contributor
timestamp: September 11, 2020, 10:17:09 am
content: A 3 cycle acquisition time may not be long enough, especially if you divider is not bypassed. Trying increasing this.

author: syntax333
author_rank: Regular Contributor
timestamp: September 11, 2020, 01:18:07 pm
content: I changed the supply 3.3V and measured it. Vcc was 3.25 instead of 3.3V. This small error with Voltage divider amplified my overall error.After calculating the voltages with Vref 3.25V everything seems to be correct.