cancel
Showing results for 
Search instead for 
Did you mean: 

ADC and DMA Discovery Board F412 - cant get it to work

SSchu.4
Associate II

Hi all,

I have two pins where I want to read in the voltage with ADC: PA5 and PA7.

Reading in each at its own with polling works fine.

Now I want to read them in both and continously. I understand that the right way to

go is DMA, contonious mode and scan mode.

I have set up a DMA Request:

circular; halfword/halfword; increment at memory

ADC Setup:

static void MX_ADC1_Init(void)
{
 
  /* USER CODE BEGIN ADC1_Init 0 */
  /* USER CODE END ADC1_Init 0 */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC1_Init 1 */
  /* USER CODE END ADC1_Init 1 */
  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */
  /* USER CODE END ADC1_Init 2 */
 
}

Calling the function like that

// variable global
/* USER CODE BEGIN PV */
uint16_t adc_val[2];
/* USER CODE END PV */
 /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_DMA_Init();
  /* USER CODE BEGIN 2 */
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  HAL_Delay(1000);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

Callback implemented

/* USER CODE BEGIN 4 */
HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc){
	__NOP();
}
 
/* USER CODE END 4 */

Now the problem:

  • Callback gets only called once
  • Only one value is written to the DMA destination

Debug values are attached as screenshot.

Things I tried:

  • Reordering init-functions (apperantly there is a bug, but this changed nothing)
  • bigger buffers in DMA
  • Setting ADC ECO Flag to "end of all conversion"
  • DMA continuous requests to true

Nothing helped. I am kind of stuck. Any help appreciated.

3 REPLIES 3

Need to look at the DMA1 registers, confirm it's in circular mode, and not flagging errors

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

OVR bit is set in ADC_SR. An overrun will stop the ADC.

Slow down the conversions by increasing sampling time to max or by triggering off of a timer at a reasonable rate.

If you feel a post has answered your question, please click "Accept as Solution".
MM..1
Chief III

Your code have three errors

  1. DMA init order need before ADC
  2. DMA continuous request need enable
  3. ADC need call start i dont see this in your code.

And use one sample buffer with DMA isnt very effective