Skip to main content
Visitor II
January 4, 2023
Question

ADC implementation in LL can only read 3 values ?

  • January 4, 2023
  • 1 reply
  • 1137 views

Hello,

I am trying to implement an ADC init and read in interrupt mode.

I have a very basic setup where I read an analog entry from a potentiometer and print its raw converted value.

When I first implemented it with HAL, I had no issue and could read values that smoothly evolved from 0 et 65535 (16 Bits) as I tweaked the potentiometer.

Then I tried reimplementing my code using the Low Layer (LL) Library and as I read from the ADC, I can only read 3 values: 32767, 49151, 65535.

Here is a snippet of my code :

void ADC_Init(void)
{
	LL_ADC_InitTypeDef ADC_InitStruct = {0};
	LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
	LL_ADC_CommonInitTypeDef ADC_CommonInitStruct = {0};
 
	LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
 
	LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLL2P);
 
	// Peripheral clock enable
	LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_ADC12);
 
	//ADC1 GPIO Configuration
	LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOA);
	GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7;
	GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
	GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
	LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
	// ADC1 interrupt Init
	NVIC_SetPriority(ADC_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
	NVIC_EnableIRQ(ADC_IRQn);
	LL_ADC_EnableIT_EOC(ADC1);
 
	// Common config
	LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);
	ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_16B;
	ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
	LL_ADC_Init(ADC1, &ADC_InitStruct);
	ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
	ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
	ADC_REG_InitStruct.SequencerDiscont = DISABLE;
	ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
	ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
	LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
	ADC_CommonInitStruct.CommonClock = LL_ADC_CLOCK_ASYNC_DIV1;
	ADC_CommonInitStruct.Multimode = LL_ADC_MULTI_INDEPENDENT;
	LL_ADC_CommonInit(__LL_ADC_COMMON_INSTANCE(ADC1), &ADC_CommonInitStruct);
 
	LL_ADC_DisableDeepPowerDown(ADC1);
	LL_ADC_EnableInternalRegulator(ADC1);
	uint32_t wait_loop_index;
	wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
	while(wait_loop_index != 0)
	{
	 wait_loop_index--;
	}
 
	// Configure Regular Channel
	LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_3);
	LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_3, LL_ADC_SAMPLINGTIME_1CYCLE_5);
	LL_ADC_SetChannelSingleDiff(ADC1, LL_ADC_CHANNEL_3, LL_ADC_SINGLE_ENDED);
}
 
void ADC_IRQHandler(void)
{
 // Check if the end of conversion flag is set
 if (LL_ADC_IsActiveFlag_EOC(ADC1))
 {
	 LL_ADC_ClearFlag_EOC(ADC1);
	 AD_RES = LL_ADC_REG_ReadConversionData16(ADC1);
 }
 
}
 
int main(void)
{
 
 HAL_Init();
 
 SystemClock_Config();
 
 PeriphCommonClock_Config();
 
 MX_GPIO_Init();
 MX_USART3_UART_Init();
 MX_USB_OTG_HS_USB_Init();
 
 ADC_Init();
 LL_ADC_SetChannelPreSelection(ADC1, LL_ADC_CHANNEL_3);
 LL_ADC_Enable(ADC1);
 while (LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0);
 
 while (1)
 {
 LL_ADC_REG_StartConversion(ADC1); 
 char adc_string[32];
 sprintf(adc_string, "The value of ADC is : %d \n\r", AD_RES);
 HAL_UART_Transmit(&huart3, adc_string, sizeof(adc_string), 1000);
 }
 
}

Thank you for your help.

    This topic has been closed for replies.

    1 reply

    Super User
    January 4, 2023

    Which STM32?

    Place breakpoint into the ADC and read out the ADC registers' content there using debugger. Still only 3 values?

    Try comparing to working case.

    JW