Electronic – STM32L0x1 incorrect temperature reading

sensorstm32temperature

I'm having trouble reading the temperature, its values are incorrect. The temperature in the room is 22C and the temperature of the sensor shows 55C (selfheating and the measurement error cannot be that big). I have many times checked the correctness of the code, and I use the functions recommended by the manufacturer (Code examples from reference manual). I have no idea why it doesn't work.

Data:

STM32L0x1 family MCU

3.3V supply voltage

Clock frequency: 2.097MHz (MSI)

Problems I ruled out:

1) ADC sampling time too short (it should be longer than 10us and it is).

2) I tested the code on different MCUs of the same model, and also on other models of STM32L0x1 family.

3) VDD of the chip is 3.3V, not e.g. 3.0V, there is no mistake here.

Below I paste the program code, as well as sample data from debugging in STM Studio.

#include "stm32l0xx.h"

#define TEMP130_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FF8007E))
#define TEMP30_CAL_ADDR  ((uint16_t*) ((uint32_t) 0x1FF8007A))
#define VDD_CALIB ((uint16_t) (300))
#define VDD_APPLI ((uint16_t) (330))

int32_t temperature_in_C;
uint16_t temperature_ADC_value;
int32_t temp130_cal_value;
int32_t temp30_cal_value;

int32_t ComputeTemperature(uint32_t measure)
{
    int32_t temperature;
    temperature = ((measure * VDD_APPLI / VDD_CALIB) - (int32_t) *TEMP30_CAL_ADDR );
    temperature = temperature * (int32_t)(130 - 30);
    temperature = temperature / (int32_t)(*TEMP130_CAL_ADDR - *TEMP30_CAL_ADDR);
    temperature = temperature + 30;
    return(temperature);
}

void ADC_Init()
{
    RCC->APB2ENR |= RCC_APB2ENR_ADCEN;      /* Enable ADC clock */

    ADC1->CFGR2 |= ADC_CFGR2_CKMODE_0
                |  ADC_CFGR2_CKMODE_1;      /* ADC Clock = PCLK (2.097MHz) */
    ADC->CCR |= ADC_CCR_LFMEN;              /* Enable if ADC Clock Freq < 3.5MHz */C
    ADC1->CFGR1 |= ADC_CFGR1_CONT;          /* Continous conversions */
    ADC1->CHSELR = ADC_CHSELR_CHSEL18;      /* Channel 18 - Temperature sensor */
    ADC1->SMPR |= ADC_SMPR_SMP;             /* Sampling time - 160.5 ADC cycles */
    ADC->CCR |= ADC_CCR_TSEN;               /* Enable temperature sensor */

    ADC1->ISR |= ADC_ISR_ADRDY;             /* Clearing bit ADRDY (ADC ready) */
    ADC1->CR |= ADC_CR_ADEN;                /* Enable ADC */
    while((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* Wait for turn on */
        ;
    ADC1->CR |= ADC_CR_ADSTART;             /* Start */
}

int main(void)
{
    ADC_Init();

    while (1)
    {
      for(int i = 0; i < 10000; i++) /* Delay */
          ;

      temperature_ADC_value = ADC1->DR;                 /* Debug */
      Temp130_cal_value = (int32_t)(*TEMP130_CAL_ADDR); /* Debug */
      Temp30_cal_value = (int32_t)(*TEMP30_CAL_ADDR);   /* Debug */

      temperature_in_C = ComputeTemperature(temperature_ADC_value);
    }
    return 0;
}

Data from the debugger

Best Answer

The solution is very simple, I was hinted at in the ST forum. It lacks ADC calibration. After adding the missing code, the reading is 30C, which means it's the expected one.