NTC热敏电阻温度换算太复杂?一篇搞定所有算法!

NTC热敏电阻温度换算太复杂?一篇搞定所有算法!

一、NTC热敏电阻是什么

        在嵌入式系统开发中,温度测量是一个常见需求。NTC(负温度系数)热敏电阻因其成本低、灵敏度高而被广泛应用。本文将详细介绍如何利用一个简单的分压电路,结合STM32的ADC和数学公式,实现高精度的温度测量。

        NTC是Negative Temperature Coefficient的缩写,意为“负温度系数”。其核心特性是电阻值随温度升高而呈指数型下降。这种特性使其对温度变化极为敏感,非常适合作为温度传感器。

  • 工作原理:其半导体材料内部的载流子数量随温度升高而增加,导致电阻下降。
  • 关键参数
    • R25:在25°C(即298.15K)时的零功率电阻值。这是最重要的标称值,例如常见的10kΩ100kΩ等。在下文计算中,我们的R0就是指这个值。
    • B值:材料常数,单位为开尔文(K)。它描述了NTC电阻-温度曲线的形状,代表了在T1T2两个温度之间的“斜率”。B值越大,在相同温度变化下,电阻变化率越高。常用值如3380K3950K等。
  • 优点:成本低、灵敏度高、体积小。
  • 缺点:非线性、需要校准和计算、测温范围相对较窄。

二、电路设计采用分压电路

        为了测量NTC的电阻,我们通常不直接测量电阻,而是将其转换为电压进行测量。最经典、最经济的方案就是分压电路

电路分析:

  1. 拓扑结构:NTC(R1)与一个精度较高的定值电阻R2(图中为49.9kΩ)串联,接在3.3V电源与地之间。
  2. 测量点:中间节点NTC_ADC的电压V_out即是我们的测量目标。这个点连接至STM32的ADC输入引脚。
  3. 工作原理:这是一个经典的分压器。V_out的电压由R1和R2的阻值比例决定:V_out = 3.3V * (R2 / (R1 + R2))由于NTC的阻值R1会随温度变化,V_out也会随之变化。温度升高 -> R1减小 -> V_out升高。
  4. 下拉电阻R2的选型:R2的阻值选择至关重要,它决定了电路的灵敏度和测量范围。通常选择与NTC在目标测温范围中心点的阻值相近的阻值。本例中选择49.9kΩ,是为了在较宽的温度范围内获得较好的电压变化线性度。如果主要测量室温附近,可以选择与R25(10kΩ)相近的阻值,如10kΩ。
  5. 计算NTC电阻:通过ADC读取到V_out后,我们可以反推出NTC在当前温度下的电阻值R_ntc:R_ntc = R2 * (Vcc / V_out - 1),其中Vcc = 3.3VR2 = 49.9kΩ

        

三、Steinhart-Hart简化方程公式推导

        NTC的电阻-温度关系是非线性的,最精确的描述是Steinhart-Hart方程。但在一定温度范围(如-40°C ~ 125°C)内,我们可以使用其简化版本,精度已足够。推导基于NTC的数据手册参数R25B值。

Steinhart-Hart简化公式为:

        T:待求的温度,单位为开尔文(K)。
        T0:参考温度,单位为开尔文(K)。通常取25°C = 298.15K。
        R:在温度T下测量/计算得到的NTC电阻值。
        R0:在参考温度T0下的NTC电阻值,一般为10kΩ。
        B:NTC的材料常数B值。

NTC温度的计算步骤:

        a. 通过ADC和分压公式,求出当前R_ntc

        b. 计算ln(R_ntc / R25)

        c. 计算1/T = 1/298.15 + (1/B) * ln(R_ntc / R25)

        d. 计算T = 1 / (1/T),得到开尔文温度。

        e. 转换为摄氏度:Temp(°C) = T(K) - 273.15

四、基于HAL库的逻辑代码

#include "temp.h" #include "stdio.h" #include "math.h" #include "oled.h" // NTC参数 #define NTC_BETA 3450.0f // NTC热敏系数(B25/85值) #define NTC_R25 10000.0f // 25℃时NTC阻值(Ω) #define PULLDOWN_RESISTOR 50000.0f // 下拉电阻R2值(Ω) - 50kΩ /** * @brief ADC初始化函数 * @note 执行ADC校准并启动ADC转换 * @param 无 * @retval 无 */ void ADC_Init(void) { HAL_ADCEx_Calibration_Start(&hadc1); HAL_ADC_Start(&hadc1); } /** * @brief 中值滤波函数 * @note 采集N次ADC值,排序后返回中值 * @param hadc: ADC句柄指针 * @param N: 采样次数(建议奇数) * @retval 滤波后的ADC值 */ int getMiddleValue(ADC_HandleTypeDef *hadc, int N) { int value_buf[N]; int i, j, k, temp; for(i = 0; i < N; i++) { HAL_ADC_PollForConversion(hadc, HAL_MAX_DELAY); value_buf[i] = HAL_ADC_GetValue(hadc); } // 冒泡排序 for(j = 0; j < N-1; j++) { for(k = 0; k < N-1-j; k++) { if(value_buf[k] > value_buf[k+1]) { temp = value_buf[k]; value_buf[k] = value_buf[k+1]; value_buf[k+1] = temp; } } } return value_buf[(N-1)/2]; } /** * @brief 计算NTC电阻值 * @note 根据NTC在上、固定电阻在下的分压电路计算NTC电阻 * @param voltage: ADC测量电压(V) * @retval NTC电阻值(Ω) */ float calculate_ntc_resistance(float voltage) { // 电路:3.3V → R16(NTC) → ADC点 → R8(40k) → GND // 分压公式:Vadc = 3.3V * R8 / (R_NTC + R8) // 推导出:R_NTC = (3.3V * R8 / Vadc) - R8 return (3.3f * PULLDOWN_RESISTOR / voltage) - PULLDOWN_RESISTOR; } /** * @brief 温度计算函数 * @note 使用Steinhart-Hart简化方程计算NTC温度 * @param resistance: 当前NTC电阻值(Ω) * @retval 温度值(℃),错误返回-999.0 */ float calculate_temperature(float resistance) { if(resistance <= 0) return -999.0f; // 参考温度T0 = 25C = 298.15K const float T0_K = 273.15f + 25.0f; // 298.15K // 计算 ln(R/R0) float ln_ratio = logf(resistance / NTC_R25); // 计算 1/T = 1/T0 + (1/B) * ln(R/R0) float reciprocal_temp = 1.0f/T0_K + (1.0f/NTC_BETA) * ln_ratio; // 计算 T = 1 / (1/T) float temp_k = 1.0f / reciprocal_temp; // 转换为摄氏度 return temp_k - 273.15f; } int ntc_value = 0; // ADC原始值 float ntc_voltage = 0.0f; // NTC电压值(V) float ntc_resistance = 0.0f; // NTC电阻值(Ω) float temperature = 0.0f; // 计算温度值(℃) char displayStr[16]; // OLED显示字符串 /** * @brief 温度处理主函数 * @note 采集温度数据,计算实际温度并在OLED显示 * @param 无 * @retval 无 */ void temperature_proc(void) { // NTC温度采集 ntc_value = getMiddleValue(&hadc1, 7); // 转换成电压值 ntc_voltage = (ntc_value / 4095.0f) * 3.3f; // 计算NTC电阻值 ntc_resistance = calculate_ntc_resistance(ntc_voltage); // 计算温度 temperature = calculate_temperature(ntc_resistance); // 显示温度 sprintf(displayStr, "T:%.1fC", temperature); OLED_ShowString(0, 1, displayStr); } 

五、总结

        通过NTC测量温度是一个嵌入式中的经典应用。整个过程可以总结为以下链条:温度变化 -> NTC电阻变化 -> 分压点电压变化 -> ADC采样值变化 -> 公式计算 -> 得到温度值。

  1. 电路设计是基础:一个稳定的Vcc和一个精密的下拉电阻是获得准确电压的前提。
  2. 公式是核心:Steinhart-Hart简化公式是将非线性电阻值转换为线性温度值的关键桥梁。务必确保B值和R25两个参数准确。
  3. 软件实现需注意细节:ADC的参考电压、分辨率、滤波(软件或硬件),以及浮点数运算的精度和效率都需要根据实际项目权衡。

        在实际项目中,为了提高精度,我们还可以进行两点校准,(例如在冰水混合物和沸水中,以消除元件公差和电路带来的系统误差。

        如有任何勘误,还望各位在评论区一起交流讨论学习!

Read more

--- 通过逆向 WebChat 协议打造 OpenClaw 的“万能胶水” ---

摘要 在 OpenClaw 的二次开发中,官方推荐的 Channel 扩展模式往往伴随着较高的开发和部署成本。本文介绍了一种更直接的“降维打击”方案:通过逆向工程解析 Gateway 与 WebChat 之间的 WebSocket 通信协议,构建一个通用适配器(Universal Adapter)。该适配器能将任何外部程序(CLI、脚本、第三方 UI)伪装成官方 WebChat 客户端,从而实现零后端修改接入,并天然支持会话历史同步。 正文内容 1. 缘起:为什么我们需要这层“胶水”? 在 OpenClaw 的生态中,如果你想让一个外部系统(比如一个 Python 脚本、一个 IoT 设备或者一个自定义网页)和 Agent 对话,官方的标准答案通常是:“去开发一个

By Ne0inhk
《Web 自动化测试入门:从概念到百度搜索实战全拆解》

《Web 自动化测试入门:从概念到百度搜索实战全拆解》

一、自动化的核心概念 1. 定义:通过自动方式替代人工操作完成任务,生活中常见案例(自动洒水机、自动洗手液、超市闸机)体现了 “减少人力消耗、提升效率 / 质量” 的特点。 2. 软件自动化测试的核心目的: * 用于回归测试:软件迭代新版本时,验证新增功能是否影响历史功能的正常运行。 3. 常见面试题解析: * 自动化测试不能完全取代人工测试:需人工编写脚本,且功能变更后需维护更新,可靠性未必优于人工。 * 自动化测试不能 “大幅度降低工作量”:仅能 “一定程度” 减少重复工作,需注意表述的严谨性。 二、自动化测试的分类 自动化是统称,包含多种类型,核心分类及说明如下: 分类说明接口自动化针对软件接口的测试,目的是验证接口的功能、性能、稳定性等。UI 自动化 针对软件界面的测试,包含: 1. 移动端自动化:通过模拟器在电脑上编写脚本,测试手机应用;稳定性较差(受设备、

By Ne0inhk
DevUI 组织 2025 年度运营报告:扎根 AtomGit,开源前端再启新程

DevUI 组织 2025 年度运营报告:扎根 AtomGit,开源前端再启新程

在开源浪潮席卷全球的今天,DevUI 始终以「打造企业级前端开源解决方案」为初心,依托 AtomGit 平台的生态优势稳步前行。2025 年,我们聚焦组件迭代、生态共建与社区连接,在技术深耕与开源协作中收获颇丰。现将全年发展足迹与未来规划分享如下,致谢每一位同行者的支持! 一、年度核心成果:数据见证成长 * 项目矩阵持续扩容:新增 MateChat-React、react-devui 等 4 个衍生项目,形成覆盖 Vue、Angular、React 三大框架的全栈组件生态,累计开源仓库达 7 个 * 社区活力显著提升:全年接收 PR 提交 300+,Star 数稳步增长至 3.02k,累计下载量超 46.08k 次,核心项目 MateChat、vue-devui、ng-devui

By Ne0inhk
基于 Spring Boot 的 Web 三大核心交互案例精讲

基于 Spring Boot 的 Web 三大核心交互案例精讲

—知识点专栏——JavaEE专栏— 作为 Spring Boot 初学者,理解后端接口的编写和前端页面的交互至关重要。本文将通过三个经典的 Web 案例——表单提交、AJAX 登录与状态管理、以及 JSON 数据交互——带您掌握前后端联调的核心技巧和 Spring Boot 的关键注解。 1. 案例一:表单提交与参数绑定(计算求和) 本案例展示最基础、最传统的 Web 交互方式:HTML 表单提交。 1.1 后端代码:CalcController.java 使用 @RestController 简化接口编写,并通过方法参数接收表单数据。 packagecn.overthinker.springboot;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.

By Ne0inhk