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);
}

 

 
 
15 REPLIES 15

Note, that ADC starts the second conversion immediately after the first on ends, so if your check-conversion-end and readout functions take longer than the second conversion, the first conversion's result is already lost and you are reading only the second conversion's result.

JW

I can never read the result of the second transformation.

This may be consequence of overrun, too. The RM is not entirely clear whether in case of overrun the old result is retained or it's overwritten with the new one.

Check the OVR bit in ADC_SR.

JW

I found out that channels 5 and 6 are not working correctly.
Most likely only channel 6 does not work correctly, but due to the fact that channels 5 and 6 were in the same sequence, they did not work correctly together.
For the present I do not know for what reason, it is necessary to look at the scheme.

I changed ADC channels. Now there is a problem that you described.
I only get results from Rank 2

I need to find how to take the result from two Ranks

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

 

LCE
Principal

Sooner or later you should throw out any polling stuff anyway...

On a H735 I have 7 sequenced ADC channels running all the time in the background with circular DMA for monitoring several power supplies. Every 100 ms or so the buffer is checked, with least priority.