10.STM32F407ZGT6-内部温度传感器
参考:
1.正点原子
前言:
本笔记的主要目的和意义就是,再次练习ADC的使用。
32.1 内部温度传感器简介
STM32F407 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA)。对于STM32F407 系列来说,该温度传感器在内部和 ADC1_INP16(STM32F40xx/F41xx 系列)或ADC_IN18(STM32F42xx/F43xx)输入通道相连接,此通道把传感器输出的电压转换成数字值。
STM32F4 的内部温度传感器支持的温度范围为:-40~125 度。精度为±1.5℃左右。
STM32F407 内部温度传感器的使用很简单,只要设置一下内部 ADC,并激活其内部温度传感器通道就差不多了。关于 ADC 的设置,我们在上一章已经进行了详细的介绍,这里就不再多说。接下来我们介绍一下和温度传感器设置相关的两个地方。
第一个地方,我们要使用 STM32F407 的内部温度传感器,必须先激活 ADC 的内部通道,这里通过 ADC_CCR 的 VSENSEEN 位(bit23)设置。设置该位为 1 则启用内部温度传感器。
第二个地方,STM32F407ZGT6 的内部温度传感器固定的连接在 ADC1 的通道 16 上,所以,我们在设置好 ADC1 之后只要读取通道 16 的值,就是温度传感器返回来的电压值了。根据这个值,我们就可以计算出当前温度。计算公式如下:
𝑇(℃) ={ (Vsense - V25) / Avg_Slope}+25
式子中:
V25 = Vsense 在 25 度时的数值(典型值为:0.76)
Avg_Slope = 温度与 Vsense 曲线的平均斜率(单位:mv/℃或 uv/℃)(典型值:2.5mv/℃)。
利用以上公式,我们就可以方便的计算出当前温度传感器的温度了。
现在,我们就可以总结一下 STM32 内部温度传感器使用的步骤了,如下:
1)设置 ADC,并开启 ADC_CR2 的 VSENSEEN 位。
关于如何设置 ADC,请参考上一章对单通道 ADC 采集实验的设置,都是大同小异。然后,我们需要设置 ADC_CR2 寄存器的 VSENSEEN 位为 1,开启内部温度传感器。
2)读取 ADC 通道 16 的 AD 值,计算结果。
在设置完之后,我们就可以读取温度传感器的电压值了,得到该值就可以用上面的公式计算温度值了。
32.2 硬件设计
- 例程功能
通过 ADC1 的通道 16 读取 STM32F407 内部温度传感器的电压值,并将其转换为温度值,通过串口输出。 - 硬件资源
1)串口 1(PA9/PA10 连接在板载 USB 转串口芯片 CH340 上面)
2)ADC1 通道 16
3)内部温度传感器 - 原理图
ADC 和内部温度传感器都属于 STM32F407 内部资源,实际上我们只需要软件设置就可以正常工作。
32.3 程序设计
32.3.1 ADC 的 HAL 库驱动
本实验用到的 ADC 的 HAL 库 API 函数前面都介绍过,具体调用情况请看程序解析部分。
下面介绍读取内部温度传感器 ADC 值的配置步骤。
读取内部温度传感器 ADC 值配置步骤
1)开启 ADC 时钟
通过__HAL_RCC_ADC1_CLK_ENABLE 函数开启 ADC1 的时钟。
2)设置 ADC1,开启内部温度传感器
调用 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 值。最后根据上面介绍的公式计算出温度传感器的温度值。
32.3.3 程序解析
1. adc 驱动代码
首先是 ADC 初始化函数,其定义如下:
void MX_ADC1_Init(void)
{/* USER CODE BEGIN ADC1_Init 0 *//* USER CODE END ADC1_Init 0 */ADC_ChannelConfTypeDef sConfig = {0};/* USER CODE BEGIN ADC1_Init 1 *//* USER CODE END ADC1_Init 1 *//** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)*/hadc1.Instance = ADC1;hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;hadc1.Init.Resolution = ADC_RESOLUTION_12B;hadc1.Init.ScanConvMode = DISABLE;hadc1.Init.ContinuousConvMode = DISABLE;hadc1.Init.DiscontinuousConvMode = DISABLE;hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;hadc1.Init.NbrOfConversion = 1;hadc1.Init.DMAContinuousRequests = DISABLE;hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;if (HAL_ADC_Init(&hadc1) != HAL_OK){Error_Handler();}/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.*/sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; /*ADC16通道*/sConfig.Rank = 1;sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)/*配置了ADC16,该函数就会打开内部温度传感器*/{Error_Handler();}/* USER CODE BEGIN ADC1_Init 2 *//* USER CODE END ADC1_Init 2 */}
下面是获得 ADC 转换后的结果函数,其定义如下:
#include "adc_app.h"extern ADC_HandleTypeDef hadc1;/**
* @brief 设置 ADC 通道采样时间
* @param adcx : adc 句柄指针,ADC_HandleTypeDef
* @param ch : 通道号, ADC_CHANNEL_0~ADC_CHANNEL_17
* @param stime: 采样时间 0~7, 对应关系为:
* @arg ADC_SAMPLETIME_3CYCLES, 3 个 ADC 时钟周期ADC_SAMPLETIME_15CYCLES, 15 个 ADC 时钟周期
* @arg ADC_SAMPLETIME_28CYCLES, 28 个 ADC 时钟周期 ADC_SAMPLETIME_56CYCLES, 56 个 ADC 时钟周期
* @arg ADC_SAMPLETIME_84CYCLES, 84 个 ADC 时钟周期 ADC_SAMPLETIME_112CYCLES,112 个 ADC 时钟周期
* @arg ADC_SAMPLETIME_144CYCLES,144 个 ADC 时钟周期ADC_SAMPLETIME_480CYCLES,480 个 ADC 时钟周期
* @param rank: 多通道采集时需要设置的采集编号, 假设你定义 channel1 的 rank=1,channel2 的 rank=2,
* 那么对应你在 DMA 缓存空间的变量数组 AdcDMA[0] 就 i 是 channle1 的转换结果, AdcDMA[1]就是通道 2 的转换结果。单通道 DMA 设置为 ADC_REGULAR_RANK_1
* @arg 编号 1~16:ADC_REGULAR_RANK_1~ADC_REGULAR_RANK_16
* @retval 无
*/
void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime)
{/* 配置对应 ADC 通道 */ADC_ChannelConfTypeDef adc_channel;adc_channel.Channel = ch; /* 设置 ADCX 对通道 ch */adc_channel.Rank = rank; /* 设置采样序列 */adc_channel.SamplingTime = stime; /* 设置采样时间 */HAL_ADC_ConfigChannel( adc_handle, &adc_channel);
}/**
* @brief 获得 ADC 转换后的结果
* @param ch: 通道值 0~17,取值范围为:ADC_CHANNEL_0~ADC_CHANNEL_17
* @retval 无
*/
uint32_t adc_get_result(uint32_t ch)
{/* 设置通道,序列和采样时间 *///adc_channel_set(&hadc1, ch, 1, ADC_SAMPLETIME_480CYCLES);HAL_ADC_Start(&hadc1); /* 开启 ADC */HAL_ADC_PollForConversion(&hadc1, 10); /* 轮询转换 *//* 返回最近一次 ADC1 规则组的转换结果 */return (uint16_t)HAL_ADC_GetValue(&hadc1);
}/**
* @brief 获取通道 ch 的转换值,取 times 次,然后平均
* @param ch : 通道号, 0~17
* @param times : 获取次数
* @retval 通道 ch 的 times 次转换结果平均值
*/
uint32_t adc_get_result_average(uint32_t ch, uint8_t times)
{uint32_t temp_val = 0;uint8_t t;for (t = 0; t < times; t++) /* 获取 times 次数据 */{temp_val += adc_get_result(ch);}return temp_val / times; /* 返回平均值 */
}/**
* @brief 获取内部温度传感器温度值
* @param 无
* @retval 温度值(扩大了 100 倍,单位:℃.)
*/
float adc_get_temperature(void)
{uint32_t adcx;float result;double temperature;adcx = adc_get_result_average(ADC_CHANNEL_TEMPSENSOR, 10);/* 读取内部温度传感器通道,10 次取平均 */temperature = (float)adcx*(3.3/4096); /* 获取电压值 */temperature = (temperature - 0.76)/0.0025 + 25; /* 将电压值转换为温度值 */result = temperature;return result;
}
该函数先是调用前面 ADC 实验章节写好的 adc_get_result_average 函数取获取通道 ch 的转换值,然后通过温度转换公式,返回温度值。
2. main.c 代码
在 main.c 里面编写如下代码:
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_DMA_Init();MX_USART1_UART_Init();MX_TIM6_Init();MX_RTC_Init();MX_ADC1_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){uart_debug_task();XL_TIME6_time_show(); /*周期输出内部温度值*//* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}
3.内部温度周期调用
#include "stdio.h"
#include "tim.h"
#include "usart.h"
#include "rtc.h"
#include "adc_app.h"#define TIME_PERIODIC_1S (10) /*1s打印一次*/
#define TIME_PERIODIC_10S (100) /*修改为10s打印一次*/static uint32_t g_time_1s = 0;
static uint32_t g_time_10s = 0;void LED_blink(void)
{HAL_GPIO_TogglePin(LED_0_GPIO_Port, LED_0_Pin);HAL_GPIO_TogglePin(LED_1_GPIO_Port, LED_1_Pin);
}void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim->Instance == TIM6){LED_blink();g_time_1s++;g_time_10s++;}}void XL_TIME6_time_show(void)
{if (g_time_1s >= TIME_PERIODIC_1S){g_time_1s = g_time_1s - TIME_PERIODIC_1S;float tmp_value = adc_get_temperature();printf("tmp_value:%f\r\n", tmp_value);}if (g_time_10s >= TIME_PERIODIC_10S){g_time_10s = g_time_10s - TIME_PERIODIC_10S;RTC_TimeTypeDef sTime = {0};HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);printf("H:%d, M:%d, S:%d\r\n", sTime.Hours, sTime.Minutes, sTime.Seconds);RTC_DateTypeDef sDate = {0};HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);printf("Y:%d, M:%d, W:%d, D:%d\r\n", sDate.Year, sDate.Month, sDate.WeekDay, sDate.Date);}
}
32.4 下载验证
将程序下载到开发板后,可以看到串口周期输出温度:稳定在31.3度左右(因为芯片会发热,所以一般会比实际温度偏高一点)
32.5 STM32CubeMX
1.内部温度的配置
32.6 源代码路径
git clone git@gitee.com:xiaoliangliangcong/stm32.git
STM32F407ZGT6/10.internal_temperature_sensor
相关文章:

10.STM32F407ZGT6-内部温度传感器
参考: 1.正点原子 前言: 本笔记的主要目的和意义就是,再次练习ADC的使用。 32.1 内部温度传感器简介 STM32F407 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA)。对于STM32F407 系列来说,该温度传感器在…...

运维安全中心(堡垒机)
阿里云运维安全中心(Alibaba Cloud Operation and Maintenance Security, OMS,通常也称为“堡垒机”)是一款针对云上运维管理的安全解决方案。它专注于加强云环境中运维过程的安全性,确保对关键云资源和服务的访问可控、可审计&am…...
Linux OOM | Early OOM | 进程监视
注: 本文为 “Linux OOM” 相关文章合辑。 Linux OOM 终结者 译者:花名有孚 | 2015-07-21 08:47 现在是早晨 6 点钟。已经醒来的我正在总结到底是什么事情使得我的起床闹铃提前了这么多。我们的监控系统显示,Plumbr 服务出故障了。 现在我…...

【2024年华为OD机试】(A卷,100分)- 等和子数组最小和(Java JS PythonC/C++)
一、问题描述 题目描述 给定一个数组nums,将元素分为若干个组,使得每组和相等,求出满足条件的所有分组中,组内元素和的最小值。 输入描述 第一行输入 m 接着输入m个数,表示此数组nums 数据范围:1<m&…...
NFS服务
nfs文件系统 NFS:NetworkFileSystem网络文件系统,基于内核的文件系统。 服务安装 不固定端口启动,会注册到rpcbind(固定端口)服务上, 局域网适用[rootvm ~]# yum -y install nfs-utils # 依赖安装rpcbind [ro…...
RabbitMQ 交换机、队列和路由键的命名规范
在 RabbitMQ 中,使用 Topic Exchange 模式时,交换机、队列和路由键的命名规范是非常重要的,尤其是在多环境和多微服务的场景中。合理的命名规范可以提高消息系统的可维护性、可扩展性以及可读性。以下是一些关于 Topic Exchange 模式中交换机…...

腾讯云AI代码助手编程挑战赛-刑说
作品简介 鉴于当代普法力度不够大,这个刑说可以帮助大家更好的普及法律知识 技术架构 采用了全后端分离的架构,前端使用Vue.js,腾讯云的AI服务处理自然语言理解与生成。 实现过程 开发环境、开发流程 系统:win11 开发工具&…...

【测试】持续集成CI/CD
近期更新完毕,建议关注收藏点赞~ 目录 概括gitJenkinspostman集成jenkins代码集成jenkins 概括 CI/CD stands for Continuous Integration and Continuous Deployment 定义 团队成果持续集成到公共平台。一天可以集成1次or多次 本地代码管理 git 远程代…...
阿里云直播Web
官方文档:Web播放器SDK常见问题_视频点播(VOD)-阿里云帮助中心 bug:播流的不稳定,直播总会进入 onM3u8Retry 监听,用户端就会黑屏,(但其实并没有关播,正常关播进入的是pause这个监听࿰…...

DuckDB:PRAGMA语句动态配置数据库行为
PRAGMA语句是DuckDB从SQLite中采用的SQL扩展。PRAGMA命令可能会改变数据库引擎的内部状态,并可能影响引擎的后续执行或行为。本文介绍PRAGMA命令及其典型应用场景。 DuckDB PRAGMA介绍 在 DuckDB 中,PRAGMA 是一种编译指示(compiler directi…...
GO通过SMTP协议发送邮件
什么是SMTP协议 SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)是用于发送邮件的协议。当一个邮件服务器需要发送邮件给另一个邮件服务器时,它会使用SMTP协议与目标服务器建立连接,并传输邮件内容。SMTP协议的…...
轻量自高斯注意力机制LSGAttention模型详解及代码复现
模型背景 近年来,卷积神经网络(CNN)在高光谱图像分类领域取得了显著进展。然而,CNN面临 长距离关系建模 和 计算成本 增加的挑战。为解决这些问题,研究人员提出了基于 轻量自高斯注意(Light Self-Gaussian-Attention, LSGA) 机制的视觉转换器(Vision Transformer, VIT),旨…...
解读若依框架中的`@Excel` 和 `@Excels` 注解
文章目录 一、Excels 注解详解1.1 适用场景1.2 作用与好处 二、Excel 注解详解2.1 核心属性解析2.2 高级用法2.3 综合应用案例 三、总结 解读若依框架中的 Xss 注解博客:解读若依框架中的 Xss 注解 接下来我们将对若依框架中的 Excel 和 Excels 注解进行更加详细的…...

云商城--基础数据处理和分布式文件存储
第2章 基础数据处理和分布式文件存储 1.分布式文件存储系统Ceph学习 1).掌握Ceph架构 2).掌握Ceph组件 3).搭建Ceph集群(了解) 2.Ceph使用 1).基于Ceph实现文件上传 2).基于Ceph实现文件下载 3.SKU、SPU管理 1).掌握SKU和SPU关系 2).理解商品发…...
六十九:基于openssl实战验证RSA
RSA(Rivest-Shamir-Adleman)是一种非对称加密算法,广泛应用于数据加密和数字签名领域。在实际开发和学习过程中,理解 RSA 的工作原理和使用场景非常重要。本文将以 OpenSSL 工具为基础,通过实例操作来验证和理解 RSA 的…...
Three.js 用户交互:构建沉浸式3D体验的关键
文章目录 前言一、基本交互:鼠标与触摸事件二、高级交互:键盘控制与游戏手柄支持三、物理模拟与碰撞检测四、手势识别与多点触控五、增强现实(AR)与虚拟现实(VR)六、触觉反馈与震动效果七、语音控制八、眼球…...
Android车机DIY开发之学习篇(五)默认应用修改
Android车机DIY开发之学习篇(五)默认应用修改 android默认应用位置 sdk/packages/apps InitRC配置 应用安装的目录 /system/priv-app 该路径存放一些系统底层的应用,比如Setting,systemUI等。该目录中的app拥有较高的系统权限,而且如果要使…...
linux 设置mysql 外网访问
1、修改 MySQL 配置文件 找到并编辑配置文件:在Linux系统中,MySQL的配置文件通常是/etc/mysql/my.cnf,使用命令sudo vim /etc/mysql/my.cnf打开文件。 注释或修改 bindaddress:找到bindaddress 127.0.0.1,将其注释掉…...
SQL UNION 操作符
SQL UNION 操作符 SQL UNION 操作符用于合并两个或多个 SELECT 语句的结果集。它将多个结果集组合成一个单独的结果集,并去除重复的行。为了使用 UNION,每个 SELECT 语句必须具有相同的列数,并且对应列的数据类型必须兼容。 语法 SELECT c…...
c++ 17 constexpr
未来已来:从SFINAE到concepts #include <type_traits> #include <vector> #include <list> #include <iostream> // 一个通用的容器打印函数,支持任何带 begin()/end() 的容器 template<typename Container> …...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...