cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F334 HRTIM and ADC noise

azdepfr
Associate III

Hello,

I am using the HRTIM on an STM32F334 to drive a buck/boost converter.

I monitor MOSFET temperature using NTCs via ADC2, and I also need to measure the internal CPU temperature and VREFINT using ADC1.

ADC configuration:

ADC1

  • Regular: VREFINT, TEMPSENSOR

  • Injected: Vin

ADC2

  • Regular: MosFetTemp1, MosFetTemp2, AnalogStartInfo

  • Injected: Vout

Issue:

As soon as the HRTIM is initialized (even without starting it), the ADC regular conversion values become unstable.

Observations:

  • 100 samples of VREFINT only → stable when HRTIM is not initialized

  • 100 samples of TEMPSENSOR only → stable when HRTIM is not initialized

  • 100 samples of (VREFINT + TEMPSENSOR) → stable when HRTIM is not initialized

  • 100 samples of (VREFINT + TEMPSENSOR + ANALOGSTARTINFO) → stable when HRTIM is not initialized

As soon as HRTIM is initialized, all these measurements become noisy/unstable.

The issue is also present:

  • even if HRTIM is not started

  • even if GPIOs are not initialized  (so MOSFETs are not switching)

  • even if line HAL_HRTIM_MspPostInit(&hhrtim1) is comment

Question:

Has anyone experienced a similar issue with HRTIM affecting ADC accuracy on STM32F3?

Could this be related to:

  • internal analog coupling between HRTIM and ADC?

  • ADC clocking or trigger configuration?

  • VDDA or internal reference disturbance caused by HRTIM initialization?

Any insights or ideas would be greatly appreciated.

Thanks in advance.

Best regards,

in main.c :

  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_ADC2_Init();

  MX_HRTIM1_Init();

  /* ---- Test  pour debug ADC ---- */
  if(HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
  {

  }

  Debug_ActiveCanauxInternesAdc1();
  HAL_Delay(2);

  U16 volatile u16_Index = 0;
  U16 volatile tu16_Data[100][2];
  U16 volatile tu16_Data_2[100];

  while(1)
  {
    U16 volatile u16_raw_vdda;
    U16 volatile u16_raw_cpu;
    U16 volatile u16_raw_dplus;

    u16_raw_vdda  = Debug_LireVddaBrut();
    u16_raw_cpu   = Debug_LireTempCpuBrut();
    u16_raw_dplus = Debug_LireDPlus();

    tu16_Data[u16_Index][0] = u16_raw_vdda;
    tu16_Data[u16_Index][1] = u16_raw_cpu;

    tu16_Data_2[u16_Index] = u16_raw_dplus;

    //printf("TEMP raw = %u\r\n", u16_raw);
    HAL_Delay(100);
    u16_Index++;
    if (100 <= u16_Index)
    {
      u16_Index = 0;
    }
  }
  /* ------- fin test pour debug ADC ---------- */

 

DebugTemp.c :

void Debug_ActiveCanauxInternesAdc1(void)
{
  LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1),
      LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_TEMPSENSOR);

  HAL_Delay(1);
}

U16 Debug_LireTempCpuBrut(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  sConfig.Channel      = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank         = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff   = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_601CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset       = 0;

  if(HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    return 0xFFFF;
  }

  if(HAL_ADC_Start(&hadc1) != HAL_OK)
  {
    return 0xFFFE;
  }

  if(HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
  {
    return 0xFFFD;
  }

  return (U16)HAL_ADC_GetValue(&hadc1);
}

U16 Debug_LireVddaBrut(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  sConfig.Channel      = ADC_CHANNEL_VREFINT;
  sConfig.Rank         = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff   = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_181CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset       = 0;

  if(HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    return 0xFFFF;
  }

  if(HAL_ADC_Start(&hadc1) != HAL_OK)
  {
    return 0xFFFE;
  }

  if(HAL_ADC_PollForConversion(&hadc1, 10) != HAL_OK)
  {
    return 0xFFFD;
  }

  return (U16)HAL_ADC_GetValue(&hadc1);
}

U16 Debug_LireDPlus(void)
{
  ADC_ChannelConfTypeDef sConfig = {0};

  sConfig.Channel      = ADC_CHANNEL_4;
  sConfig.Rank         = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff   = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_19CYCLES_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset       = 0;

  if(HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
  {
    return 0xFFFF;
  }

  if(HAL_ADC_Start(&hadc2) != HAL_OK)
  {
    return 0xFFFE;
  }

  if(HAL_ADC_PollForConversion(&hadc2, 10) != HAL_OK)
  {
    return 0xFFFD;
  }

  return (U16)HAL_ADC_GetValue(&hadc2);
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
azdepfr
Associate III

@TDK, @Ozone Thanks for your comment.

I restart the issue description, and I re-send test software.

On a custom board, I use HRTIM to manage buck-boost MosFet.
HRTIM trigs ADC1 (VIN) and ADC2 (VOUT).

ADC1 Regular is used to : VREFINT, TEMPSENSOR
ADC2 Regular is used to : MosFetTemp1, MosFetTemp2, AnalogStartInfo

I haved issue by using TEMPSENSOR, between two conversions (100mS) some time I haved 10°C.

I tried on a Nucleo-F334R8 with STCubeIDE, I developped a soft to check.
The software can read 100 times (every 100mS) VREFINT(ADC1), TEMPSENSOR(ADC1) and an external signal(ADC2), then start HRTIM, then read 100 times analogs signals.

The software is executed in debug to be able to set breakpoint.
By using breakpoint, I can execute (or not) the first loop, then I can execute (or not) HRTIM start, then I execute the second loop.
The analog values are stored in a array (VREFINT and TEMPSENSOR in the same array), I read array in stop mode by using the debugger.
The issue is present on VREFINT, TEMPSENSOR and external signal. To simplify I describe only TEMPSENSOR.

test 1:
- read in first loop => TempSensor is stable 1739,1740,1739,1738,1740,1742 etc etc
- HAL_ADCEx_InjectedStart_IT called
- read in second loop => TempSensor is stable 1740, 1743, 1743, 1739 etc

test 2:
- NO read in first loop
- HAL_ADCEx_InjectedStart_IT called
- read in second loop => TempSensor is UNstable and wrong 1435, 1452, 1440, 1485, 1472, 1439, etc

test 3:
- NO read in first loop
- HAL_ADCEx_InjectedStart_IT NOT called
- read in second loop => TempSensor is stable 1738, 1736, 1740, 1739 , 1737 etc etc

test 4:
- read in first loop => TempSensor is stable
- HAL_ADCEx_InjectedStart_IT NOT called
- read in second loop => TempSensor is stable

So :
- if HAL_ADCEx_InjectedStart_IT is not called : TempSensor always stable (values are in a small range)
- if HAL_ADCEx_InjectedStart_IT is called :
-- if I execute the first loop : TempSensor always stable
-- if I don't execute the first loop :
--- Tempsensor is wrong ( 1430 to 1492 ) => cpu temperature > 100°C !!!
--- Tempsensor is not stable ( some time 60 units between two sample )

I use HAL_ADC_PollForConversion too read regular adc. (I tryed interrupt, but no effect).
I tried with/without HAL_ADC_Stop.
I tried to use only one conversion and reconfigure adc before start conversion, no effect.

At the end of last week I tryed DMA, it's ok, Tempsensor is alaways stable, with/without HAL_ADCEx_InjectedStart_IT and with/without read adc before start hrtim.

I read errata, I saw issue hrtim can disturb DAC, but nothing about hrtim/adc.

If there is a known limitation or recommended approach for mixing regular + injected conversions on STM32F334, I would be very interested.

 

I hope to be clear, sorry for my English !

 

Best regard's

View solution in original post

17 REPLIES 17
TDK
Super User

Nothing in the errata sheet about this.

Is this custom hardware? Can you show schematic? Are there solid VREF connections with bypass caps?

If you feel a post has answered your question, please click "Accept as Solution".
Andrew Neil
Super User

@azdepfr wrote:

As soon as the HRTIM is initialized (even without starting it), the ADC regular conversion values become unstable.


What, exactly, do you mean by "unstable" ?

Please show some actual figures.

As @TDK said, please also show your hardware setup.

Do you see noise appear anywhere else in this system when this happens?

 

How to write your question to maximize your chances to find a solution

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
azdepfr
Associate III

Hello,

Thanks @TDK and @Andrew Neil for your replies.

Regarding the hardware:

This is a custom board, so I cannot share the full schematic, but I can provide some details:

  • VSSA is directly connected to GND

  • VDDA and VBAT are connected to +3.3 V

  • Each VDD pin has a 100 nF decoupling capacitor placed close to the pin

  • However, there is currently no dedicated capacitor directly on VDDA

Regarding VREF:

  • VREF+ is internally tied to VDDA (no external reference used)

Regarding the "unstable" behavior:

Here are actual measurements (raw ADC values for TEMPSENSOR):

  • Without HRTIM initialization: values are stable around 1735–1739

  • With HRTIM initialized (but not started): values drop and fluctuate between 1380–1480

This range does not seem realistic, as it would correspond to a CPU temperature of around 120°C.

Additional observations:

  • The issue appears even if HRTIM is not started

  • The issue is still present if GPIOs are not initialized (no MOSFET switching)

  • The same behavior is observed on external ADC channels (ADC2), not only on internal channels

Question:

Could this be related to:

  • VDDA decoupling (missing capacitor directly on VDDA)?

  • Internal analog interference between HRTIM and ADC?

  • ADC clock or sampling configuration?

I have not yet observed obvious noise elsewhere, but I will investigate further.

Any suggestions or similar experiences would be very helpful.

Best regards,


@azdepfr wrote:

This is a custom board, so I cannot share the full schematic,


Just because it's a custom doesn't mean you can't share it!

If it's confidential, you could raise a direct support case with ST: https://ols.st.com/s/ 

Without seeing a schematic, we obviously don't have the full picture!

Can you reproduce this on an ST board ?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
azdepfr
Associate III

Hello,

Thanks @Andrew Neil for your suggestion.

You are right, testing on an ST evaluation board would help to clearly distinguish between a hardware issue and an MCU-related behavior.

At the moment, I have only tested this on our custom board. I will try to reproduce the issue on an ST board (for example NUCLEO or Discovery with STM32F3 + HRTIM) to confirm whether the behavior is the same.

Regarding the schematic, I understand your point. Unfortunately, I cannot share it publicly due to company restrictions, but I will consider opening a support ticket with ST if needed.

In parallel, I will also try to improve the VDDA decoupling (adding a capacitor directly on VDDA) and check if it impacts the measurements.

I will report back with the results.

Best regards,

Probably this is (unlikely) an undocumented deficiency in the silicon or (likely) there is more to the story here (hardware design error?). It's hard to know which from the outside, but my money is on the latter.

Reproducing on known good hardware would be a good next step. Barring that, reproducing on several different boards can also provide information. Attaching a minimal working example that shows the problem can help, but what you attached is pretty good.

I don't see any issues in the posted code. Don't have an F3 board to test.

Is VDDA connected to VDD? If not, is it always greater than VDD and provided first? These are requirements per the data sheet.

If you feel a post has answered your question, please click "Accept as Solution".
azdepfr
Associate III

Hello,

Thanks @TDK for your detailed feedback.

Yes, VDDA is directly connected to VDD (both at +3.3 V), so it should meet the requirement of being at least equal to VDD and powered at the same time.

However, as mentioned earlier, there is currently no dedicated decoupling capacitor directly on VDDA, which might be an issue. I will add proper decoupling (100 nF + 1 µF close to VDDA/VSSA) and check if it improves the situation.

I agree that reproducing the issue on known good hardware would be a very useful step. I will try to run the same test on an ST evaluation board to determine whether this is related to our hardware design or not.

I will also try to reproduce the issue on another board of the same design to see if the behavior is consistent.

Regarding your comment about a potential hardware issue, I understand your point. The fact that the problem appears as soon as HRTIM is initialized (even without switching activity) suggests that enabling internal analog blocks may be affecting VDDA or the reference.

I will report back with the results after these tests.

Best regards,

azdepfr
Associate III

Hello,

I test on a Nucleo-F334, and I observe an unexpected behavior when mixing ADC regular and injected conversions on the same ADC.

The issue appears when starting injected conversions triggered by HRTIM.

Configuration

  • MCU: STM32F334
  • ADC used: ADC1
  • Regular channels:
    • VREFINT
    • TEMPSENSOR
  • Injected channel:
    • ADC_CHANNEL_1
    • Trigger: HRTIM_TRG2
  • HAL drivers (CubeMX generated project)

Test description

I built a minimal test project with:

  • ADC initialized normally
  • Internal channels enabled (VREFINT + TEMPSENSOR)
  • Regular conversions done by polling (no DMA, no interrupt)
  • Injected conversion started with:

HAL_ADCEx_InjectedStart_IT(&hadc1);

Test results

Test 1

  • Read VREFINT & TEMPSENSOR in a first loop → stable
  • Start injected conversion
  • Read again → stable

Test 2

  • No read before starting injected conversion
  • Start injected conversion
  • Read VREFINT & TEMPSENSOR → unstable

Test 3

  • No injected conversion
  • Read → stable

Test 4

  • Read first loop
  • No injected conversion
  • Read again → stable

Key observation

The instability appears only if:

  • injected conversion is started
  • AND no regular conversion was performed beforehand

It seems that performing at least one regular conversion before enabling injected conversions “stabilizes” the ADC behavior.

Additional checks

  • ADC calibration performed → no effect
  • Adding HAL_ADC_Stop() after conversions → no effect 

    Code excerpts

    Injected configuration:

    sConfigInjected.InjectedChannel = ADC_CHANNEL_1;
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_19CYCLES_5;
    sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_HRTIM_TRG2;
    sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING;

    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    HAL_ADCEx_InjectedStart_IT(&hadc1);

    Regular read (simplified):

    HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 10);
    value = HAL_ADC_GetValue(&hadc1);

 

Expected behavior

Regular conversions should remain stable regardless of whether injected conversions are started or not.

Actual behavior

Regular conversions become unstable depending on initialization sequence.

Question

Is this a known limitation or expected behavior of STM32F334 ADC?

More specifically:

  • Is there a required sequence when mixing regular and injected conversions?
  • Is an initial “dummy conversion” required after enabling internal channels?
  • Could this be related to ADC internal multiplexer behavior or known errata?

Thanks in advance for your help.

 

PS : I join CubeIDE project

What about your original observation that it seemed to be  starting HRTIM which caused the "instability" ?

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.