cancel
Showing results for 
Search instead for 
Did you mean: 

Read multiple ADC channels using DMA not working.

RBV
Associate II

Hi, I am trying to read multiple ADC channels using DMA method. I am not able to read values. I am not sure what wrong i am doing.

/* ADC1 init function */
void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_4;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
 
}

I tried with DMA and polling method as well but nothing seems working.

uint32_t value[2]; 
HAL_ADC_Start_DMA(&hadc1, value, 2); // start adc in DMA mode
 
//polling method
 HAL_ADC_Start(&hadc1);
 HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
 value[0]= HAL_ADC_GetValue(&hadc1);
 HAL_ADC_Stop(&hadc1);
 HAL_ADC_Start(&hadc1);
 HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
 value[1]= HAL_ADC_GetValue(&hadc1);
 HAL_ADC_Stop(&hadc1);

can anyone explain me what i am doing wrong and i am using DMAchannel 1for ADC1.

Thanks in advance.

10 REPLIES 10
MM..1
Chief II

Hi,

you need config DMA channel for ADC and too

sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;

is low time, your measured signal with this need be very low impedance source.

Try bigger cycle number.

and your value array must be global volatile...

TDK
Guru

> uint32_t value[2];

Your data is 12 bits, so it's storing uint16_t values, not uint32_t values. Otherwise the DMA method should work. If not, post more details about the values you're getting vs the values you expect.

The polling method isn't going to work as written since you're converting two channels. There are ways to get it to work, but DMA is going to be better.

If you feel a post has answered your question, please click "Accept as Solution".
RBV
Associate II

I tried with uint16_t but it is same i am getting 4095 as values all the time. Tried with diffrent sample cycles as well.

MM..1
Chief II

You dont write mcu type , but my ADC1 on F469 i connect to DMA2 Stream0

check datasheet about dma channels and peripherals pairs

RBV
Associate II

I am using STM32l4R5 chip. I checked with DMA channel and peripherals pairs. everything should be as it is. I am not getting anything otherthan 0 or 4095.

I am using FreeRTOS in my application does it have any imapact.

MM..1
Chief II

Maybe stupid , but check with voltmeter on pins how value is here?

AIM65
Associate III

I recently encounter a similar issue, ADC value was stuck to the value of the first sample while my dma was supposed to run.

This was due to a wrong peripheral initialization sequence and was fixed by having the right : clock - gpio - dma - then adc -...

my two cents...

in main, as generated by CubeMX

 /* Initialize all configured peripherals */

 MX_GPIO_Init();

 MX_DMA_Init();

 MX_ADC_Init();

 MX_I2C1_Init();

 MX_USART1_UART_Init();

 MX_CRC_Init();

 MX_TIM1_Init();

 MX_TIM6_Init();

 MX_I2C2_Init();

RBV
Associate II

I have checked the pins and i have some voltage on it from range 100mV to 2.4 V range. I have peripheral initialization sequence like : clock - gpio - dma - then adc etc...

Still i can see only 4095 values on all channels.

RBV
Associate II

I managed to get values other than 4095 after VREF+ pin to VREFBUF_OUT. I am able to read values with DMA but those values are not exactly same. For example i suppose to get 125 as RAW value then i am getting values from 150 to 400 range.

I tried internal Vrefint channel then i supposed to get 3.3V which is equal to 4095 arround but those values also fluctuating betwwen 2900 to 3980 ??

Any suggestions on what causing this kind of behaviour.