Skip to main content
thomas23
Associate II
August 19, 2026
Question

STM32U535 wrong calibration values (VREFINT and SENSE)

  • August 19, 2026
  • 3 replies
  • 71 views

Hello,

When trying to sample internal channels on STM32U535, it appears that calibration values (stored at 0x0BFA0705-6 for VREFINT and 0710-0742 for TS) give incorrect result.

I have tried to sample the value with ADC1 (14bits) and ADC4 (12 bits, x4 on the value), but the rsult is the same.

I found 1427 when sampling VREFINT with ADC4 (12 bits). The value stored for VREFINT is 0x3150. = 3156 * 4

When applying the formula, that gives 3000 * 3156 / 1427 = 6634mV. Kind of the double of what I actually have.

Similarly, values from temperature sensor are wrong. All other channels (that are not linked to any factory calibrated value) are working fine. So I suppose there might be something wrong with the calibration…

Could someone confirm or find what is wrong? Here is the relevant code.

EDIT: Also, I would like to point out that the value I sample actually makes sense:
Considering Vrefint is ~1.2V, from the datasheet, Embedded voltage reference.
3.3 * 1427 / 4095 = 1.15V. Pretty close to Vrefint.

So, that would confirm my measure is correct, and that the factory calibrated value is wrong.
Also, in case you ask, I have checked the calibrated value byte per byte, also by reading the memory “manually”. 0x3150 is the value, no doubt about that.

 

Thank you

 


RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADCDAC;
PeriphClkInit.AdcDacClockSelection = RCC_ADCDACCLKSOURCE_SYSCLK;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);

__HAL_RCC_ADC1_CLK_ENABLE();

ADC1->CFGR1 |= ADC_CFGR1_OVRMOD; // Just in case an Overrun happens, keep converting
ADC1->CFGR1 |= 0b0 << ADC_CFGR1_RES_Pos;
ADC1->SMPR1 |= 0b101 << ADC_SMPR1_SMP0_Pos;
ADC1->PCSEL |= ADC_PCSEL_PCSEL_0;
ADC1->SQR1 |= 0 << ADC_SQR1_L_Pos;
ADC1->SQR1 |= 0 << ADC_SQR1_SQ1_Pos;
ADC1->CR &= ~ADC_CR_DEEPPWD; // Leave low power mode (active by default)
__ISB();
__DSB();
Delay1us(10);
ADC1->CR |= ADC_CR_ADVREGEN;
Delay1us(100);
while (!(ADC1->ISR & ADC_ISR_LDORDY));

// Calibrate
ADC1->CR |= ADC_CR_ADCAL;
Delay1us(20);

__IO uint32_t tries = 0xFF;
while ((ADC1->CR & ADC_CR_ADCAL) && --tries) // Wait for the calibration to complete.
Delay1us(1000);
if (!tries)
{
// failed, reboot the MCU. TODO
asm("nop");
}

ADC12_COMMON->CCR |= ADC_CCR_VREFEN;

Delay1us(10);

ADC1->CR |= ADC_CR_ADEN;
while (!(ADC1->ISR & ADC_ISR_ADRDY));

ADC1->CR |= ADC_CR_ADSTART;

 

3 replies

TDK
August 19, 2026

Increase your sampling time to max. The internal channels have minimum sampling times you are not meeting (see datasheet).

"If you feel a post has answered your question, please click ""Accept as Solution""."
thomas23
thomas23Author
Associate II
August 19, 2026

Already tested. Didn’t change anything.

thomas23
thomas23Author
Associate II
August 19, 2026

Also, I would like to point that the value I have actually makes sense:
Considering Vrefint is ~1.2V, from the datasheet, Embedded voltage reference
3.3 * 1427 / 4095 = 1.15V.

So, that would confirm my measure is correct, and that the factory calibrated value is wrong.
Also, in case you asked, I have checked the calibrated value byte per byte, also by reading the memory “manually”. 0x3150 is the value, no doubt about that.