PT100 温度采集 STM32 完整工程:从信号链到串口输出的设计与实现

发布时间:2026/10/21 18:51:00
PT100 温度采集 STM32 完整工程:从信号链到串口输出的设计与实现
简介这是一份基于STM32F103C8T6微控制器的PT100温度采集与串口通信完整工程源码包面向嵌入式初学者、电子竞赛选手以及温度测控项目开发者。工程完整演示了利用片内模数转换器读取PT100铂电阻随温度变化的阻值再通过通用异步收发器将温度数据发送到上位机的全过程涉及传感器检测电路设计、ADC通道配置、采样时间与参考电压设定、连续转换模式、DMA或中断方式读取以及串口波特率、数据位、停止位和校验位的协议匹配等关键环节。压缩包共253个文件大小约7.42MB内容以C/H源程序、Keil工程文件uvprojx、uvoptx、编译产物hex、axf、o以及调试辅助文件为主目录结构清晰可直接打开工程进行编译、烧录与验证。目前已有1214人学习下载。借助该工程读者可以快速掌握STM32 HAL/LL库环境下ADC加串口的基本开发流程理解连续转换与DMA传输对系统效率的提升并借鉴工程中的PT100检测电路设计与上位机数据解析思路作为毕业设计、课程项目或实际温度监测系统的起步模板。1. 一个把 PT100 温度采集做完整的 STM32 工程从 100Ω 铂电阻到串口温度数据冷库、恒温箱、工业现场这一类场景里温度传感器通常不选成本更低的 NTC也不选怕断线的热电偶而是选 PT100。原因很简单它 0℃ 时刚好 100Ω线性度和长期稳定性都很能打。但这个「物理特性稳定」恰恰是工程上的难点0.385Ω/℃ 的微弱变化意味着导线电阻、基准漂移、运放失调都会直接变成温度误差。手头这份 STM32F103C8T6 的 PT100 工程压缩包把信号链、固件程序和调试要点配成了一整套可以直接跑的方案三线制接法、恒流源激励、差分放大、ADC 采样、查表插值再到串口输出全都有适合做温控设备预研的工程师和想把 PT100 移植到自己板子上的开发者。拿到这种资源第一步不是急着烧录而是先搞清楚它为什么这么接再谈改哪里。下面从信号链开始拆。2. 为什么这么接PT100 信号链设计与参数推算2.1 激励方式怎么选电压分压不是不行而是不稳PT100 本质是铂电阻输出阻抗低常温附近大概 100~138Ω。它的问题不是信号小而是「小到不经放大根本喂不饱 ADC」。在 0~100℃ 范围内电阻变化率约 0.385Ω/℃如果直接用 3.3V 分压网络把 100Ω 和另一个 100Ω 精密电阻串起来1℃ 对应的电压变化只有 0.1mV 量级而 STM32F103 的 12 位 ADC 在 3.3V 参考下的 LSB 大约 0.8mV也就是说一个 LSB 就带好几度。于是放大是必须的但放大之前得先解决激励。常见做法是用恒流源给 PT100 供 1mA 电流再对电阻两端的电压做差分放大。为什么不用电桥加电压源我早期做一版就是用 3.3V 直接分压结果电源轻微波动读数就像心电图一样抖。后来换成恒流源参考源用独立的 2.5V 精密基准才把问题压下去。这背后的逻辑是恒流源输出的电流对电源波动不敏感只要电流稳定PT100 上的电压就只随电阻变化而电桥方案里电压源波动会同时改变桥臂两侧电位放大后很难分离。这份工程里用的是 1mA 恒流源在 0℃ 时产生 0.1V100℃ 时产生 0.1385V跨度 38.5mV这个跨度乘以 20 倍增益后约 0.77V恰好落在 ADC 输入范围内。如果想要更低自热可以把电流降到 0.5mA但代价是信号幅度减半增益要随之翻倍噪声也会上来这是一个需要权衡的折衷。另一条路是选更高的激励像 2mA信号幅度大了但自热也更重多数资料推荐 1mA 作为平衡点。恒流源的实现方式也值得说一句。工程里用的是运放加三极管组成的经典恒流电路比买集成恒流源芯片便宜温度系数也能做到几十 ppm 级别。如果自己重画这块电路注意采样电阻要用低温漂的金属膜电阻因为恒流源的精度直接取决于这个电阻1% 的阻值误差就是 1% 的电流误差最终全部体现在温度读数上。2.2 三线制不是玄学导线电阻会吃掉半度到一度两线制的误差很多人第一版都会踩。假设传感器线 2 米单根铜导线电阻 0.2~0.5Ω 很常见这个电阻和 PT100 串联会直接叠加到测量结果上。0.5Ω 折合到 PT100 是 0.5 / 0.385 ≈ 1.3℃而工业现场 0.5℃ 误差可能就意味着设备误报警。三线制的做法是恒流源从一根线送进 PT100另外两根线把传感器两端的电压引到运放的差分输入端。因为采样回路几乎不取电流线电阻上的压降就进不了信号通路。工程里对应的接线顺序是 V、S、S- 三根线V 接恒流源输出S 和 S- 接差分放大正负输入端。这里的关键是恒流源要带足够的负载能力长线情况下导线本身几百毫欧的电阻不会影响电流精度而差分放大器要选择输入偏置电流小的运放否则偏置电流会在采样线上产生附加压降。注意三线制只抵消了导线电阻的静态贡献如果三根线材质或长度不一致残余误差还是有。所以现场布线要求三根线尽量等长、同材质这也是为什么 PT100 传感器成品通常三根线颜色固定且粗细一致。如果项目允许四个端子引线可以彻底消除这个问题但接口成本高工程里多数不用。还有一个现场容易翻车的点三线制接反也会「能工作但不准」因为恒流源线和采样线互换后采样线里流过了激励电流线阻直接变成误差。调试时先量线序别急着怀疑电路。2.3 差分放大与基准源参数让量程、增益和参考电压对得上拿到这个工程第一件要确认的事是运放增益到底是多少这决定你能测到多少度。常见方案是用一个双运放前级做差分放大后级做一个低通跟随器或二阶滤波。工程里用的电路反馈电阻 200k输入电阻 10k理论增益 200k / 10k 20。按这个增益0~250℃ 对应电阻 100~194.07Ω输出电压 2.0V 到 3.88V已经超出 3.3V ADC 量程所以这个配置的实际测温上限是电路电压不超量程的界限约 215℃。如果项目只需要测到 120℃可以把反馈电阻降到 150k让满量程更宽如果希望 0.1℃ 分辨率保留增益尽量设计在让 250℃ 对应 3.0V 附近。这里的计算逻辑是激励电流 1mA250℃ 时 PT100 电阻 194Ω信号电压 0.194V增益 20 倍放大后 3.88V超量程反过来算要让 250℃ 对应 2.8V增益应取 2.8 / 0.194 ≈ 14.4取 15 倍比较合理ADC 参考电压不要使用芯片内部 VREF。STM32F103C8T6 内部参考精度只有约 ±5%且随温度漂移直接导致测量值跟着环境温度变化。建议把 REF 引脚接到外部 2.5V 精密基准TL431 是最常见的选择它的温度系数大约 50ppm/℃做 0.1℃ 级的设备够用。ADC 量程变成 0~2.5V 后前面的增益换算要做相应调整250℃ 对应 0.194V 信号要放大到 2.5V 以内增益上限约 12.9这也是解压工程后第一处需要改的参数。补充一个容易被忽略的点运放的共模输入范围。PT100 的电压信号是浮在恒流源负端之上的比如激励电流从 3.3V 流向 GNDPT100 上浮电压可能在 1.5V 附近。如果运放是单电源供电必须确认输入共模范围能覆盖这个中电平首选轨到轨输入运放比如常见的通用型号否则输出会提前削顶。信号削顶导致读数非线性是排查时最容易误判成「PT100 非线性」的坑之一。PCB 布线也在这里提一句差分放大器的两个输入走线要尽量等长、对称并且下方要有完整的模拟地平面。如果走线不对称两条线上的寄生电容不同共模转差模的噪声会被放大。这些细节在低速采样时不一定暴露但换到工厂环境就会突然冒出来。3. 从压缩包到串口数据工程结构与关键代码怎么改3.1 解压后先认路找对文件再动手这份压缩包用的固件库是标准外设库SPL版本不是 HAL 库。对 STM32F103 这种资源紧张的片子标准库更省 Flash也更容易看懂底层但代价是不同芯片型号之间移植性不如 HAL。工程目录里主要看这几个文件文件职责main.c主流程初始化与循环调度pt100.c / pt100.hPT100 换算与查表接口adc_dma.cADC 与 DMA 初始化calibration.c校准参数与 Flash 读写uart.c串口发送建议第一次打开工程先整体编译一遍确认工具链版本兼容再逐个文件读。标准外设库有个常见问题很多工程是从别的板子上复制出来的时钟初始化 SystemInit 里可能还留着原板子的外部晶振配置。如果板子用的是 8MHz 晶振系统时钟应配置为 72MHzPLL 倍频系数 9如果用的是 25MHz 晶振倍频系数要改成 3。这个不对后面的串口波特率和 ADC 采样时间全部会偏而且软件调不出来。主流程的逻辑是这样系统时钟 72MHz 跑起来GPIO、ADC、DMA、UART 逐个初始化然后进入 while 循环循环里每 100ms 读一次 DMA 缓冲区的平均值换算温度后通过串口发出去。串口波特率默认 96008 数据位、1 停止位、无校验数据格式是一行T25.3C末尾带换行符方便直接接串口助手或者后端的 Modbus 转接器里解读。如果接 PLC建议按 PLC 的字符串协议改或者直接换成带 CRC 的帧格式把起始符和校验加进去否则现场长线传输偶尔会错一位。3.2 ADC 加 DMA用硬件循环采样代替 CPU 忙等PT100 信号经过放大后送到 ADC 引脚工程里接的是 PA1。ADC 配置用规则通道 DMA 循环模式一次配置让硬件自动连续采样 16 次CPU 只需要在用户定时到了之后读 DMA 缓冲区。这个设计的好处是把采样和计算解耦温度换算放到主循环里采样密集度由 DMA 保证不会因为 CPU 有其他任务产生采样间隔抖动。ADC 初始化代码片段如下// ADC1 通道1DMA循环模式16次采样做软件平均 ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; // 使能时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_DMA1, ENABLE); // 配置PA1为模拟输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, GPIO_InitStructure); // DMA1通道1对应ADC1 DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)ADC1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)adc_buf; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize 16; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_Init(DMA1_Channel1, DMA_InitStructure); // ADC1配置12位分辨率、连续转换采样时间取最长 ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode DISABLE; ADC_InitStructure.ADC_ContinuousConvMode ENABLE; ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); ADC_SoftwareStartConvCmd(ADC1, ENABLE);这里有两个参数值得专门说明。一个是 DMA_BufferSize 16意思是 DMA 会连续搬运 16 个 ADC 转换结果到 adc_buf 数组之后再从头覆盖形成环形缓冲主循环只要每 100ms 读一次这 16 个数的平均值就行。另一个是 ADC_SampleTime_239Cycles5这是该芯片上最长的采样时间约 3μs能让内部采样电容充分充电。PT100 信号内阻低采样时间短问题不大但长采样时间对抑制高频噪声有帮助16 次平均配合这个采样时间等效的噪声带宽会明显收窄。主循环里的读取部分往往被写得很随意但有一个细节要注意DMA 是异步填充数组的主循环读平均值时可能正好赶上第 5 和第 6 次数据被更新造成平均值轻微不连续。常见的做法是每次先禁能 DMA拷贝缓冲再使能 DMA或者接受这一个周期的微小波动因为在 100ms 周期里影响极小。工程里采用的是第二种方式代码简单现场也没有发现可见跳变。注意如果换到其他型号的 F103DMA 通道映射可能不同直接搬代码容易踩坑。比如有的型号 ADC1 对应 DMA 通道并非 1先查数据手册再初始化这是移植时最常出的问题。3.3 温度换算函数先读数再换成电阻最后查表拿到 16 个 ADC 原始值后第一步是求平均然后换算成放大前的电压再通过激励电流换算成 PT100 电阻。这个过程里有个容易漏掉的地方如果采用外部 2.5V 基准ADC 满量程不是 3.3V 而是 2.5V另一个是运放增益 20 倍要除回。工程里给的核心换算函数如下#define ADC_VREF 2.5f // 外部基准电压 #define ADC_FULL_SCALE 4096.0f #define AMP_GAIN 20.0f #define EXC_CURRENT 0.001f // 恒流源1mA float adc_to_resistance(uint16_t adc_value) { // adc_value / 4096 * VREF 是放大后的电压 float vin ((float)adc_value / ADC_FULL_SCALE) * ADC_VREF; float vr_pt100 vin / AMP_GAIN; return vr_pt100 / EXC_CURRENT; // R U / I }这段代码的逻辑是反向还原传感器电阻返回值单位是欧姆。例如 25℃ 时理论电阻 109.73Ω对应 ADC 原始值约 1913换算结果应在 109~110Ω 之间。如果拿到的工程里 ADC 参考是 3.3V记得把 ADC_VREF 改成 3.3否则所有温度会系统性偏高 30% 左右这是移植到自制板时最常见的错误。再往上一层主循环每 100ms 做一次完整的采样、换算、发送。发送用标准库的串口函数占用时间很短。如果你要把温度数据接到 RS485 总线上建议把发送做成环形队列避免串口发送期间主循环被阻塞但这个工程里默认只是单机调试直接轮询发送足够。等到真接总线时再加队列和 CRC 也不晚。4. 查表、插值与两点校正把 0.1℃ 误差压到可接受范围4.1 生成一张 -50℃ 到 250℃ 的分度表PT100 在 -200℃ 到 850℃ 全范围内并非严格线性但在工业现场常用区间可以用分段查表。工程里提供了一张分度表从 -50℃ 到 250℃ 每 1℃ 一个电阻值数据来源是 IEC 60751 标准中 PT100 的典型值。以下展示开头的几个点方便核对表的边界和单位// 分度表-50℃ 到 250℃ 每 1℃ 的电阻值单位Ω const float pt100_table[] { 80.31f, // -50℃ 84.27f, // -40℃ 88.22f, // -30℃ 92.16f, // -20℃ 96.09f, // -10℃ 100.00f, // 0℃ 103.90f, // 10℃ 107.79f, // 20℃ 109.73f, // 25℃比对点 111.67f, // 30℃ // ... 后续省略 };这张表的间隔是 1℃如果只做最近邻查表最大误差会出现在两个点正中间约 0.19Ω折合 0.5℃。所以工程里实际用的是二分查找加线性插值把表内误差压到 0.01℃ 量级。注意插值出来的精度再高也高不过 ADC 和运放本身的测量误差表的密度更多是为了减少计算截断误差不解决模拟前端的问题。如果工程给的表不完整自己生成一张也不难。用 IEC 60751 的标准公式在电脑上先算一遍再按 C 语言数组格式输出比手工抄表靠谱得多# 生成 -50~250℃ 每1℃的PT100电阻值 r0 100.0 A 3.9083e-3 B -5.775e-7 C -4.183e-12 for t in range(-50, 251): if t 0: r r0 * (1 A * t B * t * t) else: r r0 * (1 A * t B * t * t C * (t - 100) * t * t * t) print(f{r:.2f}f, // {t}℃)生成后和工程里的表逐项比对一下如果个别点差超过 0.01Ω说明对方用的系数版本有差异以哪个为准取决于你现场用的传感器等级。工业现场 A 级 PT100 的允许误差是 ±(0.15 0.002·|t|)℃比起表本身的截断误差要大得多所以表只要没抄错通常不是精度瓶颈。如果要扩展温度范围比如低温测到 -100℃ 或高温测到 400℃只需要把表首尾补齐。查表函数的分段逻辑不用改但要注意 -100℃ 附近 PT100 灵敏度只有约 0.342Ω/℃同样电压下分辨率会略降这是材料特性查表救不了。4.2 二分查找 线性插值STM32F103 也能快速算F103 没有硬件浮点单元但 float 运算是软件模拟主频 72MHz 下执行几百次浮点运算也不是问题。查表函数写成整数二分只在最后插值步骤用一次浮点除法速度和精度都能兼顾。// 根据PT100电阻值查温度返回值单位℃ float resistance_to_temp(float resistance) { int low 0; int high TABLE_SIZE - 1; // 表长度 301 // 超出表范围直接限幅 if (resistance pt100_table[0]) return -50.0f; if (resistance pt100_table[TABLE_SIZE - 1]) return 250.0f; // 二分查找相邻两个表项 while (high - low 1) { int mid (low high) / 2; if (pt100_table[mid] resistance) { low mid; } else { high mid; } } // 线性插值温度 下界温度 电阻比例 * 1℃ float r0 pt100_table[low]; float r1 pt100_table[high]; float ratio (resistance - r0) / (r1 - r0); return (float)low - 50.0f ratio; }这个函数里low 和 high 分别是电阻值所在的左右表项索引因为表间隔固定 1℃温度差就是 (high - low)也就是 1。ratio 是介于 0 到 1 之间的插值系数。把索引换成摄氏温度需要偏移 -50因为表首项是 -50℃。二分查找 300 项最多走 9 次循环比从第 0 项开始遍历省大约 30 倍时间在 100ms 一次的温度采集周期里几乎不占时间。如果不想维护 301 个 float 的表也可以直接用标准公式反解多项式。但那样每次都要做三次方程求根F103 算起来明显更重而且公式中低温段的 C 系数处理容易出错。查表加插值是这个平台上最稳妥的写法。工程里这个函数被封装成 module_temperature.c 里的一个对外接口上层只传电阻值拿回温度值。如果以后换用其他热电阻比如 PT1000只需要换一张阻值十倍的表接口保持不动这是分层设计的好处。注意 PT1000 和 PT100 的电流配置不同PT1000 通常用 0.5mA 激励信号幅度和 PT100 在 1mA 时一样改工程时别忘记改 EXC_CURRENT。下面是一组实测的误差对比可以直观看到插值的价值查表方式最大量化误差实现成本最近邻约 0.5℃最低线性插值小于 0.01℃一次浮点除法分段多项式更高但复杂明显增加代码量对大多数工业应用线性插值已经足够再往上属于边际收益递减。4.3 标定参数存哪利用片内 Flash 最后一页做掉电保存换了个运放换了个恒流源增益和零漂就不一样了。每次都用代码硬改校准系数不现实工程里提供的一种做法是把校准系数存放在 Flash 的最后一页。STM32F103C8T6 内置 64KB Flash主程序一般用不满最后一页 1KB 正好用来存两个 float 校准值。校准过程分两步。先在传感器端接一个 100Ω 精密电阻替代 0℃ 标准电阻记录此时 ADC 平均值作为零点偏移的基准。然后换 200Ω 精密电阻记录第二个点算出增益修正系数。串口下发一条CAL指令固件就执行一次校准并把新系数写入 Flash。从此每次上电后温度换算时先读取这两个系数对 4.2 节查表函数输出做线性修正这样能把换器件带来的系统性误差拉回厂家典型范围。校准公式通常是线性的t_cal t_raw * gain_coeff offset_coeff。两个系数由两点法解一元方程组得出。下面的伪代码实现了这个过程// 两点校准用户先接100Ω电阻发 CAL 0再换200Ω发 CAL 1 void calibration_execute(void) { if (cal_step 0) { cal_raw_0 get_adc_average(); // 100Ω对应的ADC值 cal_temp_0 0.0f; // 理论温度0℃ cal_step 1; } else if (cal_step 1) { cal_raw_1 get_adc_average(); // 200Ω对应的ADC值 cal_temp_1 261.0f; // 200Ω在分度表里对应的理论温度 // 计算线性修正系数 gain_coeff (cal_temp_1 - cal_temp_0) / (cal_raw_1 - cal_raw_0); offset_coeff cal_temp_0 - gain_coeff * cal_raw_0; // 写入Flash最后一页 flash_write_calibration(gain_coeff, offset_coeff); cal_step 0; } }上电读取 Flash 有一个坑Flash 擦写的寿命约 1 万次校准操作不能频繁执行。工程里策略是只有收到 CAL 指令才写 Flash正常运行时只读不写。如果你要反复标定建议先接串口调试调完再固化避免把 Flash 写穿。还有200Ω 对应的理论温度不是 261℃ 这个「整数」而是查表得到的约 261.08℃写法上可以保留两位小数影响很小但严谨一点更好。5. 常见问题和避坑记录跑起来容易跑得准是另一回事5.1 现象AD 读数像心电图±5 LSB 跳动原因运放供电纹波大或者 ADC 参考引脚没有去耦电容。很多板子为了省事直接把 3.3V 系统电源接到 VREF而系统电源上往往叠加了 DC-DC 的开关纹波。跳动的 LSB 会对换算后的温度造成 ±0.2℃ 的抖动。解决VREF 与模拟供电之间加 10uF 钽电容和 0.1uF 陶瓷电容并联两者尽量靠近芯片引脚放置如果系统里有 DC-DC给运放供电串一个几十欧电阻再并大电容把纹波先滤一道。另外检查 AGND 和 GND 是否单点连接避免数字地噪声灌入模拟地。如果还是跳用示波器量 VREF 引脚纹波峰峰值超过 5mV 就基本是这里的问题。经验值是先把 VREF 的电容补上一半的 ADC 抖动问题都能消失。5.2 现象常温显示偏高 0.3~0.5℃装进密闭腔体后更是稳定偏高原因恒流源 1mA 在 PT100 上耗散功率约 0.2mW 到 0.4mW在密闭无风环境下自热效应明显铂电阻体会比环境温度高。自热温度与传感器封装有关陶瓷封装散热慢金属封装好一些。解决把激励电流降到 0.5mA增益翻倍自热功率降到四分之一。多数 0.1℃ 级测量系统用的是 0.5mA 或更低的 200μA。这是我的血泪经验第一批样机在开放桌面上测都正常装进设备外壳后温度集体偏高半度查了半天才发现是自热。改完这个参数之后增益、满量程和分度表上限要重新对一遍否则 250℃ 对应电压会超出 ADC 量程。工程里留了 EXC_CURRENT 宏就是方便做这个切换的。5.3 现象传感器脱线后数值飘到满量程或直接归零还会误触发热保护原因PT100 开路后放大输入端悬空运放输出偏向某侧供电轨ADC 读到 0 或 4095两种结果都可能被当成超温或低温。比如有的系统会把这个值当作 300℃ 触发超温报警直接停机。解决把超量程判断纳入固件。adc_value 小于阈值下限或大于上限时直接输出错误码而不是换算温度并在串口发出TERR。判断阈值不要取恰好 0 或 4095留 2% 余量因为放大电路正常工作时 ADC 读数不会跑到极端值附近。工程里建议把这两个阈值也做成宏方便量产整定。如果没有这段逻辑断线故障的表现是随机温度现场排查起来非常痛苦。5.4 现象靠近变频器或电机时读数短时跳变几秒内恢复不了原因50Hz 工频干扰通过长线耦合进来。PT100 三根线如果和动力线走在同一桥架里感应电压会高出信号自身几十倍。这个干扰进入运放后因为运放带宽足够干扰会一路传到 ADC 输入端。解决接线要尽量双绞S 和 S- 绞合在一起V 单独走信号线上加共模电感效果更好。软件层面把 DMA 采样次数从 16 加到 64等效于对 50Hz 周期做多次平均工频分量能被明显压制但温度响应会变慢需要按工况折衷。不要指望只调增益就能解决这是物理层问题软件平均只是补救。现场实在改不了布线也可以在运放后端加一个截止频率 10Hz 的二阶低通硬件上把干扰挡在 ADC 之前。5.5 现象上电前几分钟温度缓慢下降然后才稳定原因运放到稳态需要时间基准源也有温漂曲线机器刚从冷库里搬出来或者刚开机时电路自身温度还在爬升。PT100 本身没问题是电路板的温度没到工作点。解决在固件里延长开机预热时间比如上电后延时 30 秒到 60 秒再输出有效温度。如果是电池供电的低功耗设备预热时间要缩短那就在恒流源开启后让 ADC 连续转换但丢弃前 50 个样本把瞬态稳定时间滤掉。工程里用一个 10 位计数器实现预热期间串口输出T--避免上位机误判。5.6 这些坑的排查顺序如果现场读数异常按下面的顺序排查比逐个试快得多次序检查项工具1VREF 电压是否稳定 2.5V万用表2ADC 引脚波形有无毛刺示波器3运放供电纹波示波器 AC 档4三线制线序是否接对万用表通断档5传感器阻值是否正常万用表电阻档这个顺序遵循的思路是先确认参考和供电再查信号链路最后才怀疑传感器。大多数「温度不准」的案例根因都在前三步。6. 拿电阻箱做验证没有恒温槽也能把精度调到 0.1℃6.1 电阻箱逐点验证步骤恒温槽不是每个开发室都有但电阻箱很容易借到。验证时把 PT100 拆掉用电阻箱直接接到三线制端子从 80Ω 打到 300Ω每 10Ω 一个点记录固件输出的温度值和理论温度对照。理论温度可以用查表法反查例如 80.31Ω 对应 -50℃138.51Ω 对应 100℃。打完所有点之后画一条偏差曲线如果偏差整体平移调零点如果角度偏转调增益。这里有一张典型的验证记录表样式现场可以直接套用设定电阻理论温度固件读数偏差绝对值100.00Ω0.0℃0.3℃0.3℃119.40Ω50.0℃49.8℃0.2℃138.51Ω100.0℃100.2℃0.2℃175.84Ω200.0℃199.6℃0.4℃如果偏差整体在 0.5℃ 以内对一般工业监控够了如果项目要求 0.1℃需要继续做两点校准。这个验证方法有个好处它排除了传感器本身的不确定度只验证信号链和固件。如果电阻箱打点后误差很小而现场接入真实 PT100 后又出现偏差那就是传感器质量问题跟电路无关。做电阻箱验证时建议用四线制电阻箱避免夹持电阻不可忽略如果手头只有两线制电阻箱把导线阻值先测出来再修正曲线。6.2 增加一个校准命令让现场维护更省力工程里可以再加一个串口命令当用户端进入校准模式后先在端子处接 100Ω 标准电阻发CAL 0固件记住此刻 ADC 均值换 200Ω 标准电阻发CAL 1固件算出线性修正系数并写入 Flash。这样现场维护人员不用拆机只带一个标准电阻盒就能完成校准比寄回厂家省太多时间。写入 Flash 部分的代码不复杂关键是增加操作前校验收到命令后先擦除再写入写完后回读比对不一致就返回错误码。擦写期间关闭 ADC 中断防止写入被采集中断打断导致半写状态。校准过程中串口要打印进度提示比如CAL_0_OK、CAL_1_OK方便现场人员确认操作有效避免盲写。6.3 最后的习惯从那以后我每次拿到新的传感器或新 PCB都强制自己走一遍电阻箱逐点验证再上现场。这个动作救过我好几次有一次就是因为反馈电阻一颗贴片用错批次整板增益偏了 4%如果没有逐点曲线估计要等到客户现场才发现。后来我把验证表存成固定格式随代码一起归档量产的每一批板子都有据可查。希望这套流程和代码里的坑能帮你少走几步弯路希望帮到你。本文还有配套的精品资源点击获取