Skip to main content
Explorer
August 7, 2024
Solved

STM32L071 and ADC channel 5 and 6 rank

  • August 7, 2024
  • 1 reply
  • 813 views

Hello, I have configure ADC to use channel 5 and 6 but I am not understanding what I am doing wrong to get readings from the two channels. 

Here is my code:

void adcConvertionFinish(ADC_HandleTypeDef* handle);

static ADC_HandleTypeDef g_adc;
static const uint32_t g_shutter_pin = GPIO_PIN_5;
static const uint32_t g_window_pin = GPIO_PIN_6;
static adcPowerMeterConvertionFinishHandler g_adc_conversion_finish_handler = NULL;
static void* g_adc_convertion_finish_obj = NULL;

bool adcPowerMeterInit()
{
 __HAL_RCC_ADC1_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();

 GPIO_InitTypeDef init_struct = {0};
 init_struct.Pin = g_shutter_pin | g_window_pin;
 init_struct.Mode = GPIO_MODE_ANALOG;
 init_struct.Pull = GPIO_NOPULL;
 HAL_GPIO_Init(GPIOA, &init_struct);

 ADC_ChannelConfTypeDef config = {0};
 g_adc.Instance = ADC1;
 g_adc.Init.OversamplingMode = DISABLE;
 g_adc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
 g_adc.Init.Resolution = ADC_RESOLUTION_12B;
 g_adc.Init.SamplingTime = ADC_SAMPLETIME_39CYCLES_5;
 g_adc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
 g_adc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
 g_adc.Init.ContinuousConvMode = ENABLE;
 g_adc.Init.DiscontinuousConvMode = DISABLE;
 g_adc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
 // g_adc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T6_TRGO;
 g_adc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
 g_adc.Init.DMAContinuousRequests = DISABLE;
 g_adc.Init.EOCSelection = ADC_EOC_SEQ_CONV;
 g_adc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
 g_adc.Init.LowPowerAutoWait = DISABLE;
 g_adc.Init.LowPowerFrequencyMode = DISABLE;
 g_adc.Init.LowPowerAutoPowerOff = DISABLE;

 if(HAL_ADC_Init(&g_adc) != HAL_OK)
 return false;

 config.Channel = ADC_CHANNEL_5;
 config.Rank = ADC_RANK_CHANNEL_NUMBER;

 if(HAL_ADC_ConfigChannel(&g_adc, &config) != HAL_OK)
 return false;

 config.Channel = ADC_CHANNEL_6;
 if(HAL_ADC_ConfigChannel(&g_adc, &config) != HAL_OK)
 return false;

 if(HAL_ADC_RegisterCallback(&g_adc, HAL_ADC_CONVERSION_COMPLETE_CB_ID, adcConvertionFinish)
 != HAL_OK)
 return false;

 HAL_NVIC_SetPriority(ADC1_COMP_IRQn, g_adc_powermonitor_preempt, g_adc_powermonitor_sub);
 HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
 return true;
}
void adcPOwerMeterDeInit()
{
 __HAL_RCC_ADC1_CLK_DISABLE();
 HAL_GPIO_DeInit(GPIOA, g_shutter_pin | g_window_pin);
 HAL_NVIC_DisableIRQ(ADC1_COMP_IRQn);
}

void adcConvertionFinish(ADC_HandleTypeDef* handle)
{
 uint32_t val2 = 0, val1 = 0;

 val1 = HAL_ADC_GetValue(&g_adc);
 val2 = HAL_ADC_GetValue(&g_adc);

 if(g_adc_conversion_finish_handler && handle->Instance == g_adc.Instance)
 g_adc_conversion_finish_handler(g_adc_convertion_finish_obj, val1, val2);
}

void adcPowerMeterSetConvertionFinishHandler(adcPowerMeterConvertionFinishHandler handler, void* obj)
{
 g_adc_conversion_finish_handler = handler;
 g_adc_convertion_finish_obj = obj;
}

void adcPowerMeterStart()
{
 HAL_ADC_Start_IT(&g_adc);
}

void adcPowerMeterStop()
{
 HAL_ADC_Stop_IT(&g_adc);
}

// HAL Functions
void ADC1_COMP_IRQHandler(void)
{
 HAL_ADC_IRQHandler(&g_adc);
}

At adcConvertionFinish function, I am getting allways the value of the channel 5 (on both variables val1 val2). I am following a example of using rank's to get values from two channels that I found on web, but it is not working for me.

My goal is to start a convertion (get convertion for channel 5 and channel 6), then when it is finish, get the values. 

What I am doing wrong?

 

Thank you for you help in advance

    This topic has been closed for replies.
    Best answer by TDK

    Use DMA to convert more than one channel at a time.

     

    > val1 = HAL_ADC_GetValue(&g_adc);
    > val2 = HAL_ADC_GetValue(&g_adc);

    There is no FIFO in the ADC. Such a scheme cannot work. You must read out a channel before the next one is converted or you will get an overrun.

     

    Here is an example of using ADC on multiple channels:

    STM32CubeL0/Projects/NUCLEO-L053R8/Examples/ADC/ADC_Sequencer/Src/main.c at a91b71702355c483e72868edd3fb620e4278e017 · STMicroelectronics/STM32CubeL0 (github.com)

    1 reply

    TDKAnswer
    Super User
    August 7, 2024

    Use DMA to convert more than one channel at a time.

     

    > val1 = HAL_ADC_GetValue(&g_adc);
    > val2 = HAL_ADC_GetValue(&g_adc);

    There is no FIFO in the ADC. Such a scheme cannot work. You must read out a channel before the next one is converted or you will get an overrun.

     

    Here is an example of using ADC on multiple channels:

    STM32CubeL0/Projects/NUCLEO-L053R8/Examples/ADC/ADC_Sequencer/Src/main.c at a91b71702355c483e72868edd3fb620e4278e017 · STMicroelectronics/STM32CubeL0 (github.com)