cancel
Showing results for 
Search instead for 
Did you mean: 

I want to sample one (of six) ADC channel for 2 ms in blocking mode. How hard can it be?

Haddock
Associate III

I using STM32CubeIDE and STM32L03.

I don't understand how to make a simple sample of a ADC channel (in blocking mode). I had config the Cube to generate a ADC_Init() that contains my 6 Analog In channels.

I want to have a function that goes like this: uint16_t AD_Read(unit32_t channel) { ... }

I make a ADC_Start and then HAL_Polling() and then get the ADC value. Doing that for 20 samples. But where do I set what ADC channel I want to read? Is it the rank member I set before I calling HAL_ADC_Start() or what? The first channel in ADC_Init has this "rank" member set.

The config I tried to keep as simple as I could. No group scanning or continuous scanning and no interrupt.

The ADC_Init

hadc.Instance = ADC1;

 hadc.Init.OversamplingMode = DISABLE;

 hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;

 hadc.Init.Resolution = ADC_RESOLUTION_10B;

 hadc.Init.SamplingTime = ADC_SAMPLETIME_19CYCLES_5;

 hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;

 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 hadc.Init.ContinuousConvMode = DISABLE;

 hadc.Init.DiscontinuousConvMode = DISABLE;

 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

 hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 hadc.Init.DMAContinuousRequests = DISABLE;

 hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

 hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

 hadc.Init.LowPowerAutoWait = DISABLE;

 hadc.Init.LowPowerFrequencyMode = DISABLE;

 hadc.Init.LowPowerAutoPowerOff = DISABLE;

plus six ADC-channel where the first has sConfig.rank = ADC_RANK_CHANNEL_NUMBER

1 ACCEPTED SOLUTION

Accepted Solutions

Now it works. I saw the array of configurations per channel. I modified them so it suited my processor.

Then I called ad_read () with Hadc and channel selection as parameters. The error was in the fact that the AD got the wrong configuration. Now it got correct.

Thanks again.

View solution in original post

8 REPLIES 8
KnarfB
Principal III

if you don't want to use the automatics, configure only the first channel in CubeMX and use that config as a blueprint for your user written config_i for each channel i. Then your code is

while(1) {
  config_1
  start
  poll
  v[1] = get_value
 
  config_2
  ...
}

You may of course use an inner for-loop etc..

If it doesn't work, show your code snippets

hth

KnarfB

Haddock
Associate III

The thing is to configure each channel as the first one.

Example:

AD_Read(channel)

{

config_[channel] (see below)

for n=0; n < 20; n++

{start

poll

x = x + get_value}

x= x / 20

return x

}

FYI:

First ch look like this in the ADC_Ini

 sConfig.Channel = ADC_CHANNEL_1;

 sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;

 if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

Am I thinking right?

KnarfB
Principal III

You init sConfig once and then change only the Channel field, not the rank, they are all rank 1, and call HAL_ADC_ConfigChannel right before the start.

You can conveniently keep the channels in an array like

const uint32_t adc_channels[] = {
  ADC_CHANNEL_VREFINT,    // internal measurement channel
  ADC_CHANNEL_TEMPSENSOR, // internal measurement channel
  ADC_CHANNEL_8,
  ADC_CHANNEL_9,
  ADC_CHANNEL_10,
  ADC_CHANNEL_11
};

and say

sConfig.Channel = adc_channels[i];

in the inner for-loop.

hth

KnarfB

Haddock
Associate III

I got it. I must say, I did that test before (I think). I thought the HAL_ADC_ConfigChannel() made some switching around the ADC and after that I could make a START(); poll..., Read. But it didn't work out. Some of the sampled values was very huge like I needed to use a MASK to get the correct value.

However, your answer show that I'm on the right track.

Thanx

Tried again and it does NOT work. I don't understand. It's like the ADC is not turned on. There must be some ADC_enable() somewhere?

Maybe I have problems with definitions/declarations of variables? To change channel in ADC_Read() the sConfig needs to be reachable also here.

My ADC_Init() is in main.c. CubeIDE takes care of that. Then I have a file called adc.c/adc.h. adc_read() is defined here.

sConfig is defined in ADC_Init(). I move the definition of sConfig outside of ADC_Init() and then declare it as external in ADC_Read(). Also included the xxxxx_adc.h file from the Driver folder.

Is it here the error is committed?

S.Ma
Principal

This code works on STM32C0 and does repetitively blocking single channel read... for all of them, including the internal ones.

The ADC generation might be newer, the most difficult to grasp was how to configure it for the -unanticipated- simple operating mode...

Thank you. it's all about configuration and this will help me. I think I miss something obvious.

Now it works. I saw the array of configurations per channel. I modified them so it suited my processor.

Then I called ad_read () with Hadc and channel selection as parameters. The error was in the fact that the AD got the wrong configuration. Now it got correct.

Thanks again.