cancel
Showing results for 
Search instead for 
Did you mean: 

ADC example for several channels polling?

Pavel A.
Evangelist III

Can anybody point me to example of two or more ADC channels polling?

I'm trying to measure two channels of one ADC but it looks like it reads one channel twice

Initialization:

static void MX_ADC1_Init(void)
{
  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};
 
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;  // scan all channels?
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV; //<<<<
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
 
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
 
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_2;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

​Reading;

 
void ADC_read2meas(ADC_HandleTypeDef *hADC_NAC, uint16_t *p1, uint16_t *p2)
{
    HAL_StatusTypeDef st = HAL_ADC_Start(hADC_NAC);
    if (st != HAL_OK) {
        Error_Handler();
    }
 
    st = HAL_ADC_PollForConversion(hADC_NAC, 3 /*ms*/);
    if (st != HAL_OK) {
        Error_Handler();
    }
 
    //1
    uint32_t v = HAL_ADC_GetValue(hADC_NAC);
    if (v & 0xFFFFF000) {
        Error_Handler(); // does not fit in 12 bits
    }
    *p1 = v & 0xFFF;
 
    v = HAL_ADC_GetValue(hADC_NAC);
    if (v & 0xFFFFF000) {
        Error_Handler(); // does not fit in 12 bits
    }
    *p2 = v & 0xFFF;
}

 Need to call start twice or call HAL_ADC_PollForConversion twice?

14 REPLIES 14
KnarfB
Principal III

attached my L4 project, Drivers omitted for space reasons.

hth

KnarfB

Thank you @KnarfB​ Sampling time in your project is much longer than mine, this can explain why it works with polling.

Ohh, that really makes a difference. Have reduced that time to the minimum and it stopped working. Saw the overrun flag set in ADC ISR.

As a remedy, I enabled Discontinuous Conversion Mode (1), and moved HAL_ADC_Start into the inner loop. That works for me.

hth

KnarfB

Tushar_4
Associate II

In the Configuration part , don't we need two instances of sConfig for 2 different channel or only one instance will work no matter the number of channel?

 

@Tushar_4  The sConfig struct can be reused after HAL_ADC_ConfigChannel call. One instance will do. But this is not obvious in C code, you're right.