cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103C8 ADC internal temperature read way too high.

AAnth.1
Senior

Hi

Using the STM32F103C8 with STM32CubeIDE and bare metal programming, I am trying to read the internal temperature. While I manage to read the ADC, enter the ADC ISR and do the calculation to get the temperature, the result is unrealistic. The data register value is around 1600, which seems to be way too high. The resulting calculation to get the temperature in degC is then around 400degC.

Does anyone see a big issue in my setup?

Thank you,

/**
 * STM32F103C8 ADC
 * Uses ADC1
 * Reads the temperature from the internal temp sensor
 */
 
#include <stdint.h>
#include "stm32f1xx.h"
 
#define AVG_SLOPE	4.3	// mV per C
#define V25			1.43	// V
 
int main(void)
{
	__NVIC_EnableIRQ(ADC1_2_IRQn);
 
	// Setup of ADC1
	uint8_t i = 0;
	RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
	for(;i<255;i++);
	i=0;
	ADC1->CR1 |= ADC_CR1_EOSIE;
 
 
	ADC1->CR2 |= ADC_CR2_ADON | ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTTRIG | ADC_CR2_TSVREFE;
	ADC1->SMPR1 |= ADC_SMPR1_SMP16;
	ADC1->SQR3 |= 16;
 
	// Setup of TIM2
	RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
	for(;i<255;i++);
	i=0;
	GPIOA->CRL |= GPIO_CRL_MODE1_1 | GPIO_CRL_CNF1_1;
 
	// Enables TIM2 bus
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	for(;i<255;i++);
	i=0;
	TIM2->CR1 |= TIM_CR1_ARPE | TIM_CR1_URS;
	TIM2->DIER |= TIM_DIER_UIE;
	TIM2->PSC = 7999;
	TIM2->ARR = 1000;
	TIM2->CCMR1 |= TIM_CCMR1_OC2PE | TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2;
	TIM2->EGR |= TIM_EGR_CC2G;
	TIM2->CCER |= TIM_CCER_CC2E;
	TIM2->CCR2 = 500;
 
	TIM2->CR1 |= TIM_CR1_CEN;
 
    /* Loop forever */
	for(;;);
}
 
void ADC1_2_IRQHandler(void)
{
		// Handles the IRQ of ADC1. EOC flag is cleared by reading data register
		static uint32_t temp = 0;
		static uint32_t temp_sensor = 0;
		temp = ADC1->DR;
		temp_sensor = (temp-V25)/(AVG_SLOPE)+25;
		(void)temp_sensor;
}

6 REPLIES 6

Do you perform calibration as outlined in the Calibration subchapter of ADC chapter in RM0008?

Do you observe the startup time and sampling time given in Temperature sensor characteristics chapter of the datasheet?

What is your hardware? Are VREF+/VDDA and all grounds properly connected? Isn't this a bluepill?

JW

AAnth.1
Senior

Hi JW

1) I added the calibration to the code after my initial post to ensure that the missing calibration is not the root cause of the wrong result. It did affect the result only slightly, but I'm still way off.

2) I am not quite sure how I can observe the sampling time. The datasheet says 17.1us for the temp sensor. With an internal RC of 8MHz, the ADC clock runs at 8MHz as well. Doing the math, I end up needing 17.1us*8MHz = 137 clock cycles. My current setting is 111 : 239.5us as per ref manual. The next lower value would be 110: 71.5us which is below the temp sensor recommended sampling time. So I hope I am safe with my setting. Also, these bits are set as they should in the

3) It is not the blue pill per se, but kind of. I purchased the board from robotdyn a while ago hoping to have a genuine MCU. I am using the 48pin package version of the MCU, where VREF+ and VREF- are not available on a pin. So it's all internal, which is why I was hoping for a coding mistake.

https://robotdyn.com/catalog/stm32f103-stm32-arm-mini-system-dev-board-stm-firmware-stm32f103c8t6-64kb-soldered.html

Thanks mate,

TDK
Guru

> #define AVG_SLOPE 4.3 // mV per C

> #define V25 1.43 // V

> ...

> temp = ADC1->DR;

> temp_sensor = (temp-V25)/(AVG_SLOPE)+25;

This isn't right. "temp" is a raw ADC value and the other two are voltages (floating point). You should convert temp to a voltage first in order to use this equation. Something like:

> temp_sensor = (temp*3.3/4095-V25)/(AVG_SLOPE)+25;

If you feel a post has answered your question, please click "Accept as Solution".
AAnth.1
Senior

Thank you, TDK. Now it seems to be more correct. I should also add, that AVG_SLOPE actually has mV/degC. So the correct equation should include a factor of 1000 to account for the correct units.

temp_sensor = (temp*3.3/4095-V25)/(AVG_SLOPE)*1000+25;

Thank you both for your inputs. I believe I am now on track again.

PS:

Now that I have this thread already created, one should mention that I used floating point math for the sake of simplicity, though the correct way would probably to implement fixed point math.

MFend
Associate III

I'm working on STM32L451 - and the code that i inherited seems to have

#define INTERNAL_TEMPSENSOR_V25        ((int32_t)741)          /* Internal temperature sensor, parameter V25 (unit: mV). Refer to device datasheet for min/typ/max values. */
#define INTERNAL_TEMPSENSOR_AVGSLOPE   ((int32_t)4300)         /* Internal temperature sensor, parameter Avg_Slope (unit: uV/DegCelsius). Refer to device datasheet for min/typ/max values. */

I'm trying to find a reference in the data sheet for the correct values.

I also try to calculate the temperature using the calibration values found in the following addresses (from data sheet):

#define TEMP30_CAL_ADDR  (*((uint16_t*)0x1FFF75A8))
#define TEMP130_CAL_ADDR (*((uint16_t*)0x1FFF75CA))

Looking in memory, these values are 0x0673 and 0xFFFF.

Neither of these calculations are giving me correct values.

The raw ADC values are in the range of 939-947.

Can you please help with the calculations?

First, dnt hijack threads. Start a new thread, restating the problem, pointing to this thread.

> I'm trying to find a reference in the data sheet for the correct values.

Temperature sensor characteristics subchapter. Your value for slope appers to be incorrect., though.

The FFFF value for TS_CAL2 is nicorrect, too. Check, if that address matches addresses in other models of the 'L4 family.

JW