2023-02-14 07:39 AM
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?
Solved! Go to Solution.
2023-02-15 06:51 AM
2023-02-14 07:51 AM
HAL_ADC_PollForConversion twice should do the trick.
2023-02-14 09:54 AM
> HAL_ADC_PollForConversion twice
The 2nd HAL_ADC_PollForConversion (added in line 20) fails.
Do I need to change EOCSelection? hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
2023-02-14 10:58 AM
ADC_EOC_SINGLE_CONV
here is more on that https://community.st.com/s/question/0D53W00000trJxJSAU/reading-multiple-adc-channel
[Edit]
my init (STM32L432KC):
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 6;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
my loop:
while (1)
{
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
status = HAL_ADC_Start(&hadc1);
if (status != HAL_OK) {
Error_Handler();
}
for( int i=0; i<sizeof(adc_raw)/sizeof(adc_raw[0]); ++i) {
status = HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
if (status != HAL_OK) {
Error_Handler();
}
adc_raw[i] = HAL_ADC_GetValue(&hadc1);
}
HAL_Delay(1);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
but HAL_ADC_Start_DMA works nicer?!
hth
KnarfB
2023-02-14 11:43 AM
> but HAL_ADC_Start_DMA works nicer?!
Maybe. But I thought polling with multiple channels was possible too.
Changed Init.EOCSelection = ADC_EOC_SINGLE_CONV.
Repeated HAL_ADC_PollForConversion always fails for me.
2023-02-15 02:11 AM
failes how, timeout?
Debugging seems to interfere by reading the data register which clears EOC.
2023-02-15 06:02 AM
There are many variations of ADC among the STM32 portfolio.
Some have injected channels, some don't
Some have differential inputs, some don't
Some have sigma delta ADC, some don't
For STM32C0, check the basic Analog.c source file. It has the basic to scan manually PA4/PA5 and Vref/Vtemp channels.
2023-02-15 06:26 AM
Yes, timeout on the 2nd HAL_ADC_PollForConversion.
I run thru all this at full speed.
It seems that the ADC data register in STM32F30 does not have a buffer or FIFO, so it must be read very quickly, preferably by DMA? Or increase sampling time?
2023-02-15 06:32 AM
Yeah, but that demonstrates the per-channel config-start-poll loop, not the configall-start-poll-poll-poll... scenario.
KnarfB
2023-02-15 06:39 AM
> For STM32C0, check the basic Analog.c source file
Thank you but there you poll all channels one by one, on the same position. For each conversion, call HAL_ADC_ConfigChannel then HAL_ADC_Start. This way, it works for me on STM32F3 too. The question is, how to do conversion of several channels at once without DMA?
I've tried to use injected conversions instead of normal, same behavior.