Skip to main content
HShal.1
Associate
October 16, 2020
Question

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

  • October 16, 2020
  • 3 replies
  • 1218 views

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,

This topic has been closed for replies.

3 replies

HShal.1
HShal.1Author
Associate
October 22, 2020

Any thoughts on why I might be getting this result?

Thanks,

TOlli
Senior
October 23, 2020

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.

HShal.1
HShal.1Author
Associate
October 23, 2020

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

HShal.1
HShal.1Author
Associate
October 23, 2020

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

HShal.1
HShal.1Author
Associate
October 30, 2020

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.