2020-10-16 02:55 AM
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,
2020-10-22 08:21 AM
Any thoughts on why I might be getting this result?
Thanks,
2020-10-22 10:03 PM
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.
2020-10-23 09:19 AM
I tried adding HAL_ADCEx_Calibration_Start after channel config and it still only produces 32768 :( thank you for the input though!
2020-10-23 09:28 AM
UPDATE: If I enable continous conversion mode, it seems to convert successfully! Any additional clues?
2020-10-30 08:01 AM
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.