Internal temperature sensor block diagram
-
STM32 has an internal temperature sensor that can be used to measure the CPU and surrounding temperature (TA).
-
The temperature sensor is connected internally to the ADCx_IN16 input channel, which converts the output voltage of the sensor to a digital value.
-
The recommended sampling time for temperature sensor analog input is 17.1 mus.
-
The internal temperature sensor of STM32 supports temperatures ranging from -40 to 125 degrees.The accuracy is poor, about (+) 1.5 C.
Internal temperature sensors are better suited to detect temperature changes than absolute temperatures.If extreme temperature needs to be measured, an external temperature sensor should be used.
Correspondence between ADC channel and pin of STM32F10x series chips
Cautions for use of internal temperature sensor

2. The internal temperature sensor of STM32 is fixed on channel 16 of ADC, so as long as we read the value of channel 16 after setting up ADC, it will be the voltage value returned by the temperature sensor.
From this value, we can calculate the current temperature.The formula is as follows:
T(℃)={(V25-Vsense)/Avg_Slope}+25
Top Form:
V25=Vsense at 25 degrees (typical value: 1.43).
Avg_Slope=the average slope of temperature versus Vsense curve (in mv/C or uv/C) (typical value is 4.3Mv/C).
With the above formula, we can easily calculate the temperature of the current temperature sensor.
Temperature and Voltage Diagram of Internal Temperature Sensor
void Adc_Init(void) { ADC_InitTypeDef ADC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //Enable ADC1 channel clock RCC_ADCCLKConfig(RCC_PCLK2_Div6); //Set ADC frequency dividing factor 6 72M/6=12,ADC maximum time cannot exceed 14M //PA1 as Analog Channel Input Pin GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //Analog input pin GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_DeInit(ADC1); //Reset ADC1, reset all registers of peripheral ADC1 to default values ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC working mode: ADC1 and ADC2 working in stand-alone mode ADC_InitStructure.ADC_ScanConvMode = DISABLE; //A/D conversion works in single channel mode ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //A/D conversion works in single conversion mode ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //Conversion is initiated by software rather than external triggers ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC Data Right Alignment ADC_InitStructure.ADC_NbrOfChannel = 1; //Number of ADC channels ordered for rule conversion ADC_Init(ADC1, &ADC_InitStructure); //Initialize registers for peripheral ADCx based on parameters specified in ADC_InitStruct ADC_Cmd(ADC1, ENABLE); //Enables the specified ADC1 ADC_ResetCalibration(ADC1); //Enable reset calibration while(ADC_GetResetCalibrationStatus(ADC1)); //Waiting for Reset Calibration to End ADC_StartCalibration(ADC1); //Turn on AD calibration while(ADC_GetCalibrationStatus(ADC1)); //Waiting for calibration to end // ADC_SoftwareStartConvCmd(ADC1, ENABLE); //Enables the specified software conversion startup function for ADC1 } //Get ADC value //ch:Channel value 0~3 u16 Get_Adc(u8 ch) { //Set the rule group channel, a sequence, sampling time for the specified ADC ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC channel, sampling time 239.5 cycles ADC_SoftwareStartConvCmd(ADC1, ENABLE); //Enables specified ADC1 software conversion startup functions while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//Waiting for conversion to end return ADC_GetConversionValue(ADC1); //Returns the result of the last ADC1 rule group conversion } u16 Get_Adc_Average(u8 ch,u8 times) { u32 temp_val=0; u8 t; for(t=0;t<times;t++) { temp_val+=Get_Adc(ch); delay_ms(5); } return temp_val/times; }
void T_Adc_Init(void) //ADC Channel Initialization { ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1 , ENABLE ); //Enable GPIOA,ADC1 channel clock RCC_ADCCLKConfig(RCC_PCLK2_Div6); //The crossover factor 6 clock is 72M/6=12MHz ADC_DeInit(ADC1); //Reset all registers of peripheral ADC1 to default values ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC working mode: ADC1 and ADC2 working in stand-alone mode ADC_InitStructure.ADC_ScanConvMode = DISABLE; //A/D conversion works in single channel mode ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //A/D conversion works in single conversion mode ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //Conversion is initiated by software rather than external triggers ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC Data Right Alignment ADC_InitStructure.ADC_NbrOfChannel = 1; //Number of ADC channels ordered for rule conversion ADC_Init(ADC1, &ADC_InitStructure); //Initialize registers for peripheral ADCx based on parameters specified in ADC_InitStruct ADC_TempSensorVrefintCmd(ENABLE); //Turn on the internal temperature sensor ADC_Cmd(ADC1, ENABLE); //Enables the specified ADC1 ADC_ResetCalibration(ADC1); //Reset the reset register of the specified ADC1 while(ADC_GetResetCalibrationStatus(ADC1)); //Gets the status of the ADC1 reset calibration register, and the setting status waits ADC_StartCalibration(ADC1); // while(ADC_GetCalibrationStatus(ADC1)); //Gets the calibrator for the specified ADC1, and the setting state waits } u16 T_Get_Adc(u8 ch) { ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC channel 3, first conversion, sampling time 239.5 cycles ADC_SoftwareStartConvCmd(ADC1, ENABLE); //Enables specified ADC1 software conversion startup functions while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//Waiting for conversion to end return ADC_GetConversionValue(ADC1); //Returns the result of the last ADC1 rule group conversion } //Get the value of ADC sampling internal temperature sensor //Take 10 times, then average u16 T_Get_Temp(void) { u16 temp_val=0; u8 t; for(t=0;t<10;t++) { temp_val+=T_Get_Adc(ADC_Channel_16); //TampSensor delay_ms(5); } return temp_val/10; } //Get the conversion value of channel ch //Take times, then average u16 T_Get_Adc_Average(u8 ch,u8 times) { u32 temp_val=0; u8 t; for(t=0;t<times;t++) { temp_val+=T_Get_Adc(ch); delay_ms(5); } return temp_val/times; }
#define ADC_CH_TEMP, ADC_Channel_16//Temperature Sensor Channel u16 T_Get_Temp(void); //Get the temperature value void T_Adc_Init(void); //ADC Channel Initialization u16 T_Get_Adc(u8 ch); //Get a channel value u16 T_Get_Adc_Average(u8 ch,u8 times);//Get the average of 10 samples for a channel #endif
int main(void) { u16 adcx; float temp; float temperate; delay_init(); //Delay function initialization uart_init(9600); //Serial port initialized to 9600 LED_Init(); //Initialize the hardware interface to connect to the LED LCD_Init(); T_Adc_Init(); //ADC Initialization POINT_COLOR=RED;//Set font to red LCD_ShowString(60,50,200,16,16,"Mini STM32"); LCD_ShowString(60,70,200,16,16,"Temperature TEST"); LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(60,110,200,16,16,"2014/3/9"); //Show prompt information POINT_COLOR=BLUE;//Set font to blue LCD_ShowString(60,130,200,16,16,"TEMP_VAL:"); LCD_ShowString(60,150,200,16,16,"TEMP_VOL:0.000V"); LCD_ShowString(60,170,200,16,16,"TEMPERATE:00.00C"); while(1) { adcx=T_Get_Adc_Average(ADC_CH_TEMP,10); LCD_ShowxNum(132,130,adcx,4,16,0);//Display the value of ADC temp=(float)adcx*(3.3/4096); temperate=temp;//Preserve the voltage value of the temperature sensor adcx=temp; LCD_ShowxNum(132,150,adcx,1,16,0); //Display Voltage Value Integer Part temp-=(u8)temp; //Minus the integer part LCD_ShowxNum(148,150,temp*1000,3,16,0X80); //Display Voltage Decimal Part temperate=(1.43-temperate)/0.0043+25; //Calculate the current temperature value LCD_ShowxNum(140,170,(u8)temperate,2,16,0); //Display temperature integer part temperate-=(u8)temperate; LCD_ShowxNum(164,170,temperate*100,2,16,0X80);//Show temperature decimal part LED0=!LED0; delay_ms(250); } }