cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743 ADC2 converts correctly but ADC1 doesn't with exactly the same settings

HShal.1
Associate II

Hi,

I have ADC1 and ADC2 configured on one of the pins (PA3 - ADC1_INP15, ADC2_INP15) of my STM32H743VI. I am using the standard cubeMX initialization.

static void MX_ADC1_Init(void)
{
 
  /* USER CODE BEGIN ADC1_Init 0 */
 
  /* USER CODE END ADC1_Init 0 */
 
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC1_Init 1 */
 
  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_15;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */
 
  /* USER CODE END ADC1_Init 2 */
 
}

and

static void MX_ADC2_Init(void)
{
 
  /* USER CODE BEGIN ADC2_Init 0 */
 
  /* USER CODE END ADC2_Init 0 */
 
  ADC_ChannelConfTypeDef sConfig = {0};
 
  /* USER CODE BEGIN ADC2_Init 1 */
 
  /* USER CODE END ADC2_Init 1 */
  /** Common config
  */
  hadc2.Instance = ADC2;
  hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV16;
  hadc2.Init.Resolution = ADC_RESOLUTION_16B;
  hadc2.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc2.Init.LowPowerAutoWait = DISABLE;
  hadc2.Init.ContinuousConvMode = DISABLE;
  hadc2.Init.NbrOfConversion = 1;
  hadc2.Init.DiscontinuousConvMode = DISABLE;
  hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc2.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_15;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC2_Init 2 */
 
  /* USER CODE END ADC2_Init 2 */
 
}

Then in my main loop, I have a small code snippet to fill a buffer with 10 values read consecutively:

               for(int n = 0; n<10; n++){
			HAL_ADC_Start(&hadc1);
			HAL_ADC_PollForConversion(&hadc1, 10000);
			adata[n] = HAL_ADC_GetValue(&hadc1);
		}

In debugger, when I use hadc1, adata contains 10x values of 32768.

When I use hadc2, adata contains 10x values of 1020 +/- 5lsb (expected).

I have tried this with only initializing one of the ADCs at a time i.e. ADC1 without ADC2 and ADC2 without ADC1 and I get the same results.

Is there something specific I am missing?

Thanks,

5 REPLIES 5
HShal.1
Associate II

Any thoughts on why I might be getting this result?

Thanks,

I don't see a function for calibration, did you use one?

HAL_ADCEx_Calibration_Start()? In the adc_ex -files.

Might not make a difference, but then again, it might.

I tried adding HAL_ADCEx_Calibration_Start after channel config and it still only produces 32768 :( thank you for the input though!

HShal.1
Associate II

UPDATE: If I enable continous conversion mode, it seems to convert successfully! Any additional clues?

HShal.1
Associate II

UPDATE: Initialising the ADC without the HAL functions solves the problem and I can convert correctly. My initialisation function is:

static void ID_ADC1Init(void){
	//Do clock
	__HAL_RCC_ADC12_CLK_ENABLE();
	__HAL_RCC_ADC12_FORCE_RESET();
	HAL_Delay(1);
	__HAL_RCC_ADC12_RELEASE_RESET();
 
	//Slowest clock
	ADC12_COMMON->CCR |= ADC_CCR_PRESC_0 | ADC_CCR_PRESC_1 | ADC_CCR_PRESC_3;
 
	//Ensure idle
	while((ADC1->CR & ADC_CR_ADDIS));
 
	//Wake from deep power down
	ADC1->CR &= ~ ADC_CR_DEEPPWD;
 
	//Enable Vreg
	ADC1->CR |= ADC_CR_ADVREGEN;
	//Startup time for LDO is 10us, wait at least this
	HAL_Delay(1);
 
	//Do calibration
	ADC1->CR |= ADC_CR_ADCALLIN;
	ADC1->CR |= ADC_CR_ADCAL;
	//Wait for calibration
	while(ADC1->CR & ADC_CR_ADCAL);
 
	//Disable overrun
	ADC1->CFGR |= ADC_CFGR_OVRMOD;
 
	//Set channels
	ADC1->PCSEL |= ADC_PCSEL_PCSEL_3;
	ADC1->SQR1 |= (3)<<ADC_SQR1_SQ1_Pos;
	ADC1->SMPR1 |= ADC_SMPR1_SMP3;
 
	//Enable ADC
	ADC1->CR |= ADC_CR_ADEN;
	while(!(ADC1->ISR & ADC_ISR_ADRDY));
 
}

It seems to be a problem with HAL.