Internal temperature sensor experiment

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

1. To use the internal temperature sensor of STM32, we must first activate the internal channel of ADC, which is set by the TSVREFE bit (bit23) of ADC_CR2.Set this bit as an internal temperature sensor enabled.

 

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

Turn on the internal temperature sensor step:
1. Select the ADC_IN16 input channel.
(2) Setting sampling time greater than 17.1us
(3) Set the TSVREFE bit of ADC_CR2 and turn on the internal temperature sensor
(4) Setting ADON bit to start conversion
Read ADC results
Calculation.
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);
	}										    
}	

 

67 original articles were published. 5. 10,000 visits+
Private letter follow

Posted by jfeather on Wed, 04 Mar 2020 17:30:50 -0800