cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L071 and ADC channel 5 and 6 rank

teobarbs
Associate

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

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

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)

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

1 REPLY 1
TDK
Guru

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)

If you feel a post has answered your question, please click "Accept as Solution".