2020-09-06 11:35 PM
Hi I am trying to sample an external signal with the ADC inside STM32F405RG MCU.
You can see the code below.
#include "main.h"
#include "SysClockConfiguration.h"
uint16_t ADC_Buffer0[1000];
uint16_t ADC_Buffer1[1000];
void Dummy_Delay(uint32_t x)
{
while(x)
{
x--;
}
}
void Initialization()
{
//---------Clock Configuration---------//
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //Enable ADC Clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; //Enable GPIOA Clocks
RCC->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 ADC
ADC->CCR |= (0b01<<ADC_CCR_ADCPRE_Pos);//ADC clock divided by 4
ADC1->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 ADC
Dummy_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 transfer
DMA2_Stream0->PAR = (uint32_t) &ADC1->DR; //Peripheral Address
DMA2_Stream0->M0AR = (uint32_t) ADC_Buffer0; //First Buffer
DMA2_Stream0->M1AR = (uint32_t) ADC_Buffer1; //Second Buffer
DMA2_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.4Msps
ADC 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
2020-09-07 08:30 AM
> 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?
Are you sure they're both full as opposed to just one full and the other is just starting to be filled? I would expect a few values to be in the second buffer by the time it hits your breakpoint.
> 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.
With nothing hooked up to the ADC, why do you care what it reports? The measurement of an infinite impedance source doesn't make a lot of sense.
2020-09-07 09:43 AM
> I would expect a few values to be in the second buffer by the time it hits your breakpoint.
What's the sampling rate? DMA won't stop... so few might quite well be all the second buffer.
JW