1
\$\begingroup\$

I am new to ARM world and using STM32F103C8T6 ARM microcontroller. I want to get micro's internal temperature sensor working. I am able to get some data from it but I'm not sure how to convert these numbers into temperature. I looked it up on and I found that there is two read-only addresses in memory that hold factory calibration numbers at 30 and 110 degrees.

The problem is there is nothing about it in either datasheet or Reference Manual. There is only some minimums and maximums for parameters. I believe using average of these values may affect accuracy. So I'm confused. How should I do this conversion? Do I even need these factory calibration data? Do I have to self calibrate the ADC in this case?

here is the code I used so far:

 #include "stm32f103xb.h"
 int main(void)
{

// Select a clock source for ADC


RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;     // Enable ADC1 to use APB2 BUS
RCC->CR |= RCC_CR_HSION;  // set the internal clock on (8MHz)
while((RCC->CR & RCC_CR_HSIRDY) == 0){}     // wait until HSI is ready

RCC->CFGR &= ~(RCC_CFGR_HPRE);  // set AHB prescaler to 1
RCC->CFGR &= ~(RCC_CFGR_PPRE2); // set APB2 prescaler to 1 (PCLK2)
RCC->CFGR |= RCC_CFGR_ADCPRE;   // use ADC prescaler

// Select a Sampling rate
ADC1->SMPR1 |= ADC_SMPR1_SMP16;
ADC1->SQR3 |= ADC_SQR3_SQ1_4; //set to convert the channel 16 fitst

// enable temperature sensor
ADC1->CR2 |= ADC_CR2_TSVREFE;

// ADC Calibration
// Power up the ADC and then Calibrate it
ADC1->CR2 |= ADC_CR2_ADON | ADC_CR2_CAL | ADC_CR2_CONT;
// wait until the calibration is completed and reseted
while((ADC1->CR2 & ADC_CR2_CAL) == 1){}


while(1)
{
    // Start 
    ADC1->CR2 |= ADC_CR2_ADON;
    while((ADC1->SR & ADC_SR_EOC) == 0){} // wait for end of conversion
    // Print the results on LCD
    LCDSendInstruction(LCD_CLEAR);
    LCDSendInteger(ADC1->DR,8);

}
}

Thanks in advance :D

\$\endgroup\$
  • \$\begingroup\$ "I looked it up on and I found that there is two read-only addresses in memory that hold factory calibration numbers at 30 and 110 degrees. " - where did you get this information? \$\endgroup\$ – Bruce Abbott Dec 28 '17 at 23:42
  • \$\begingroup\$ @BruceAbbott other STM32 Families have this numbers, stated in their datasheet. I looked it up and they use it for better results, check this \$\endgroup\$ – dub-dub Dec 29 '17 at 8:15
4
\$\begingroup\$

The STM32Cube library for your part includes one or two helper macros for calculating the temperature from an ADC reading of the internal temperature sensor. The User Manual for the HAL and Low-layer (LL) Drivers describes these macros. The implementation differs from one STM32 family to another so make sure you get the information for your particular part. Even if you're not going to use the STM32Cube library you can still refer to the source code for an example of how the temperature macros are implemented.

The two macros are __LL_ADC_CALC_TEMPERATURE and __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS.

Some STM32 parts have temperature calibration values that are measured during manufacturing of the device and programmed into ROM. These parts use the __LL_ADC_CALC_TEMPERATURE macro. This macro uses the ROM calibration values to improve the accuracy of the temperature measurement.

Other STM32 parts do not have temperature calibration values in ROM. These parts use the __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS macro. This macro uses the "typical" values for Avg_Slope and V25 taken from the device datasheet.

I believe the STM32F1 family does not have temperature calibration values in ROM so you would use __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS with the typical parameters from the device datasheet.

If you want to improve the temperature readings you could calibrate each of your units during production and store the custom calibration values for Avg_Slope and V25 in ROM. Then substitute your custom calibration values for the typical values from the datasheet.

\$\endgroup\$
2
\$\begingroup\$

If you are just looking some reference as to how to use the temperature sensor, this might help you! Pages 234 and 235 have what you are looking for!

Just to complete the answer, I am quoting the usage as described in the document

Reading the temperature

To use the sensor:

  1. Select the ADCx_IN16 input channel.
  2. Select a sample time of 17.1 µs
  3. Set the TSVREFE bit in the ADC control register 2 (ADC_CR2) to wake up the temperature sensor from power down mode.
  4. Start the ADC conversion by setting the ADON bit (or by external trigger).
  5. Read the resulting \$V_{SENSE}\$ data in the ADC data register
  6. Obtain the temperature using the following formula:

\$ Temperature (in °C) = {(V_{25} - V_{SENSE}) / Avg_{Slope}} + 25 \$

Where, \$V_{25} = V_{SENSE}\$ value for 25° C and

Avg_Slope = Average Slope for curve between Temperature vs. VSENSE (given in mV/° C or µV/ °C).

Finally, beware of the effect on the accuracy of readings because of the heat generated by the processor itself!

EDIT: The constants have a range because they are affected by the heat variations in the processor itself. So, if you are looking for very accurate results you better use an external sensor. Or you have to empirically calculate the processor temperature variations with respect to the temperature sensor. I don't think any data is available related to this and note that the above formula is just a linear approximation.

\$\endgroup\$
  • \$\begingroup\$ I've read this, but the problem is constants in this formula have a range (specified in datasheet) not a unique number. How can I be determine these constants accurately?? \$\endgroup\$ – dub-dub Dec 29 '17 at 8:18
  • \$\begingroup\$ @dub-dub You would use the typical values from the datasheet. If that's not good enough then you should perform a custom calibration of each unit during manufacturing and store the custom values in ROM. \$\endgroup\$ – kkrambo Dec 29 '17 at 15:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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