ADC example for several channels polling?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-14 7: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.
- Labels:
-
ADC
-
STM32Cube MCU Packages
-
STM32F3 Series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-15 6:51 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-14 7:51 AM
HAL_ADC_PollForConversion twice should do the trick.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-14 9: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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-15 2:11 AM
failes how, timeout?
Debugging seems to interfere by reading the data register which clears EOC.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-15 6: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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-15 6: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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-15 6:32 AM
Yeah, but that demonstrates the per-channel config-start-poll loop, not the configall-start-poll-poll-poll... scenario.
KnarfB
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2023-02-15 6: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.
