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

 

17 REPLIES 17

> 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

To me, this looks very much like a drop of Vref when you turn this timer on.

> I am using the HRTIM on an STM32F334 to drive a buck/boost converter.
> This is a custom board,  ...

This is a high-noise, high-EMI application.
The worst thing one could do in this environment is to connect VDDA directly to VDD.
I would recommend a separate VDDA supply, or an external Vref.

 

azdepfr
Associate III

@Andrew Neil  Good point, thanks for raising this.

I initially suspected HRTIM because the issue appeared after enabling it in my main project.

However, after isolating the problem in a minimal test, I can clarify the behavior:

  • HRTIM initialization alone (MX_HRTIM1_Init) does NOT cause any instability
  • ADC regular readings remain fully stable as long as injected conversion is not started

The instability appears only when:

HAL_ADCEx_InjectedStart_IT(&hadc1);

is called, with the injected trigger configured from HRTIM.

So the key point seems to be:

  • not HRTIM initialization itself
  • but the activation of injected conversions (triggered by HRTIM)

Also, I observed that:

  • if at least one regular conversion is performed before starting injected conversion → stable
  • if not → regular readings become unstable

This suggests a dependency on the ADC internal state before injected conversions are enabled.

So at this stage, my understanding is that the issue is related to the interaction between:

  • ADC regular conversions (internal channels)
  • ADC injected conversions
  • and the HRTIM-triggered injection mechanism

rather than HRTIM alone.

Let me know if you think I should further isolate the trigger (for example by disabling HRTIM events while keeping injected configured).

Thanks, this is a valid point.

I agree that a VDDA / VREF-related issue is a credible explanation for my initial observation, especially in the original buck/boost application where the environment is noisy and VDDA is directly tied to VDD.

However, in the more recent minimal tests, I observed something more specific:

  • if injected conversion is not started, regular readings remain stable
  • if injected conversion is started, readings may become unstable
  • but if I perform a first regular read loop before enabling injected conversion, the second read loop remains stable

So at this stage, I suspect there may be two separate effects:

  1. a possible hardware / analog supply sensitivity in the original application
  2. an ADC sequencing interaction when mixing regular internal-channel reads and injected conversions on the same ADC

In other words, your VDDA/VREF concern may explain the original large shift, but it does not seem to fully explain why the behavior also depends on whether a first regular conversion was performed before starting injected conversion.

I will keep investigating both aspects.

However, in the more recent minimal tests, I observed something more specific:
> - if injected conversion is not started, regular readings remain stable
> - if injected conversion is started, readings may become unstable
> - but if I perform a first regular read loop before enabling injected conversion, the second read loop remains stable

If my assumption is correct and the "instability" is caused by VDDA / Vref, the driving force (and thus the cause) is the supply current.
Any change in current draw, no matter if caused by an external or internal source, will cause fluctuations of VDD - and subsequently VDDA. And the effect would be more or less proportional.

You have the hardware, you can do the measurements.
You could e.g. use a scope to record the VDDA voltage during those operations you mentioned.  And e.g. use instrumentation code to toggle a GPIO, as a trigger signal for the scope.

azdepfr
Associate III

Hello,

I would like to share an update regarding my previous issue with ADC regular conversions becoming unstable when using injected conversions triggered by HRTIM on STM32F334.

 

  • ADC1 is used for:
    • injected conversions (triggered by HRTIM, for control loop)
    • regular conversions (VREFINT and TEMPSENSOR, for monitoring)
  • Regular conversions were initially handled using interrupt mode (HAL_ADC_Start_IT())

Observed behavior:

  • Without injected conversions → regular measurements are stable and correct
  • With injected conversions enabled → regular measurements become unstable or incomplete
  • Behavior was also sensitive to initialization sequence (e.g. performing some reads at startup changed the outcome)

Additional investigation

I verified that:

  • Polling mode works correctly:
    • both VREFINT and TEMPSENSOR are measured
    • values are stable and consistent
  • Therefore:
    • ADC configuration is correct
    • internal channels are correctly enabled
    • the issue is not related to hardware (VDDA, etc.

Solution using DMA

I reconfigured the regular group as:

  • Scan mode with 2 ranks:
    • Rank 1 = VREFINT
    • Rank 2 = TEMPSENSOR
  • DMA in normal mode (2 samples)
  • Triggered with:

HAL_ADC_Start_DMA(&hadc1, buffer, 2);

Result:

  • Both values are correctly acquired in all cases
  • Measurements remain stable even when injected conversions are active
  • No dependency on initialization sequence anymore

Conclusion

This strongly suggests that:

  • The ADC itself is working correctly
  • The issue is related to interrupt-based handling of regular conversions in scan mode
  • Mixing regular (interrupt mode) and injected conversions on the same ADC can lead to unreliable behavior (likely due to EOC/EOS flag handling and timing)

Using DMA for regular conversions avoids this issue completely and provides robust behavior.

 

For this application, the following architecture works reliably:

  • Injected conversions (HRTIM-triggered) → interrupt
  • Regular conversions → DMA (scan mode)
TDK
Super User

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

 

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

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

 

> HRTIM initialization alone (MX_HRTIM1_Init) does NOT cause any instability

 

With conflicting statements like these it's hard to provide any real help, or even trust what is being said is accurate. I suggest posting actual code being used rather than AI generated "summaries".

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

> With conflicting statements like these ...

IMHO already the use of terms like "unstable" in this matter reveal that the OP doesn't understand the underlying problem.

Execution of code in embedded systems does not happen in an abstract space, but on real hardware and peripherals with complex interactions. Any approach by coding tricks or statistics are bound to fail.

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