stm32学习笔记-利用ADC获取stm32内部温度传感器温度

一、温度传感器的简介

内置温度传感器特性

在这里插入图片描述
■ STM32有一个内部的温度传感器,可以用来测量CPU测量周围的温度(TA)。
■ STM32内部温度传感器与ADC的通道16相连,与ADC配合使用实现温度测量
■ 温度传感器模拟输入推荐采样时间是17.1μs。
■ STM32的内部温度传感器测量范围–40~125℃,精度 ± 1.5℃。

温度的计算

官方数据手册公式如下:
在这里插入图片描述
百度给出了V25和Avg_Slope的值:

最小经典最大
V251340mV1430mV1520mV
Avg_Slope(mV/°C)4.04.34.3
  • VSENSE 如何得到?
    我们得到的AD结果是ADC_DR这个变量,存在以下的比例关系:
    ADC_DR / VSENSE = 212 / 3300mV
    所以 VSENSE
    = ADC_DR * 3300mV / 212
    = ADC_DR* 3300/4096
    = ADC_DR* 825/1024
    = (ADC_DR*825)>>10
  • 例:读到VSENSE = 1. 35V,分别取V25的典型值1340mV和Avg_Slope 的经典值4.3,计算当前温度。
      由公式 T = (VSENSE -V25 )/Avg_Slope + 25
        得 T = (1430 - 1350)/4.3 + 25 = 43.60
      所以温度大约为43.6°C

二、编程

编程思路:

①初始化ADC
②设置ADC CR2的TSVREFE位,打开内部温度传感器
 ADC_TempSensorVrefintCmd(ENABLE);
③设置采样时间等于17.1us,配置规则通道参数:选择ADC_ IN16输入通道。
 ADC_RegularChannelConfig( );
④启动软件转换
 ADC_SoftwareStartConvCmd();
⑤等待转换结束并读取ADC_DR结果
 (u32)ADC_GetConversionValue(ADC1);
⑥由ADC_DR结果计算出温度值

代码:

adc.h

#ifndef ADC_H
#define ADC_H
#include "stm32f10x.h"
#include "bsp_systick.h"

#define		V25					1370
#define		Avg_Slope		4.35
void T_ADC_Configuration(void);
u32 Get_ADC_Average(u8 channel,u8 times);
float Get_InternalSensorTemperate(void);
#endif

adc.c

#include "adc.h"

void T_ADC_Configuration(void)
{
	ADC_InitTypeDef ADC_InitStructure; 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1	, ENABLE );	  //使能GPIOA,ADC1通道时钟
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //分频因子6时钟为72M/6=12MHz

  ADC_DeInit(ADC1);  //将外设 ADC1 的全部寄存器重设为缺省值
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;	//使能扫描
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;	//设置模数转换工作在连续转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器

	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	ADC_ResetCalibration(ADC1);	//重置指定的ADC1的复位寄存器
  while(ADC_GetResetCalibrationStatus(ADC1));	//获取ADC1重置校准寄存器的状态,设置状态则等待
	ADC_StartCalibration(ADC1);	 
	while(ADC_GetCalibrationStatus(ADC1));		//获取指定ADC1的校准程序,设置状态则等待
	
	ADC_TempSensorVrefintCmd(ENABLE); //开启内部温度传感器
}

/*******************************************************************
*函数:u8 Get_ADC_Average(u8 channel,u8 times) 
*功能:获取adc转换平均值
*输入:
	u8 channel, 通道号:ADC_Channel_0 ~ ADC_Channel_17
	u8 times,	获取次数
*输出:获取次数的平均值
*特殊说明:
*******************************************************************/
u32 Get_ADC_Average(u8 channel,u8 times)   
{	
	u32 convert_Result=0;
	u8 i;
	for(i=0;i<times;i++)
	{
		ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_55Cycles5 );	//ADC1,第一个转换,采样时间为28.5周期?  			    
		ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能
		while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
		convert_Result+=(u32)ADC_GetConversionValue(ADC1);//读取ADC_DR结果数据,此时EOC会自动清除
		SysTick_Delay_ms(5);
	}
	return convert_Result/times;
}

/*******************************************************************
*函数:u8 Get_InternalSensorTemperate(u8 channel,u8 times) 
*功能:获取adc转换平均值
*输入:
*输出:获取的温度值
*特殊说明:
*******************************************************************/
float Get_InternalSensorTemperate(void)	//获取内部温度传感器温度值
{
	int ADC_ConvertedValue;//用来存储ADC转换出来的值
 	float Current_Temp;
	
	ADC_ConvertedValue = (int)Get_ADC_Average(ADC_Channel_16,20);	//20次取平均
	ADC_ConvertedValue = (ADC_ConvertedValue*825)>>10;//换算成Vsensor
	Current_Temp = (((V25-ADC_ConvertedValue)/Avg_Slope)+25);	//计算温度值 	 
	return Current_Temp;
}

main.c

#include "stm32f10x.h"
#include "bsp_systick.h"
#include "usart.h"
#include "adc.h"

int main(void)
{
	usart1_Init(9600);
	printf("start!\n");
	
	T_ADC_Configuration();
	u32 adc_DRValue = 0 ;
	float temperature;
	
	while(1)
	{
		adc_DRValue = Get_ADC_Average(ADC_Channel_16,20);//指定ADC_Channel_1,获取ADC的值
		printf("adc_DRValue:%d\n",adc_DRValue);//通过串口打印获取ADC的值
		temperature=Get_InternalSensorTemperate();//转换ADC的值,得到具体的温度
		printf("temperature:%f\n",temperature);//通过串口打印获取电压的值
		SysTick_Delay_ms(1500);
	}
}

遇到的问题-数据类型问题

在这里插入图片描述
代码如下

float Get_Temperate(void)	//获取内部温度传感器温度值
{
	u32 ADC_ConvertedValue;//用来存储ADC转换出来的值,单位是mV
 	float Current_Temp;
	ADC_ConvertedValue = T_Get_ADC_Average(10);	//20次取平均
	ADC_ConvertedValue = (ADC_ConvertedValue*825)>>10;//(ADC_ConvertedValue*825)>>10 表示 ADC_ConvertedValue*3300/4096
	Current_Temp=(float)(((1370-ADC_ConvertedValue)/4.35)+25);	//转换为温度值 	 
	return Current_Temp;
}

思来想去,最后发现是数据类型的问题,因为ADC_ConvertedValue会得到负数。
ADC_ConvertedValue由u32改为int类型就得到正确结果。

float Get_Temperate(void)	//获取内部温度传感器温度值
{
	int ADC_ConvertedValue;//用来存储ADC转换出来的值,单位是mV
 	float Current_Temp;
	ADC_ConvertedValue = (int)T_Get_ADC_Average(20);	//20次取平均
	ADC_ConvertedValue = (ADC_ConvertedValue*825)>>10;//(ADC_ConvertedValue*825)>>10 表示 ADC_ConvertedValue*3300/4096
	Current_Temp = (((1370-ADC_ConvertedValue)/4.35)+25);	//转换为温度值 	 
	return Current_Temp;
}

在这里插入图片描述

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值