目录
1. 什么是温度传感器
2. 温度传感器简介
3. 库函数配置内部温度传感器
4. 实验程序
4.1 main.c
4.2 ADC.c
4.3 ADC.h
1. 什么是温度传感器
温度传感器是一种测量物体冷热程度的设备,以可读的方式通过电信号提供温度测量。比较常见的如热电偶温度传感器。
在实际应用中,温度传感器根据类型不同又可以分为接触式温度传感器和非接触式温度传感器。
接触式温度传感器显然需要与被感测对象进行物理上的接触,由此进行温度上的传导,并且以此来检测温度变化。这种接触方式下的传感器可以在很宽的温度范围内检测固体、液体和气体。
非接触式温度传感器显然不需要物理意义上的接触,这种温度传感器使用对流和辐射来监测温度变化。可用于检测液体和气体。其实质是根据这些液体和气体在热和冷的对流中沉降到底部而发射辐射能,或者检测以红外辐射(太阳)形式从物体上传输的辐射能。
2. 温度传感器简介
温度传感器可用于测量CPU及器件的环境温度()。
对于STM32F4xx器件,温度传感器内部连接到ADC1_IN16通道,ADC1用于将传感器的输入电压转换为数字值。在不使用的时候可以将传感器置于掉电模式。
主要特性:
- 支持感应的温度范围:-40℃到125℃
- 精度:1.5℃
是至ADC1_IN16的输入。
读取温度:
- 选择ADC1_IN16输入通道。
- 选择一个采样时间,该采样时间需要大于17.1us。(17.1us是数据手册设置的最低采样时间)
- 在ADC_CCR寄存器中将TSVREFE位置1,以便将温度传感器从掉电模式中唤醒。
- 通过将SWSTART位置1(软件触发)或者通过外部触发开始ADC转换。
- 读取ADC_DR数据寄存器中生成的数据。
- 使用相应的公式去计算温度:
温度 ℃={(-)/Avg_Slope}+25
其中等于25℃时的值(典型数值:0.76)
Avg_Slope等于温度与曲线的平均斜率(典型值:2.5Mv/℃) 斜率可以通过下图计算出来
注意:
- 传感器从掉电模式中唤醒需要一个启动时间,启动时间过后其才能正确输出。ADC在上电过后同样需要一个启动时间,因此,为尽可能的减少延迟时间,应该同时将ADON位(开始ADC)和TSVREFE(从掉电模式中唤醒的标志位)位置1。
- 是使用STM32F4的内部温度传感器,必须先激活ADC的内部通道,通过ADC_CCR寄存器进行软件操作将相应位置1即可。
3. 库函数配置内部温度传感器
1. 设置ADC1,开启内部温度传感器
我们已经学习过了ADC1的设置方法,在设置ADC1的代码基础上加上使能内部温度传感器函数即可。
ADC_TempSensorVrefintCmd(ENABLE); //使能内部温度传感器
2. 读取通道16的AD值,计算结果
因为温度传感器是接在ADC1_IN16上的,所以需要读取通道16的传感器电压值,用公式计算出温度值即可。
4. 实验程序
4.1 main.c
#include "stm32f4xx.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"
#include "lcd.h"
#include "usmart.h"
#include "Key.h"
#include "ADC.h"
//LCD状态设置函数
void led_set(u8 sta)//只要工程目录下有usmart调试函数,主函数就必须调用这两个函数
{
LED1=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
led_set(sta);
}
int main(void)
{
short temp;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
uart_init(115200);
LED_Init();
LCD_Init();
Adc_Init();
POINT_COLOR=RED;
LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");
LCD_ShowString(30,70,200,16,16,"ADC TEST");
LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,110,200,16,16,"2023/20/23");
POINT_COLOR=BLUE;
LCD_ShowString(30,130,200,16,16,"Temperature: 00.00C");//固定温度的小数点
while(1)
{
temp=Get_Temperature();//获取温度值
//同51单片机一样,需要判断温度是否小于0,如果小于0,需要在温度前面打印出负号
if(temp<0)
{
temp=-temp;//把负的温度前的符号去掉,人为通过ShowString打印出负号
LCD_ShowString(30+12*8,130,200,16,16,"-");
}
else //否则表示此时的温度在正数
{
LCD_ShowString(30+12*8,130,200,16,16," ");//无符号
}
LCD_ShowxNum(30+13*8,130,temp/100,2,16,0);//显示整数部分 /除打印出整数因此拿出来的是整数部分
LCD_ShowxNum(30+16*8,130,temp%100,2,16,0);//显示小数部分 %取余打印出的是小数部分
LED0=!LED0;
delay_ms(250);
}
}
4.2 ADC.c
#include "stm32f4xx.h"
#include "ADC.h"
#include "delay.h"
//初始化ADC
void Adc_Init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);//使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);// 使能ADC1时钟
//初始化ADC1通道5 IO口
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AN; //模式为模拟输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5; //PA5 通道5
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //不带上下拉
GPIO_Init(GPIOA,&GPIO_InitStructure);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,ENABLE); //ADC1复位
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1,DISABLE); //复位结束
ADC_TempSensorVrefintCmd(ENABLE);//使能内部温度传感器
//初始化CCR通用控制寄存器配置
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_CommonInitStructure.ADC_DMAAccessMode=ADC_DMAAccessMode_Disabled; //DMA失能
ADC_CommonInitStructure.ADC_Mode=ADC_Mode_Independent; //独立模式
ADC_CommonInitStructure.ADC_Prescaler=ADC_Prescaler_Div4; //预分频值设置
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;//两个采样阶段之间延迟5个时钟
ADC_CommonInit(&ADC_CommonInitStructure);
//初始化ADC1相关参数
ADC_InitTypeDef ADC_InitStructure;
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE; //关闭连续转换
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right; //右对齐
ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_None; //禁止触发检测,使用软件触发
ADC_InitStructure.ADC_NbrOfConversion=1; //1个转换在规则序列中
ADC_InitStructure.ADC_Resolution=ADC_Resolution_12b; //12位模式
ADC_InitStructure.ADC_ScanConvMode=DISABLE; //非扫描模式
ADC_Init(ADC1,&ADC_InitStructure); //ADC初始化
ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_480Cycles); //ADC5,ADC通道,480个周期
ADC_RegularChannelConfig(ADC1,ADC_Channel_16,1,ADC_SampleTime_480Cycles); //ADC16,ADC通道,480个周期
ADC_Cmd(ADC1,ENABLE); //开启AD转换器
}
//获取ADC值
//ch:通道值 0~16
//返回值:转换结果
u16 Get_Adc(u8 ch)
{
ADC_RegularChannelConfig(ADC1,ch,1,ADC_SampleTime_480Cycles);//设置ADC规则组通道,一个序列,采样时间480
ADC_SoftwareStartConv(ADC1);//使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));//读取状态寄存器的状态位EOC,等待转换结束
return ADC_GetConversionValue(ADC1);//返回最近一次的ADC1规则组的转换结果
}
//获取通道ch的转换值,取times次,然后平均
//ch:通道编号 times:获取次数
//返回值:通道ch的times次转换结果平均值
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val=temp_val+Get_Adc(ch); //取times次通道值进行求和
delay_ms(5);
}
return temp_val/times; //返回平均值
}
short Get_Temperature(void)
{
u32 adcx;
short result;
double Temperature;
adcx=Get_Adc_Average(ADC_Channel_16,20);
Temperature=(float)adcx*(3.3/4096); //计算传感器的电压值给到温度
Temperature=(Temperature-0.76)/0.0025+25; //通过公式计算出来的温度值
Temperature=Temperature*100; //扩大100倍
result=Temperature;
return result;
}
4.3 ADC.h
#ifndef _ADC__H_
#define _ADC__H_
void Adc_Init(void);
u16 Get_Adc(u8 ch);
u16 Get_Adc_Average(u8 ch,u8 times);
short Get_Temperature(void);
#endif