cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L451VC: Problems with ADC.

Luis Ber
Associate II

Hello,

I'm working with a PCB based on STM32L451VC MCU and I have different problems with the ADC. I'm trying to measure an input channel using the HALs provided by the STM32CubeMX but I can't achieve it.

The main problem is that the bit ADRDY from ADC_ISR register never changes when the ADC is enabled.

I copy my code here:

The clock configuration:

void SystemClock_Config(void)
 
{
 
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
 
 
 /** Configure LSE Drive Capability
 
 */
 
 HAL_PWR_EnableBkUpAccess();
 
 __HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
 
 /** Initializes the CPU, AHB and APB busses clocks
 
 */
 
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_HSI;
 
 RCC_OscInitStruct.LSIState = RCC_LSI_ON;
 
 RCC_OscInitStruct.LSEState = RCC_LSE_ON;
 
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;	/*!< By default is configured to 16 MHz */
 
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 
 {
 
	 Error_Handler();
 
 }
 
 
 
//	JMAS comentat per proves => tornar a activar
 
//
 
// /* HSI16 oscillator selected as wakeup from stop clock and CSS backup clock. */
 
// HAL_RCCEx_WakeUpStopCLKConfig(RCC_STOP_WAKEUPCLOCK_HSI);
 
//
 
// /* HSI16 oscillator is enabled by hardware when exiting Stop mode with MSI as wakeup clock. */
 
// __HAL_RCC_HSIAUTOMATIC_START_ENABLE();
 
//
 
 
 
 /** Initializes the CPU, AHB and APB busses clocks
 
 */
 
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 
               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
 
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
 
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
 
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
 
 {
 
	 Error_Handler();
 
 }
 
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
 
               |RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_USART3
 
               |RCC_PERIPHCLK_LPTIM1|RCC_PERIPHCLK_LPTIM2
 
               |RCC_PERIPHCLK_I2C4|RCC_PERIPHCLK_ADC;
 
 PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_SYSCLK;
 
 PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
 
 PeriphClkInit.Usart3ClockSelection = RCC_USART2CLKSOURCE_SYSCLK;
 
 PeriphClkInit.I2c4ClockSelection = RCC_I2C4CLKSOURCE_SYSCLK;
 
 PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
 
 PeriphClkInit.Lptim2ClockSelection = RCC_LPTIM2CLKSOURCE_LSE;
 
 PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK;
 
 PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
 
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 
 {
 
	 Error_Handler();
 
 }
 
 /** Configure the main internal regulator output voltage
 
 */
 
 if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)
 
 {
 
	 Error_Handler();
 
 }
 
 
 
 /* Some changes have been added in order to disable the MSI clock */
 
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
 
 RCC_OscInitStruct.MSIState = RCC_MSI_OFF;	/*!< By default, MSI is enabled, then is necessary to disable */
 
 RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
 
 RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0;
 
 if ( HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK )
 
 {
 
	 Error_Handler();
 
 }
 
}

Function to request the ADC:

static mw_RetVal_t TestADC_RequestAdc(TestADC_adc_channel_t channel)
{
	ADC_InitTypeDef Init;
	ADC_ChannelConfTypeDef sConfig;
	Mw_Hal_Adc_Callbacks_t callbacks;
	HAL_StatusTypeDef result;
 
	memset(&callbacks, (int)NULL, sizeof(Mw_Hal_Adc_Callbacks_t));
 
	callbacks.ConvCpltCallback = TestADC_ADCConvCpltCallback;
	callbacks.ErrorCallback = TestADC_ADCErrorCallback;
	callbacks.LevelOutOfWindowCallback = TestADC_ADCLevelOutOfWindowCallback;
 
	result = HAL_ADC_Request(TESTADC_ADC_ID, &callbacks, osWaitForever);
 
	if ( result == HAL_OK )
	{
		Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
		Init.Resolution = ADC_RESOLUTION_12B;
		Init.DataAlign = ADC_DATAALIGN_RIGHT;
		Init.ScanConvMode = ADC_SCAN_DISABLE;
		Init.EOCSelection = ADC_EOC_SINGLE_CONV;
		Init.LowPowerAutoWait = DISABLE;
		Init.ContinuousConvMode = DISABLE;
		Init.NbrOfConversion = 1;
		Init.DiscontinuousConvMode = DISABLE;
		Init.ExternalTrigConv = ADC_SOFTWARE_START;
		Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
		Init.DMAContinuousRequests = DISABLE;
		Init.Overrun = ADC_OVR_DATA_PRESERVED;
		Init.OversamplingMode = DISABLE;
 
		result = HAL_ADC_Config(TESTADC_ADC_ID, &Init);
		if ( result == HAL_OK )
		{
			TestADC_Printf("TestADC: MW_HAL_ADC_Config OK");
		}
		else
		{
			TestADC_ErrorPrintf("TestADC: MW_HAL_ADC_Config error");
		}
	}
	else
	{
		TestADC_ErrorPrintf("TestADC: MW_HAL_ADC_Request error");
	}
 
	if ( result == HAL_OK )
	{
		/* Configure Channel */
		if ( channel == TESTADC_ADC_CHANNEL_VBAT )
		{
			sConfig.Channel = TESTADC_ADC_BAT_CHANNEL;
		}
		else if ( channel == TESTADC_ADC_CHANNEL_VREFINT)
		{
			sConfig.Channel = TESTADC_ADC_VINTREF_CHANNEL;
		}
 
		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;
 
		result = HAL_ADC_ConfigChannel(TESTADC_ADC_ID, &sConfig);
		if ( result == HAL_OK )
		{
			TestADC_Printf("TestADC: MW_HAL_ADC_ConfigChannel OK");
		}
		else
		{
			TestADC_ErrorPrintf("TestADC: MW_HAL_ADC_ConfigChannel error");
		}
	}
 
	return HalStatus2MwRet(result);
}

Function to read ADC value:

static mw_RetVal_t TestADC_AdcRead(uint32_t *pValue)
{
	HAL_StatusTypeDef status;
	mw_RetVal_t result;
	uint32_t signals;
 
	/* ------------ */
	RCC_OscInitTypeDef RCC_OscInitStruct;
	HAL_RCC_GetOscConfig(&RCC_OscInitStruct);
	if ( RCC_OscInitStruct.HSIState != RCC_HSI_ON )
	{
		RCC_OscInitStruct.HSIState = RCC_HSI_ON;
		RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
		RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
		HAL_StatusTypeDef ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
		if ( ret == HAL_OK )
		{
			TestADC_Printf("Fixed the HSI to clock the ADC");
		}
		else
		{
			TestADC_ErrorPrintf("Failed to fix the HSI to clock the ADC: %d", ret);
		}
	}
	/* ------------ */
 
	status = HAL_ADC_Start_IT(TESTADC_ADC_ID);
	if ( status == HAL_OK )
	{
		TestADC_Printf("TestADC: MW_HAL_ADC_Start_IT OK");
 
		signals = TestADC_SignalWait(TESTADC_SIGNAL_ADC, TESTADC_ADC_START_IT_TIMEOUT);
		status = HAL_ADC_Stop_IT(TESTADC_ADC_ID);
		if ( status == HAL_OK )
		{
			TestADC_Printf("TestADC: MW_HAL_ADC_Stop_IT OK");
		}
		else
		{
			TestADC_ErrorPrintf("TestADC: MW_HAL_ADC_Stop_IT status %d", status);
		}
 
		if ( IS_SIGNAL_FLAG(signals, TESTADC_SIGNAL_ADC) )
		{
			TestADC_Printf("TestADC: All OK, store result of ADC operation");
			result = testADC.adcOperationResult;
		}
		else
		{
			result = MW_TIMEOUT;
		}
	}
	else
	{
		TestADC_ErrorPrintf("TestADC: HAL_ADC_Start_IT status %d", status);
		result = HalStatus2MwRet(status);
	}
 
	*pValue = HAL_ADC_GetValue(TESTADC_ADC_ID);
 
	return result;
}

The function fails in HAL_ADC_Start_IT where the ADRDY bit is never '1'. Where is the possible problem? It seems that the interruption never happens? Could it be some hardware problem? Maybe the clocks? The voltage reference? I have checked and it's okay. Why issues can be happening?

I will appreciate any help. Thank you in advance.

0 REPLIES 0