您现在的位置是:首页 >技术交流 >【正点原子STM32连载】 第三十一章 内部温度传感器实验摘自【正点原子】STM32F103 战舰开发指南V1.2网站首页技术交流
【正点原子STM32连载】 第三十一章 内部温度传感器实验摘自【正点原子】STM32F103 战舰开发指南V1.2
1)实验平台:正点原子stm32f103战舰开发板V4
2)平台购买地址:https://detail.tmall.com/item.htm?id=609294757420
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html
第三十一章 内部温度传感器实验
本章,我们将介绍STM32F103的内部温度传感器并使用它来读取温度值,然后在LCD模块上显示出来。
本章分为如下几个小节:
31.1 内部温度传感器简介
31.2 硬件设计
31.3 程序设计
31.4 下载验证
31.1 内部温度传感器简介
STM32有一个内部的温度传感器,可以用来测量CPU及周围的温度(内部温度传感器更适合于检测温度的变化,需要测量精确温度的情况下,应使用外置传感器)。对于STM32F103来说,该温度传感器在内部和ADC1_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值。温度传感器模拟输入推荐采样时间是17.1us。STM32F103内部温度传感器支持的温度范围为:-40~125度。精度为±1.5℃左右。
STM32内部温度传感器的使用很简单,只要设置一下内部ADC,并激活其内部温度传感器通道就差不多了。关于ADC的设置,我们在上一章已经进行了详细的介绍,这里就不再多说。接下来我们介绍一下和温度传感器设置相关的两个地方。
第一个地方,我们要使用STM32的内部温度传感器,必须先激活ADC的内部通道,这里通过ADC_CR2的AWDEN位(bit23)设置。设置该位为1则启用内部温度传感器。
第二个地方,STM32的内部温度传感器固定的连接在ADC1的通道16上,所以,我们在设置好ADC1之后只要读取通道16的值,就是温度传感器返回来的电压值了。根据这个值,我们就可以计算出当前温度。计算公式如下:
{ (V25-Vsense) / Avg_Slope}+25
式子中:
V25 = Vsense 在25度时的数值(典型值为:1.43)
Avg_Slope = 温度与Vsense曲线的平均斜率(单位:mv/℃或uv/℃)(典型值:4.3mv/℃)。
利用以上公式,我们就可以方便的计算出当前温度传感器的温度了。
31.2 硬件设计
- 例程功能
通过ADC的通道16读取STM32F103内部温度传感器的电压值,并将其转换为温度值,显示在TFTLCD屏上。LED0闪烁用于提示程序正在运行。 - 硬件资源
1)LED灯
LED0 – PB5
2)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面)
3)正点原子 2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动)
4)ADC1 通道16
5)内部温度传感器 - 原理图
ADC和内部温度传感器都属于STM32F103内部资源,实际上我们只需要软件设置就可以正常工作,我们需要用到TFTLCD模块显示结果。
31.3 程序设计
31.3.1 ADC的HAL库驱动
本实验用到的ADC的HAL库API函数前面都介绍过,具体调用情况请看程序解析部分。下面介绍读取内部温度传感器ADC值的配置步骤。
读取STM32内部温度传感器ADC值的配置步骤
1)开启ADC时钟
通过__HAL_RCC_ADC1_CLK_ENABLE函数开启ADC1的时钟。
2)设置ADC,开启内部温度传感器
调用HAL_ADC_Init函数来设置ADC1时钟分频系数、分辨率、模式、扫描方式等参数。
注意:该函数会调用:HAL_ADC_MspInit回调函数来完成对ADC底层的初始化,包括:ADC1时钟使能、ADC1时钟源的选择等。
3)配置ADC通道并启动AD转换器
调用HAL_ADC_ConfigChannel()函数配置ADC1通道16,根据需求设置通道、规则序列、采样时间等。然后通过HAL_ADC_Start函数启动AD转换器。
4)读取ADC值,计算温度。
这里选择查询方式读取,在读取ADC值之前需要调用HAL_ADC_PollForConversion等待上一次转换结束。然后就可以通过HAL_ADC_GetValue来读取ADC值。最后根据上面介绍的公式计算出温度传感器的温度值。
31.3.2 程序流程图
图31.3.2.1 内部温度传感器实验程序流程图
31.3.3 程序解析
- adc驱动代码
这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。内部温度传感器驱动源码包括两个文件:adc.c和adc.h。本实验和ADC章节实验用的都是同一个adc.c和adc.h代码。
在adc.h头文件再加入温度传感器的相关宏定义,该宏定义如下:
/* ADC温度传感器通道 定义 */
#define ADC_TEMPSENSOR_CHX ADC_CHANNEL_16
ADC_CHANNEL_16就是ADC通道16连接内部温度传感器的通道16宏定义。我们在定义为ADC_TEMPSENSOR_CHX,可以让大家更容易理解这个宏定义的含义。
下面我们直接介绍与内部温度传感器相关的adc.c的程序,首先是ADC内部温度传感器初始化函数,其定义如下:
/**
* @brief ADC 内部温度传感器 初始化函数
* @note 本函数还是使用adc_init对ADC进行大部分配置,有差异的地方再单独配置
* 注意: STM32F103内部温度传感器只连接在ADC1的通道16上, 其他ADC无法进行转换.
*
* @param 无
* @retval 无
*/
void adc_temperature_init(void)
{
adc_init(); /* 先初始化ADC */
/* TSVREFE = 1, 启用内部温度传感器和Vrefint */
SET_BIT(g_adc_handle.Instance->CR2, ADC_CR2_TSVREFE);
}
该函数调用adc_init函数配置了ADC的基础功能参数,由于前面实验中的adc_init实验是对ADC_CHANNEL_1进行配置的,而我们对内部温度传感器的初始化步骤与普通ADC类似,为了不重复编写代码,我们用位操作函数进行修改ADC通道,把ADC_CR2的TSVREFE位置1,即SET_BIT(g_adc_handle.Instance->CR2, ADC_CR2_TSVREFE);这样子就可以完成对内部温度传感器通道的初始化工作。adc_init的实现代码,可以回顾以下ADC章节内容。
下面讲解一下获取内部温度传感器温度值函数,其定义如下:
/**
* @brief 获取内部温度传感器温度值
* @param 无
* @retval 温度值(扩大了100倍,单位:℃.)
*/
short adc_get_temperature(void)
{
uint32_t adcx;
short result;
double temperature;
/* 读取内部温度传感器通道,10次取平均 */
adcx = adc_get_result_average(ADC_TEMPSENSOR_CHX, 20);
temperature = (float)adcx * (3.3 / 4096); /* 转化为电压值 */
temperature = (1.43 - temperature) / 0.0043 + 25; /* 计算温度 */
result = temperature *= 100; /* 扩大100倍. */
return result;
}
该函数先是调用前面ADC实验章节写好的adc_get_result_average函数取获取通道ch的转换值,然后通过温度转换公式,返回温度值。
2. main.c代码
在main.c里面编写如下代码:
int main(void)
{
short temp;
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
adc_temperature_init(); /* 初始化ADC内部温度传感器采集 */
lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);
lcd_show_string(30, 70, 200, 16, 16, "Temperature TEST", RED);
lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);
lcd_show_string(30, 120, 200, 16, 16, "TEMPERATE: 00.00C", BLUE);
while (1)
{
temp = adc_get_temperature(); /* 得到温度值 */
if (temp < 0)
{
temp = -temp;
lcd_show_string(30 + 10 * 8, 120, 16, 16, 16, "-", BLUE);/* 显示负号 */
}
else
{
lcd_show_string(30 + 10 * 8, 120, 16, 16, 16, " ", BLUE); /* 无符号 */
}
lcd_show_xnum(30 + 11 * 8, 120,temp/100, 2, 16, 0, BLUE); /* 显示整数部分 */
lcd_show_xnum(30 + 14 * 8, 120,temp%100, 2, 16,0X80, BLUE);/* 显示小数部分 */
LED0_TOGGLE(); /* LED0闪烁,提示程序运行 */
delay_ms(250);
}
}
该部分的代码逻辑很简单,先是得到温度值,再根据温度值判断正负值,来显示温度符号,再显示整数和小数部分。
31.4 下载验证
将程序下载到开发板后,可以看到LED0不停的闪烁,提示程序已经在运行了。LCD显示的内容如图31.4.1所示:
图31.4.1 内部温度传感器实验测试图
大家可以看看你的温度值与实际是否相符合(因为芯片会发热,所以一般会比实际温度偏高)?