cancel
Showing results for 
Search instead for 
Did you mean: 

The sequence from the ADC_SQR3 register does not work.

MMust.5
Senior II
My goal now is to understand how ADC works.
I know that with the HAL_ADC_Start_DMA function, I can easily read data from multiple pins.
Now I want to set up data transfer from pins in semi-automatic mode, without the HAL_ADC_Start_DMA function.
I know how to do it when sConfig.Rank == 1
 
My task is to transfer data from several pins when sConfig.Rank is greater than 1.
In Cube MX this parameter is called: Number of Conversion.
-----------------------------------------------
Scan Conversion Mode enabled.
In the while loop, I set up the sequence in the ADC_SQR3 register:
 
Channel Five, First Rank
sConfig.Channel = ADC_CHANNEL_5;
sConfig.Rank = 1;
 
Channel six, second rank
sConfig.Channel = ADC_CHANNEL_6;
sConfig.Rank = 2;
 
(The code is a little more complicated of course, I write the most important thing so as not to complicate.)
A sequence appears in the ADC_SQR3 register.
But when I then write HAL_ADC_PollForConversion(&hadc1, 1000);
That conversion occurs only for the first Rank, in this case for the fifth channel. 
The second Rank is not converted. Why?
png.png
 
Full code:

 

static void MX_ADC1_Init(void)
{
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 3;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
}

 void ADC_Select_CH0 (void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

  void ADC_Select_CH1 (void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = 2;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
uint16_t a[10]={0};
while (1)
{
  ADC_Select_CH5();
  ADC_Select_CH6();
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 1000);
  a[0] = HAL_ADC_GetValue(&hadc1);
          HAL_ADC_Stop(&hadc1);
}

 

 
 
1 ACCEPTED SOLUTION

Accepted Solutions
MMust.5
Senior II
I don't understand how I did it, but I did it.
Previously, I ran with the same settings, but it did not work.
I think it's an unstable system.
I think that in order for everything to work stably, it is necessary to rewrite the HAL_ADC_PollForConversion function.

 

#include "main.h"
#include <stdio.h>
uint16_t a[5]={0};
while (1)
  {
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
a[0]=HAL_ADC_GetValue(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 1000);
a[1]=HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);

printf("%d\n", a[0]);
printf("%d\n", a[1]);
  }


static void MX_ADC1_Init(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 2;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_7;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

  sConfig.Channel = ADC_CHANNEL_8;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

}

 

This code works for me and takes data from two Ranks.
But I think it is necessary to rewrite the HAL_ADC_PollForConversion function.
In the HAL_ADC_PollForConversion function, the ADC_SR_EOC bit is enabled after the conversion is completed.
If such settings are set hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; then all Ranks are converted in order, and after each Rank is converted, the ADC_SR_EOC bit is set.
And after the end of the conversion, you must immediately start the next conversion.
In my code above, I probably somehow accidentally manage to make it in these gaps, but I don't think this code is reliable.
But it works.
png.png

 

View solution in original post

15 REPLIES 15
AScha.3
Chief II

maybe because you set end of conversion -> single conversion

AScha3_0-1690122394934.png

try

AScha3_1-1690122421849.png

 

If you feel a post has answered your question, please click "Accept as Solution".
No, that's not the reason.
I changed this setting.
The problem is that only the first Rank from the ADC_SQR3 register is measured.
Second Rank is never measured for some reason.
My task is also to measure the second Rank from the ADC_SQR3 register. 

 

Which STM32?

> My goal now is to understand how ADC works.

Then don't use Cube/HAL. It hides the details. Read the ADC chapter in manual, and write your own code.

> only the first Rank from the ADC_SQR3 register is measured.

 How do you know?

Where do you set the sequence length?

JW

>Where do you set the sequence length?

hadc1.Init.NbrOfConversion = 2;

Which STM32?

> only the first Rank from the ADC_SQR3 register is measured.

 How do you know?

>> Where do you set the sequence length?
> hadc1.Init.NbrOfConversion = 2;

Well, I don't see it in ADC_SQR1.L, in the list of registers you've given.

As I've said, if you want to learn how ADC works, don't use Cube/HAL, write your own code based on reading and understanding the manual.

JW

Thank you.
The SQR1 register actually contained the number 1.
I put 2, but it still didn't help.
ADC1->SQR1=2097152;
2097152==0010 0000 0000 0000 0000 0000
I have STM32F407VGT6

png.png

LCE
Principal

In my H723 ADC setup I'm using the HAL defines for setting the rank, because there's some bit shifting involved, but I don't know if that applies to the F4 as well.

sConfig.Rank = ADC_REGULAR_RANK_2;

This definitely works in STM32F407.
sConfig.Rank = 2;
Here is an example if I set ONLY the second Rank.

png.png

MMust.5
Senior II

The problem is that the DR register is 16 bit and when I write like this
a[0] = HAL_ADC_GetValue(&hadc1);
then I load the result from only one Rank.
How to download the result from the second Rank

And when I write this
HAL_ADC_Start(&hadc1);
then the conversion always starts from the first Rank

Maybe the second Rank is being converted, but I just don't know how to save the result of the conversion.