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

STM32U535 wrong calibration values (VREFINT and SENSE)

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.