Skip to main content
Visitor II
June 12, 2025
Question

STM32H7 + Zephyr: ADC + DMA giving wrong (low) values for Internal temperature, VBAT, VREF

  • June 12, 2025
  • 4 replies
  • 930 views

Hi,

we are using ADC with DMA for internal ADC channel like internal Temperature sensor, VBAT, VREF but we are facing issue related to accuracy please help me on this Configuration:

ADC channel:

   adc_channel_config_t ADC3_temp_config = {
        .channel       = ADC_CHANNEL_TEMPSENSOR,
        .rank          = ADC_REGULAR_RANK_8,
        .sampling_time = ADC_SAMPLETIME_810CYCLES_5,
    };
   adc_channel_config_t ADC3_vbat_config = {
        .channel       = ADC_CHANNEL_VBAT,
        .rank          = ADC_REGULAR_RANK_9,
        .sampling_time = ADC_SAMPLETIME_8CYCLES_5,
    };
        uC_AtoD_HAL::adc_channel_config_t ADC3_vref_config = {
        .channel       = ADC_CHANNEL_VREFINT,
        .rank          = ADC_REGULAR_RANK_10,
        .sampling_time = ADC_SAMPLETIME_8CYCLES_5,
};
 
DMA :
dma_channel_config_t ADC3_dma_config = {
        .channel = 2, // Channel 0 - ADC1, Channel 1 - ADC2, Channel 2 - ADC3, In H7 this parameter is used as a
                      // instance number
        .stream          = DMA1_Stream3,
        .src_data_width  = DMA_PDATAALIGN_WORD,
        .dest_data_width = DMA_MDATAALIGN_WORD
    };
 
ADC register for internal:
    ADC_Common_TypeDef *adc_common = ADC3_COMMON_REGISTER(pADC3Handler);
    adc_common->CCR |= ADC_CCR_TSEN | ADC_CCR_VREFEN | ADC_CCR_VBATEN;
 
Code:
For temperature:
#define TS_CAL1_TEMP 30.0f
#define TS_CAL2_TEMP 110.0f
#define TS_CAL1_ADDR ((uint16_t*)0x1FF1E820) // 30°C
#define TS_CAL2_ADDR ((uint16_t*)0x1FF1E840) // 110°C
uint16_t TS_CAL1 = *TS_CAL1_ADDR;
uint16_t TS_CAL2 = *TS_CAL2_ADDR;
LOG_DBG("TS_CAL1: %d, TS_CAL2: %d\n", TS_CAL1, TS_CAL2);
uint32_t TS_DATA = 0;
for (int i = 0; i < NUM_OF_CHANNEL_BUFFERS_ADC3; i++)
{
TS_DATA += MCUTemperature[i];
}
TS_DATA = TS_DATA / NUM_OF_CHANNEL_BUFFERS_ADC3;

float McuTemperature = 
(float_t)(((TS_CAL2_TEMP - TS_CAL1_TEMP) / (float_t)(TS_CAL2 - TS_CAL1)) * (TS_DATA - TS_CAL1)) + TS_CAL1_TEMP;
 
For Vref:
#define VREFIN_CAL ((uint16_t*)0x1FF1E860)
uint16_t Vrefin_Cal_Value = *VREFIN_CAL;
uint32_t VREF_DATA = 0;
for (int i = 0; i < NUM_OF_CHANNEL_BUFFERS_ADC3; i++)
{
VREF_DATA += Vrefint_volt[i];
}
VREF_DATA = VREF_DATA / NUM_OF_CHANNEL_BUFFERS_ADC3;
float vref = 3.3 * (Vrefin_Cal_Value /VREF_DATA );
vref = (vref / 65535) * VREF_DATA;
 
for Vbat:
    uint32_t Vbat_DATA = 0;
    for (int i = 0; i < NUM_OF_CHANNEL_BUFFERS_ADC3; i++)
    {
      Vbat_DATA += BatteryVoltage[i];
    }
    Vbat_DATA = Vbat_DATA / NUM_OF_CHANNEL_BUFFERS_ADC3;

   LOG_DBG("Vbat Raw count : %d\n",Vbat_DATA );

  BatteryVoltage = (Vbat_DATA * 4.0 * 3.3) / 65535.0;
 
Please let me know any configuration is miss 
Thanks in Advance
 


    This topic has been closed for replies.

    4 replies

    Super User
    June 12, 2025

    A few things:

    • Are you calibrating the ADC before using it? You need to.
    • What chip are you using?
    • What raw ADC values do you get?
    • What vbat//vrefint/temperature values do you get and, if not obvious, why do you think they're incorrect?
    • You're using 130 for the upper end temperature instead of 110 as the comments say.
    Visitor II
    June 13, 2025

    Are you calibrating the ADC before using it? You need to.

    ANS: Yes

    What chip are you using?

    ANS: STM32H743ZIVET6

    What raw ADC values do you get?

    ANS: During debugging we could read the below calibration values and ADC raw count.

    TS_CAL2 = 16287, TS_CAL1 = 12805.

    Temperature raw count = 2877

    Vbat raw count = 2760

     

    You're using 130 for the upper end temperature instead of 110 as the comments say.

    ANS:

    #define TS_CAL1_TEMP 30.0f
    #define TS_CAL2_TEMP 110.0f
     
    What vbat//vrefint/temperature values do you get and, if not obvious, why do you think they're incorrect?
    ANS:
    We are using 16bit ADC 
    For temperature,

    As per the Datasheet of STM32H743ZI, an internal MCU temperature sensor connected to ADC3_INP18 channel is factory calibrated and below are the calibration values stored into the MCU internal Flash.

    DhirajThakur_0-1749794370052.jpeg

     

    Below formula will be used for actual temperature calculation. Where TS_DATA is the actual temperature sensor output value converted by ADC. also mention this formula in code above 

    DhirajThakur_1-1749794370053.jpeg

     

    At room temperature, it is expected to get the value of TS_DATA between TS_CAL1 & TS_CAL2 or near around TS_CAL1.  But we are getting TS_DATA = 2877 & calculated temperature = -198.098

    For Vbat,

    ADC count for Vbat/4  = 2760, formula used to calculate battery volt = 4 * 3.3 * Vbat raw count / 65535 , where 4 is multiplying factor for ADC count Vbat /4,  3.3 V is VDDA, 65535 is for 16 bit ADC resolution.

    Hence Calculated Vbat = 0.56V

    Measured Vbat pin voltage on STM32H743ZI Nucleo board is 3.25V. 

     
    ST Employee
    June 13, 2025

    Hello @DhirajThakur

    Since the issue is related to TS_DATA value (very low), and this value is converted by ADC, most probably the issue is related to the ADC configuration; try using a longer sampling time for the internal temperature sensor.

    Another thing is in your formula: Vbat= 4 * 3.3 * Vbat raw count / 65535 where VDDA= 3.3 

    Depending on the package VDDA can be internally connected to Vref+ or not, could you specify the package you're using! 

    Super User
    June 13, 2025

    > ADC_REGULAR_RANK_8

    If converting 3 channels, they should be on ranks 1-3. Or maybe 0-2, not sure if it's base 0 or 1.

    I have to believe the issue is in how the ADC is being configured. Doesn't look like you're using HAL. Ensure the SQRx registers point to the correct channels.

    > ADC_SAMPLETIME_8CYCLES_5

    Unlikely to be long enough for VREFINT or VBAT. Required sampling duration is in the datasheet.

    ST Employee
    June 17, 2025

    Hi @DhirajThakur 

     

    This post has been escalated to the ST Online Support Team for additional assistance.  We'll contact you directly.

     

    Regards,

    Billy