cancel
Showing results for 
Search instead for 
Did you mean: 

ADC example for several channels polling?

Pavel A.
Super User

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
Super User

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.