1)实验平台:正点原子MiniPro H750开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=677017430560 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-336836-1-1.html 4)对正点原子STM32感兴趣的同学可以加群讨论:879133275
第三十二章 内部温度传感器实验本章,我们将介绍STM32H750的内部温度传感器并使用它来读取温度值,然后在LCD模块上显示出来。 本章分为如下几个小节: 32.1 内部温度传感器简介 32.2 硬件设计 32.3 程序设计 32.4 下载验证
32.1 内部温度传感器简介 STM32H750有一个内部的温度传感器,可以用来测量CPU及周围的温度(TA)。对于STM32H7系列来说,该温度传感器在内部和ADC3_INP18输入通道相连接,此通道把传感器输出的电压转换成数字值。 STM32H750的内部温度传感器支持的温度范围为:-40~125度。精度为±3℃左右。 STM32H750内部温度传感器的使用很简单,只要设置一下内部ADC,并激活其内部温度传感器通道就差不多了。关于ADC的设置,我们在上一章已经进行了详细的介绍,这里就不再多说。接下来我们介绍一下和温度传感器设置相关的两个地方。 第一个地方,我们要使用STM32H750的内部温度传感器,必须先激活ADC的内部通道,这里通过ADC3_COMMON_CCR的VSENSEEN位(bit23)设置。设置该位为1则启用内部温度传感器。 第二个地方,STM32H750的内部温度传感器固定的连接在ADC3的通道18上,所以,我们在设置好ADC3之后只要读取通道18的值,就是温度传感器返回来的电压值了。根据这个值,我们就可以计算出当前温度。计算公式如下:
×(TS_DATA - TS_CAL1)+30
上式中: TS_CAL1 是温度传感器在30℃时的校准值,固定保存在芯片内部的:0X1FF1 E820 ~ 0X1FF1 E821这两个地址(16位)。 TS_CAL2 是温度传感器在110℃时的校准值,固定保存在芯片内部的:0X1FF1 E840 ~ 0X1FF1 E841这两个地址(16位)。 TS_DATA:ADC3通道18读取到的当前温度传感器转换值。 利用以上公式,我们就可以方便的计算出当前温度传感器的温度了。 32.2 硬件设计
- 例程功能 通过ADC3的通道18读取STM32H7内部温度传感器的电压值,并将其转换为温度值,显示在TFTLCD屏上。LED0闪烁用于提示程序正在运行。
- 硬件资源 1)RGB灯 RED : LED0 - PB4 2)串口1(PA9/PA10连接在板载USB转串口芯片CH340上面) 3)正点原子2.8/3.5/4.3/7/10寸TFTLCD模块(仅限MCU屏,16位8080并口驱动) 4)ADC3 通道18 5)内部温度传感器 32.3 程序设计 32.3.1 ADC的HAL库驱动 本实验用到的ADC的HAL库API函数前面都介绍过,具体调用情况请看程序解析部分。下面介绍读取内部温度传感器ADC值的配置步骤。 读取内部温度传感器ADC值配置步骤 1)开启ADC时钟 通过__HAL_RCC_ADC3_CLK_ENABLE函数开启ADC3的时钟。 2)设置ADC3,开启内部温度传感器 调用HAL_ADC_Init函数来设置ADC3时钟分频系数、分辨率、模式、扫描方式、对齐方式等信息。 注意:该函数会调用:HAL_ADC_MspInit回调函数来完成对ADC底层的初始化,包括:ADC3时钟使能、ADC3时钟源的选择等。 3)配置ADC通道并启动AD转换器 调用HAL_ADC_ConfigChannel()函数配置ADC3通道18,根据需求设置通道、序列、采样时间和校准配置单端输入模式或差分输入模式等。然后通过HAL_ADC_Start函数启动AD转换器。 4)读取ADC值,计算温度 这里选择查询方式读取,在读取ADC值之前需要调用HAL_ADC_PollForConversion等待上一次转换结束。然后就可以通过HAL_ADC_GetValue来读取ADC值。最后根据上面介绍的公式计算出温度传感器的温度值。 32.3.2 程序流程图
图32.3.2.1 内部温度传感器实验程序流程图 32.3.3 程序解析
- adc3驱动代码 这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。ADC3驱动源码包括两个文件:adc3.c和adc3.h。 adc3.h头文件只有一个宏定义和一些函数的声明,该宏定义如下:
#define ADC3_TEMPSENSOR_CHX ADC_CHANNEL_TEMPSENSOR
ADC_CHANNEL_TEMPSENSOR就是ADC3通道18连接内部温度传感器的通道18宏定义。我们在定义为ADC3_TEMPSENSOR_CHX,可以让大家更容易理解这个宏定义的含义。
下面我们直接介绍adc3.c的程序,首先是ADC3初始化函数,其定义如下:
/**
* @brief ADC3初始化函数
* @note 本函数专用于支持ADC3, 和ADC1/2区分开来, 方便使用
* 我们使用16位精度, ADC采样时钟=32M, 转换时间为:采样周期 + 8.5个ADC周期
* 设置最大采样周期: 810.5, 则转换时间 = 819个ADC周期 = 25.6us
* @param 无
* @retval 无
*/
void adc3_init(void)
{
g_adc3_handle.Instance = ADC3; /* 选择哪个ADC */
/* 输入时钟2分频,即adc_ker_ck=per_ck/2=32Mhz */
g_adc3_handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
g_adc3_handle.Init.Resolution = ADC_RESOLUTION_16B; /* 16位模式 */
g_adc3_handle.Init.ScanConvMode = ADC_SCAN_DISABLE; /* 非扫描模式 */
g_adc3_handle.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* 关闭EOC中断 */
g_adc3_handle.Init.LowPowerAutoWait = DISABLE; /* 自动低功耗关闭 */
g_adc3_handle.Init.ContinuousConvMode = DISABLE; /* 关闭连续转换模式 */
g_adc3_handle.Init.NbrOfConversion = 1; /* 赋值范围是1~16,本实验用到1个通道 */
/* 禁止常规转换组不连续采样模式 */
g_adc3_handle.Init.DiscontinuousConvMode = DISABLE;
/* 配置不连续采样模式的通道数,禁止常规转换组不连续采样模式后,此参数忽略 */
g_adc3_handle.Init.NbrOfDiscConversion = 0;
g_adc3_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* 软件触发 */
/* 采用软件触发的话,此位忽略 */
g_adc3_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
/* 常规通道的数据仅仅保存在DR寄存器里面 */
g_adc3_handle.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
/* 有新的数据后直接覆盖掉旧数据 */
g_adc3_handle.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
/* 设置ADC转换结果的左移位数 */
g_adc3_handle.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
g_adc3_handle.Init.OversamplingMode = DISABLE; /* 关闭过采样 */
HAL_ADC_Init(&g_adc3_handle); /* 初始化 */
HAL_ADCEx_Calibration_Start(&g_adc3_handle, ADC_CALIB_OFFSET,
ADC_SINGLE_ENDED); /* ADC校准 */
}
该函数主要调用了两个HAL库函数,HAL_ADC_Init函数配置了选择哪个ADC、数据对齐方式、是否使用扫描模式等参数,HAL_ADCEx_Calibration_Start函数用于校准ADC。另外HAL_ADC_Init函数会调用它的MSP回调函数HAL_ADC_MspInit,该函数用来存放使能ADC和配置选择ADC时钟源等代码,其定义如下:
/**
* @brief ADC底层驱动,引脚配置,时钟使能
此函数会被HAL_ADC_Init()调用
* @param hadc:ADC句柄
* @retval 无
*/
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
RCC_PeriphCLKInitTypeDef rcc_periph_clk_struct = {0};
__HAL_RCC_ADC3_CLK_ENABLE(); /* 使能ADC3时钟 */
rcc_periph_clk_struct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
rcc_periph_clk_struct.AdcClockSelection = RCC_ADCCLKSOURCE_CLKP;
HAL_RCCEx_PeriphCLKConfig(&rcc_periph_clk_struct);
}
下面是获得ADC转换后的结果函数,其定义如下:
/**
* @brief 获得ADC转换后的结果
* @param ch: 通道号, ADC_CHANNEL_0~ADC_CHANNEL_19
* @retval 无
*/
uint32_t adc3_get_result(ADC_HandleTypeDef adc_handle, uint32_t ch)
{
ADC_ChannelConfTypeDef adc_ch_conf = {0};
adc_ch_conf.Channel = ch; /* 通道 */
adc_ch_conf.Rank = ADC_REGULAR_RANK_1; /* 序列 */
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_810CYCLES_5; /* 采样时间 */
adc_ch_conf.SingleDiff = ADC_SINGLE_ENDED; /* 单边采集 */
adc_ch_conf.OffsetNumber = ADC_OFFSET_NONE; /* 不使用偏移量的通道 */
adc_ch_conf.Offset=0; /* 偏移量为0 */
HAL_ADC_ConfigChannel(&adc_handle, &adc_ch_conf); /* 通道配置 */
HAL_ADC_Start(&adc_handle); /* 开启ADC */
HAL_ADC_PollForConversion(&adc_handle, 10); /* 轮询转换 */
return HAL_ADC_GetValue(&adc_handle); /* 返回最近一次ADC规则组的转换结果 */
}
该函数先调用HAL_ADC_ConfigChannel函数设置通道的转换序列和采样时间等,再调用HAL_ADC_Start函数开启ADC,接着调用HAL_ADC_PollForConversion函数等待转换完成,最后调用HAL_ADC_GetValue函数获取转换后的当前结果。 下面介绍的是获取ADC某通道的转换多次后的平均值函数,函数定义如下:
/**
* @brief 获取通道ch的转换值,取times次,然后平均
* @param ch : 通道号, 0~19
* @param times : 获取次数
* @retval 通道ch的times次转换结果平均值
*/
uint32_t adc3_get_result_average(ADC_HandleTypeDef adc_handle,
uint32_t ch, uint8_t times)
{
uint32_t temp_val = 0;
uint8_t t;
for (t = 0; t
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?