NTC测温读数为0或跳变剧烈,主因是未接入分压电路导致ADC输入阻抗干扰;应采用R_fixed与NTC构成分压、加滤波电容、确保ADC采样时间充足、正确换算阻值与温度,并抑制自热效应。

ADC读取NTC电压时,为什么测出来全是0或跳变剧烈?
常见原因是NTC没接入分压电路,直接接ADC引脚——这会导致ADC输入阻抗与NTC阻值形成不可控分压,尤其当MCU的ADC输入阻抗不够高(比如STM32默认约10kΩ~50kΩ)时,读数严重偏低甚至锁死在0。NTC必须和一个已知阻值的R_fixed组成分压器,ADC采样中间节点。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 选
R_fixed阻值尽量接近NTC在目标温度中点处的阻值(例如25℃时10kΩ NTC,就用10kΩ金属膜电阻) - 分压输出端务必加0.1μF陶瓷电容到地,滤除高频噪声和ADC采样瞬间的电流冲击
- 确认MCU的ADC参考电压稳定(如用内部1.2V基准需校准,外部VREF+需低噪声LDO供电)
- 避免长导线直连NTC,否则引入工频干扰,最好用双绞线或屏蔽线
用Steinhart-Hart公式换算温度,但结果偏差超过±5℃怎么办?
标准三参数Steinhart-Hart公式精度高,但前提是三个标定点(如0℃、25℃、70℃)的实测阻值准确;多数人直接套用NTC厂商给的B值公式(两参数简化版),误差大是因为B值只在有限温区有效,且未补偿热敏电阻批次差异。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 优先用B值公式:
1/T = 1/T0 + (1/B) * ln(R/R0),其中T0=298.15(25℃),R0是25℃标称阻值,B查规格书(如3950),单位K - 若要求±0.5℃精度,必须实测至少3个温度点的阻值,用最小二乘法拟合三参数
A、B、C,而非硬编码厂商给的理论值 - 注意单位:ADC读的是电压,要先转成阻值:
R_ntc = R_fixed * (Vref / V_adc - 1)(假设分压是R_fixed上拉、NTC接地) - 浮点运算在资源受限MCU上可能溢出,用
float而非double,并检查ln()输入是否≤0(防止V_adc=0或满幅)
STM32 HAL库里调HAL_ADC_Start()后HAL_ADC_PollForConversion()总超时
本质是ADC时钟配置或通道初始化遗漏。HAL默认不开启ADC时钟,也不自动设置采样时间——而NTC响应慢,若采样时间太短(如1.5 cycles),寄生电容来不及充放电,结果就是读数恒定或随机。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 手动使能ADC时钟:
__HAL_RCC_ADC_CLK_ENABLE() - 在
MX_ADC_Init()中显式设置采样时间:对一般NTC分压输出,设为ADC_SAMPLETIME_239CYCLES_5(≈10μs以上) - 确认GPIO模式是
ANALOG,且无上下拉(PULLUP/PULLDOWN会改变分压比) - 不要在中断里反复调
HAL_ADC_Start(),应启动一次后循环用HAL_ADC_PollForConversion()或改用DMA+回调
温度值抖动大,软件滤波后仍不平滑
硬件噪声和热时间常数不匹配是主因。NTC本身热惯性大(响应数百毫秒),但ADC每10ms采一次,高频噪声被全盘捕获;单纯用移动平均会掩盖真实温度变化趋势。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 硬件上:在分压输出端串一个1–10kΩ限流电阻+0.1μF电容(RC低通,截止频率≈160Hz),比纯软件更治本
- 软件上:用一阶IIR滤波:
temp_filtered = temp_filtered * 0.8f + temp_raw * 0.2f,系数按响应速度调整(越小越平滑,但滞后越大) - 避免对原始ADC值滤波再换算温度——应先换算出温度,再对温度值滤波,因为NTC阻值-温度是非线性的,线性滤波ADC码值会引入非线性失真
- 若用于温控,建议加迟滞判断(如温度变化±0.3℃才更新),避免频繁触发动作
实际中最容易被忽略的是NTC的自热效应:当流过NTC的电流超过100μA(对应10kΩ上1V压差),自身发热就会让读数偏高。务必核算分压电流:I = Vref / (R_fixed + R_ntc_min),高温时R_ntc可能仅几百欧,电流骤增——这时要么提高R_fixed,要么改用定时采样+采样后立刻断开分压供电(用MOSFET控制)。


















