2023-01-04 03:11 AM
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.
2023-01-04 06:27 AM
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