1
\$\begingroup\$

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

\$\endgroup\$
10
  • \$\begingroup\$ What sensor? What circuit? \$\endgroup\$
    – Andy aka
    Jan 19, 2020 at 11:35
  • \$\begingroup\$ @Andyaka Sorry, I forgot to add this important information - it's an internal MCU temperature sensor \$\endgroup\$
    – Piotr
    Jan 19, 2020 at 11:47
  • \$\begingroup\$ An internal running temperature of 55 doesn’t sound excessive at all. \$\endgroup\$
    – Andy aka
    Jan 19, 2020 at 11:53
  • \$\begingroup\$ @Andyaka Comparing the temperature calculated by me with the one calculated by others, whose topics I read, my is still too high. Moreover, my MCU is not connected to any current consuming device, the only thing it does is take an ADC measurement and convert its value to temperature in C degrees, so it should not get so hot. \$\endgroup\$
    – Piotr
    Jan 19, 2020 at 12:06
  • 1
    \$\begingroup\$ The formula is right, so for some reason if the temperature is not 55, then the ADC gives you false readings. Double check that internal reference and temperature sensor are enabled. Then double check that the converted channel is correct, and that the result alignment and bitness is correct. Even if the sampling time is longest possible, I would not hammer the temp sensor with continuous readings, so try single reads, sample maybe once per second. The delay loop is not very long, and it might be optimized out by the compiler. \$\endgroup\$
    – Justme
    Jan 19, 2020 at 14:21

1 Answer 1

1
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.