资讯动态

STM32+AD7124多路热电偶/PT100测温系统设计

发布时间:2026/10/19 6:04:57 来源:尧图企业网站定制
1. 项目定位为什么选 AD7124 搭档 STM32 做多路测温先交代一下这个项目的背景。我之前在做一个工业现场的分布式测温板卡要求同时支持多路热电偶输入并且预留铂电阻通道作为比对和冷端采样。测温范围从零下几十度到一千多度精度要求比较高不是那种“差不多能用”就行而是要能进产线标定、能出数据的级别。当时第一版方案用的是仪表放大器加独立 ADC外围电路堆得很大通道一多就非常痛苦。后来换了思路把核心统一到一片 AD7124 上用 STM32 做控制器整个信号链一下子清爽了很多。为什么选 AD7124 而不选其他 ADC核心原因是它把太多东西集成进去了。AD7124 是 24 位 Sigma-Delta ADC自带可编程增益放大器支持 8 路差分输入或者 15 路单端输入内置可配置激励电流源还有内部基准源和热电偶冷端补偿用的片上温度传感器。这基本上把测温需要的模拟前端全部包圆了。对于热电偶这种微伏级信号PGA 必须够好AD7124 的最低量程档可以做到正负 39mV这个量程下对 K 型、J 型、T 型这些常见热电偶都非常合适。配合片上温度传感器做冷端补偿硬件上不再需要额外接一颗数字温度传感器设计上能省不少事。STM32 这边承担的任务就是通信与数据处理。AD7124 对外是 SPI 接口STM32 做主机按寄存器配置巡检各通道把原始码值读回来之后做滤波、标定、线性化、冷端补偿一系列运算。数据量并不大一个通道也就是 4 字节的码值STM32 的资源完全够用。选 STM32 的另一个好处是生态好不管是从标准库切到 HAL 库还是直接操作寄存器资料都多踩坑也容易找到参考。而且 STM32 的 SPI 速度比起 AD7124 的通信能力高很多不存在瓶颈问题你可以用很低的 SPI 速率换稳定性的同时保持足够高的刷新率。这个方案对什么场景适配最典型的就是多路温度采集仪、老化测试设备、环境试验箱的通道板还有工业过程控制的温度采集模块。它的好处是板子可以做得比较小通道密度高校准逻辑可以全部放在软件里量产时只需要做一次逐通道校准参数存到片内 Flash 或者外部 EEPROM 即可。如果你是在做单路测温那用个专用的热电偶放大器芯片可能更简单但一旦通道数量上来了“ADC 加 MCU”的架构优势就非常明显成本分摊下来也更划算。2. 热电偶与铂电阻的测温原理以及为什么冷端补偿绕不开2.1 热电偶的基本测量关系热电偶测温的原理是塞贝克效应两种不同金属导体构成闭合回路当两个接点温度不同时回路中会产生热电动势热电势。一端放在被测温区叫测量端热端另一端处于环境温度或者某个参考温度叫参考端冷端。实际测量时我们永远只能测到“热端与冷端之间温度差产生的电动势”而不是直接得到热端的绝对温度。这里有个关键点如果你把冷端放在室温下室温本身是会漂的。上午 25 度下午 35 度同样的热端温度下你测出来的电动势都不一样。所以测温必须知道冷端温度然后把冷端温度对应的热电势补偿回去才能得到实际温度。这就是冷端补偿CJCCold Junction Compensation的本质。对于 K 型热电偶来说热电势大约是 41 微伏每摄氏度左右不同温度区间略有差异。也就是说如果冷端温度误差 1 度对应到热电势就偏差 40 多微伏。在 AD7124 的 39mV 量程下这个偏差大概是满量程的千分之一折算到温度是实实在在的 1 度。所以冷端补偿如果做得不准不管你 ADC 多好、线性化精度多高最后的温度读数都是白搭。2.2 Pt100 在方案中承担的两个角色Pt100 在这个系统里不是普通的外部传感器它承担了两个作用。第一个作用很简单直接就是作为独立的测温通道测介质温度比如测环境温度、测管道温度。第二个作用就很有意思了——把 Pt100 接到冷端附近用它来测冷端温度也就是热电偶的参考端温度。为什么用 Pt100 来测冷端而不是直接用 AD7124 的片上温度传感器片上温度传感器的精度一般在正负 1 摄氏度左右有些场合够用但如果你要做高精度的热电偶测温冷端温度误差会被直接叠加到最终结果里所以最好用一个外接的、经过校准的 Pt100 来测冷端。Pt100 在 0 到 100 摄氏度范围内的线性度很好阻值变化约 0.385 欧姆每摄氏度配合 AD7124 的激励电流源做比例测量可以实现很高的冷端测温精度。这也解释了为什么这个项目同时要保留三线制和四线制。因为冷端 Pt100 的引线如果比较长导线电阻本身就会引入误差。三线制可以抵消大部分引线电阻的影响四线制则把引线电阻彻底排除在外。后面我会专门讲这两种接法的电路设计和程序实现上的差异。2.3 AD7124 片上温度传感器还能用来干嘛AD7124 的片上温度传感器其实也不鸡肋它可以直接测芯片结温精度大概正负 2 度。在实际使用中我通常拿它做自检和冗余。比如系统上电的时候把片上温度和外部 Pt100 测到的冷端温度对比一下如果差异超过 5 度就说明外部传感器或者接线有问题可以主动上报故障。这比单纯依赖一个传感器可靠很多也算是一种低成本的故障诊断手段。3. 前端模拟电路设计从热电偶到 ADC 的完整信号链3.1 热电偶输入通道的电路结构热电偶输入通道的设计很多新手会忽略一个问题热电偶本身是浮地的它和系统地之间没有直流通路。如果 ADC 是差分输入输入引脚如果没有偏置电流路径共模电压漂移会导致读数极不稳定甚至漂出量程。这个问题的标准解法是给每个热电偶差分输入端加一个对地的偏置电阻。通常的做法是在热电偶正端和负端之间跨接一个大电阻比如 100K 到 1M 欧姆同时在某个输入端到 AGND 之间也接一个电阻提供一个直流泄放路径。AD7124 的输入偏置电流很小这个偏置电阻的阻值不需要太低高了反而减少对热电偶微弱信号的负载效应。还有一个非常容易被忽略的点热电偶输入的 EMI 滤波。工业现场经常有变频器、电机、开关电源这些设备会产生很强的共模噪声。AD7124 是 Sigma-Delta ADC它虽然对工频干扰有一定抑制能力但射频干扰进入 ADC 后可能会被混叠到低频段。所以在输入端加共模滤波电容和差模滤波电容是必须的。我一般在每根热电偶输入线上串联一个 100 欧姆的电阻然后在差分端之间并联一个 10nF 电容在每线到地之间并联 1nF 电容。这个组合对射频干扰有不错的抑制效果同时不会明显拖慢信号的建立时间。3.2 Pt100 三线制接法原理与电路先解释一下为什么会有三线制这个东西。Pt100 是电阻传感器你要测它的阻值就需要给激励电流流过它。激励电流从 ADC 流出经过导线到 Pt100再经过另一根导线回到传感器激励端。不管是走电流的还是测电压的回路只要有导线电阻就会产生额外的压降而这个压降会被 ADC 当成 Pt100 的电阻电压的一部分引入误差。三线制的巧妙之处在于它用三根线两根走激励电流一根作为电压采样线。实际接法是ADC 的激励电流源 IOUT1 接一根线到 Pt100 一端记为 APt100 另一端记为 B分出两根线一根接模拟输入 AIN 作为电压采样另一根接回 ADC 的 IOUT2 电流汇点。在 A 端激励电流流过导线电阻后到 Pt100所以 A 端的电压实际上包含了 A 端导线的压降在 B 端采样线上几乎没有电流流过ADC 输入阻抗极高所以 B 端的电压就是 Pt100 另一端的真实电压。这样测得的电压差 Pt100 电压 V_A线阻压降也就是说 A 端导线电阻的影响还在。如果你把激励电流源设计成双极性同时流出 IOUT1 和 IOUT2让两根激励线上的电流相等那么两条导线的压降理论上可以相互抵消。AD7124 支持配置激励电流源为两个独立的源或者一源一汇这个项目中我采用的就是双激励源方式配合差分输入端分别测量实现近似补偿。3.3 Pt100 四线制接法原理与电路三线制已经够好了为什么还要上四线制很简单因为强迫精度。在温度范围跨度大、导线长度差异大的场合三线制的补偿效果依赖于两根导线电阻的匹配程度如果一根线是 0.5 欧姆另一根是 0.8 欧姆补偿就不完全。四线制彻底绕开了这个问题。四线制的接法激励电流从 IOUT1 出发沿第一根线到 Pt100 的 A 端从 B 端沿第二根线回到 IOUT2。电压采样则完全独立AIN 通过第三根线接到 Pt100 的 A 端AIN- 通过第四根线接到 Pt100 的 B 端。采样回路没有电流流过所以采样线上的导线电阻不产生压降而 Pt100 两端测到的电压就纯粹是 Pt100 自身产生的电压。这个方法的精度只取决于 ADC 的失调和增益误差跟导线电阻基本无关。四线制的代价就是多了一根线而且对 ADC 的激励电流精度要求高了一点——电流源本身的精度直接影响激励电流值的稳定性如果激励电流漂移电压和阻值的换算就会出现系统性偏差。AD7124 的激励电流源可以配置为稳定输出配合内部的校准寄存器实际使用效果不错。但要注意一点激励电流不能太大否则 Pt100 会因为自热效应升温导致测出来的温度偏高。一般 Pt100 的激励电流建议不超过 1mA我通常用 250uA 或者 500uA自热误差可以控制在小数点后面几位。3.4 八种热电偶的量程配置与 PGA 档位选择AD7124 的可编程增益放大器有多个档位最低能到正负 39mV最高能到正负 2.5V 量程。对不同的热电偶最高热电势不一样所以要选择合适增益尽量让信号在满量程内最大化利用 ADC 的分辨率又不至于削波。做一个对比热电偶类型测温范围最大热电势推荐 PGA 档位B 型250°C 到 1820°C约 12.15mV±39mV 或 ±78mVE 型-200°C 到 1000°C约 76.36mV±78mV 或 ±156mVJ 型-210°C 到 1200°C约 69.55mV±78mVK 型-200°C 到 1372°C约 54.87mV±78mVN 型-200°C 到 1300°C约 47.51mV±78mVR 型-50°C 到 1768°C约 21.10mV±39mVS 型-50°C 到 1768°C约 18.69mV±39mVT 型-200°C 到 400°C约 20.87mV±39mV选择原则其实很简单在确保信号不超量程的前提下用最接近满量程的低档位这样等效输入噪声最低分辨率最高。比如 K 型热电偶最大热电势 54.87mV如果你用 ±39mV 档就会削波得用 ±78mV 档。而 T 型最大只有 20mV 左右用 ±39mV 档就非常舒服。有一个容易被忽略的问题热电偶本身输出的电压很小而量程档位的选择还跟 PGA 的增益漂移有关档位越高增益误差越大。所以不要觉得“反正有漂移我可以校准”要在设计时直接挑合适的档位减少误差源数量。4. 固件架构剖析通道配置、采样调度与数据处理4.1 AD7124 寄存器配置的关键细节AD7124 的寄存器挺多但值得深究的核心就那么几个。我先把寄存器配置的关键流程拆解一遍大家在移植到自己的工程时有个参考。首先是复位。上电之后给 AD7124 发送一堆连续的 1至少 64 个时钟周期可以进行复位或者通过写复位命令。我习惯在每次初始化 SPI 之后先发送复位序列确保芯片状态是干净的。复位之后建议等待一些时间大概 10ms 左右让内部基准源和振荡器稳定下来。然后是配置 ADC 控制寄存器。这里主要是选择工作模式、数据输出速率、滤波模式、基准源类型还有使能内部温度传感器。在 AD7124 中你要为每个通道配置一个或多个通道寄存器确定该通道的模拟输入引脚、增益、输入类型差分还是单端、转换开始与否以及该通道使用的基准源。每个通道寄存器的位域配置如果不仔细很容易出现“读数一直是零”或者“读数乱跳”的问题。举例来说K 型热电偶接到 AIN0 和 AIN1配置通道 0我实际用的配置代码精简版是这样的void AD7124_Init_RTD(void) { // 复位 AD7124_Reset(); // 配置 ADC 控制寄存器 // 2.925 SPS Sinc4 滤波模式 // 外部基准源低功耗模式 AD7124_Write_Reg(REG_ADC_CTRL, AD7124_ADC_CTRL_DEFAULT); // 配置通道 0AIN0 与 AIN1 差分输入PGA8接到外部基准源 uint32_t ch0 (AD7124_PGA_8) | (AD7124_CONFIG_REF_EXT) | (AD7124_CONFIG_INPUT_P_AIN0) | (AD7124_CONFIG_INPUT_N_AIN1) | (AD7124_CONFIG_CHANNEL_0); AD7124_Write_Reg(REG_CH0_MAP, ch0); // 配置设置寄存器 0 // 双极性、启用通道 0、滤波器更新等 AD7124_Write_Reg(REG_SETUP_0, AD7124_SETUP_USE_CH0 | AD7124_BIPOLAR_FLAG); }这里要注意几点AD7124 的 PGA 档位数据手册上以灰码形式存在寄存器里配置时要留意位序基准源如果悬空或者短路读数会非常异常这个问题后面排查里细说。4.2 连续转换模式与单次转换模式的取舍AD7124 支持连续转换模式和单次转换模式还可以配合 GPIO 触发。我这个项目里最终选了单次转换模式加巡检的软件调度方式。为什么不用连续转换因为多个温度通道的刷新率要求其实不高一般一秒刷新几遍就够了。单次转换模式在一个通道转换结束之后才启动下一通道天然规避了通道间切换时建立时间不足的坑而且还能依据每个通道的滤波模式单独配置。单次转换模式下需要做的是写通道映射开始转换然后轮询 STATUS 寄存器的 RDY 位等到数据寄存器可读时读取数据。巡检调度的流程我简化为下面几步先把所有通道对应的通道映射寄存器配置好并且关闭没有使用的通道避免杂散信号干扰。设置一个全局通道索引从 0 开始。启动当前通道的转换写入通道映射寄存器后将 DOUT/RDY 引脚拉低或者轮询状态位。等待 DOUT/RDY 引脚拉高或者置位标志此时可以安全读取数据寄存器。读取完成后索引加一并处理下一个通道。全部通道轮询完后进行冻干处理算温度然后再从第一个通道开始。这种方式的优点是逻辑清晰扩展性好。比如说要从 8 个热电偶通道扩展到 10 个只需要增加通道映射配置加两轮循环而已。很多人喜欢用连续转换模式配合 DMA但我觉得对于测温这种低速场景单次转换加轮询已经足够可靠了逻辑还简单。4.3 数字滤波从原始码值到稳定温度读数AD7124 内部的滤波器已经在处理工频干扰了但在工业现场还会存在残余波动。一般的做法是再做一次软件均值滤波或者滑动平均。我实测下来对 10SPS 左右的数据输出速率做 5 到 8 次的滑动平均效果已经很好温度波动可以从 0.3 度降到 0.05 度以内。推荐用滑动平均而不推荐简单平均因为简单均值滤波器的响应不够快。假设一个通道被 200 欧姆的电磁干扰脉冲打了一下简单平均要把所有数据排除才知道异常滑动平均会自动把异常值挤出窗口。在代码里实现其实很轻量#define FILTER_WINDOW 8 static int32_t filter_buf[FILTER_WINDOW]; static uint8_t filter_index 0; static int32_t filter_sum 0; int32_t AD7124_Smooth(int32_t new_sample) { filter_sum - filter_buf[filter_index]; filter_buf[filter_index] new_sample; filter_sum filter_buf[filter_index]; filter_index (filter_index 1) % FILTER_WINDOW; return filter_sum / FILTER_WINDOW; }当然这个滤波窗口大小不是死板的要看最终需要多快的响应。我在做老化测试设备的时候温度变化率很慢窗口可以给到 16 甚至 32。但如果是做快速温度循环测试窗口给大了就会让温度读数严重滞后这时候窗口就得小一些否则 PID 控制器很容易过冲。4.4 冷端补偿的算法与实现细节热电偶冷端补偿的算法本质上有两种思路一种是把冷端温度直接转换为对应热电势做电压加和然后反查温度另一种是用补偿的经验公式直接从热端电压和冷端温度两个变量算出最终温度。第一种思路更通用是因为它依赖标准化查表对每种热电偶类型都成立而且程序可以直接使用 NIST 生成的表格。具体流程是这样的先读取冷端温度 T_cold。假设用 Pt100 四线制采集得到阻值后查分度表得到 T_cold。针对当前工作热电偶类型查该类型在 T_cold 温度下的热电势值 E_cold。读取 ADC 转换后的热端热电势值 E_hot_raw这个是差分输入测到的。最终热电势 E_total E_hot_raw E_cold。用 E_total 反查该类型热电偶的分度表得到热端温度。这个流程在代码里对应到三个查表函数分别是铂电阻分度表查找、热电偶正向查表温度转电势、热电偶反向查表电势转温度。数据量不小所以我在 STM32 的 Flash 里存了多项式系数表或者稀疏度数表运行时用牛顿迭代或者插值算法求解。有一个很关键的实现细节冷端温度在读取之后一定要和热电偶类型匹配。比如冷端是 25 度对 K 型来说25 度对应的热电势约是 1.0006mV而对 J 型则是 1.277mV。所以每次切换热电偶类型时都要重新查一遍当前冷端温度对应的电势而不是复用上一次的结果。这一点如果写代码时图省事就会引入随环境温度变化的系统误差。冷端温度本身的测量精度要求有多高粗略估算一下冷端温度误差 1 度对 K 型热电偶的斜率为 40 微伏每度左右折算到总电压的影响就是 40 微伏换算成温度也大约是 1 度。所以冷端 0.1 度的误差大概对应 0.1 度的最终读数误差。这个线性关系在不同热电偶上的比例不同但对大多数热电偶来说冷端要做到 0.1 度以内用四线制 Pt100 是可以的三线制则要看线长和匹配置。4.5 标定与自校准不能省略的那一步AD7124 虽然出厂做了校准但板子上的电阻容差、基准源精度、PCB 布线引起的误差还是存在的。所以项目里必须做一次系统级标定。我的做法是对每个热电偶通道在 0mV 输入输入端短接时采集原始码值得到失调。用一个精密电压源输出标准电压通常是满量程的一半或者 80% 量程点采集码值计算出增益。把校准系数存储在 STM32 的 Flash 中作为出厂参数。使用 AD7124 内部校准功能也是一条路径但内部校准只能校准 ADC 本身不能校准外部电路的失调。系统级校准才能把外部电路误差一并吸收。所以我在工程里提供了两种校准模式一种是快速自校准利用 AD7124 的内部校准模式另一种是完整的系统校准需要接标准源。这里提示一下AD7124 的校准命令需要按顺序写入校准寄存器而且校准期间不能切换通道。如果多通道都要做系统校准就要一次只对一个通道操作校准完成后再换下一个。工程源码里我封装了这几个函数AD7124_SelfCalibrate()、AD7124_SysOffsetCalibrate()、AD7124_SysFullScaleCalibrate()。调用的时机一定要在通道配置完成后进行。5. 三线制与四线制测温方案的完整实现5.1 三线制 RTD 测温和热电偶冷端补偿的结合三线制 Pt100 在本项目里是主力因为它比四线制少一根线接线方便而且对于大多数测温距离不太长的场景精度足够。我接三线制 Pt100 时采用了一个比较讲究的接法ADC 的差分输入通道 AIN2 和 AIN3 分别引两根线一根接 Pt100 的 B 端作为检测电压正端一根接 Pt100 的 A 端作为检测电压负端激励电流源的一根从 AIN2 方向流经 Pt100另一根从 IOUT2 方向走一个单独的回路线。电流源本身由一个运放供给配合差分测量可以抵消大部分线阻。程序方面要注意三线制方案仍然需要一个“假想中点”。也就是说你要假设两根电流线的电阻相等才能完成补偿。为了自适应这种不确定性我加了引线电阻检测功能——用 ADC 在不上激励电流的情况下测量两端电压再在加激励时测一次差值得出引线电阻的具体值然后软件补偿到阻值计算中。其实现在很多集成 RTD 芯片内部已经做了这个动作但 AD7124 这个级别你只能自己动手做一次“开尔文优化”好在这部分运算量不大。5.2 四线制 RTD 测温的高精度模式四线制 Pt100 的模式我用在计量级比对通道上比如用这个通道来标校热电偶冷端或者作为整个系统的温度基准。四线制的电路连接和配置方式前面已经讲了这里说一下程序处理。四线制测出来的电压值和电流源激励电流的比值就是电阻值。为了保证精度我在程序中记录激励电流源的设定值和实际校准值。AD7124 的激励电流源虽然有边界漂移问题但通过对一个已知精度电阻比如 100 欧姆 0.01%做测量可以反推出实际电流值进一步补偿到后续运算中。这里有一个加分技巧在数据采集时把 ADC 的正负极输入信号交换一下或者采用正反激励轮流测量取平均可以消除 ADC 失调电压和 1/f 噪声的影响。AD7124 支持切换极性实际上就相当于硬件级的斩波。启用这个选项之后四线制测量的重复性可以提升很多长期漂移也明显改善。5.3 两种方案的误差对比与选型建议三线制和四线制在不同场景下的选择我整理了一个对比表对比项三线制四线制引线数量3 根4 根补偿原理依赖两根激励线电阻对称消除全部引线电阻影响精度等级0.05% 到 0.1% 级别0.01% 以下级别适用场景一般工业现场布距小于 10 米计量、校验、高精度比对程序复杂度需要额外引线电阻补偿相对简单读取即用成本少一根线接线端子少多一根线端子占用增加如果让我给一个通用建议通道密度高的产品用三线制就足够了一个 PT100 占用 3 个接线端子成本更低如果你需要做冷端补偿的高精度标准源直接用四线制。千万不要在三线制方案上去拼 0.01 级精度硬件原理上就决定了这个上限。6. 八种热电偶的类型切换与查表实现6.1 分度表的数据组织方式八种热电偶的分度表如果要完整存下来数据量其实不大。NIST 的标准表格一般是每隔 1 度或者 10 度输出一个电压值。工程里我采用了每隔 1 度存一个电动势值然后线性插值。这样每个热电偶类型的表占用几百个浮点数STM32F4 的 Flash 足够装下。表格存储我建议用 const 数组放在 Flash 里而不是存储在外部 EEPROM 或者 SD 卡中因为温度转换是高频操作Flash 读取速度远快于外部存储。如果用的是 STM32F1 系列Flash 容量小的型号要注意空间占用这种表可以用 uint16 存储微伏整数甚至用 int16 存增量值省一半空间。查表性能方面由于表格是按温度单调递增的可以用二分查找或者指数查找。对带符号的温度范围先做边界判断然后二分查找。整个查找时间在微秒级对 10 赫兹的采样速率完全无所谓。6.2 热电偶类型动态切换的实现工程里有一个全局变量用于记录当前工作热电偶类型类型代码枚举了八种。切换类型时有一个关键动作把通道映射寄存器重新写入选择合适的 PGA 档位然后把冷端补偿所用的分度表指针切换成当前类型对应的表。代码大致长这样typedef enum { TC_TYPE_B, TC_TYPE_E, TC_TYPE_J, TC_TYPE_K, TC_TYPE_N, TC_TYPE_R, TC_TYPE_S, TC_TYPE_T, } TC_Type_e; static const int16_t *thermocouple_table[8]; static const float *tc_max_mv[8]; void Thermocouple_SetType(uint8_t type) { g_active_tc_type type; // 更新 PGA 档位和通道寄存器 AD7124_ConfigChannelPGA(tc_pga_sel[type], type); // 切换查表指针 g_tc_table thermocouple_table[type]; g_tc_max_mv tc_max_mv[type]; }有个坑真的要提示切换热电偶类型之后如果当前通道已经执行到一半的转换要先复位转换状态机否则可能读到上一类型下的残余数据。我在调试时就遇到过切换类型然后马上读数据读数偶尔会跳变。解决办法是在类型切换函数末尾强制进行两次空转转换丢弃数据然后才允许上层读取温度。6.3 电动势反查温度的迭代实现查表是正向从温度找电动势反查就是从电动势找温度。由于电动势和温度之间不是严格线性关系反向查表我一般用牛顿迭代配合表格插值或者更直接地在表格中做一次反向扫描加一次线性插值。反向扫描的方式最简单从表格中找到当前电动势所在区间比如在第 i 度和第 i1 度之间然后线性插值。因为表格间隔是 1 度线性插值误差在热电偶非线性较强的区间段最大也不会太大。K 型热电偶在 500 到 1300 度之间二阶非线性可能导致插值偏差在零点几度的量级需要的话可以改用二分法两个小区间的二次插值。实际代码我会写成这样float Thermocouple_EmfToTemp(float emf, const int16_t *table, uint16_t table_len) { if (emf table[0]) return -200.0f; // 下边界 if (emf table[table_len - 1]) return 1372.0f; // 上边界 uint16_t low 0, high table_len - 1; while (high - low 1) { uint16_t mid (low high) / 2; if (table[mid] emf) low mid; else high mid; } // 线性插值 float t (float)(emf - table[low]) / (float)(table[high] - table[low]); return (float)low t; }实际项目中有的表用 mV 存有的用 uV 存。统一用 uV 整数存可以避免浮点误差。我自己更推荐用微伏为单位存 int32 数组这样在插值时计算都是整数最后再除以 1000 转成 mV速度和精度都更好。7. 完整工程源码的模块划分与移植方法7.1 源码目录结构我最终交付的工程源码按照功能模块划分成了这样几个目录BSP板级支持包含 SPI 驱动、GPIO 初始化、电源配置AD7124AD7124 的驱动包括寄存器读写、通道配置、转换状态机Sensor温度传感器层包含 Pt100 计算、热电偶分度表查表、冷端补偿算法App应用层包含温度任务调度、数据上报、诊断逻辑这样的划分对移植非常友好。假设你要换一个 MCU只需要改 BSP 层AD7124 驱动可以保持不变因为 AD7124 协议本身就是 SPI 标准只要你把 BSP 层的 SPI 读写接口替换掉即可。我建议所有硬件相关操作都封装成统一的接口比如HAL_SPI_WriteRead()驱动层只调用这些接口不要直接操作寄存器地址。7.2 移植到其他 MCU 的注意点AD7124 的 SPI 时序要注意时钟极性和相位。数据手册给的推荐设置是 CPOL0CPHA1Mode 1也就是说时钟空闲为低数据在第二个边沿采样。用 STM32 的话SPI 配置如下hspi1.Init.CLKPolarity SPI_POLARITY_LOW; hspi1.Init.CLKPhase SPI_PHASE_2EDGE; hspi1.Init.Direction SPI_DIRECTION_2LINES; hspi1.Init.DataSize SPI_DATASIZE_8BIT; hspi1.Init.NSS SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler SPI_BAUDRATEPRESCALER_64;很多移植失败的原因都是 SPI 相位没配对。AD7124 对 SPI 时序也有一定容错能力但不推荐依赖它。如果你用 HAL 库记得开启软件片选管理因为硬件 NSS 在某些芯片上会自动控制但 AD7124 的 DOUT/RDY 引脚是双向的接法不能混淆。还要特别注意 AD7124 支持 SPI 读写的规范写操作命令字是 0b00 寄存器地址 0读操作是 0b01 寄存器地址 0。很多人在读寄存器时忽略第二位结果一直读到同一地址的数据。7.3 工程中的调试接口设计调试输出我推荐走串口。一开始我用了重定向 printf 到 USART1后来发现频繁调用 printf 在中断上下文里会卡所以我自己封装了一个轻量级日志模块支持日志等级控制DEBUG 级别输出 ADC 原始码值INFO 级别输出温度值和补偿参数ERROR 级别输出异常。ADC 原始码值这个信息在调试阶段极其有价值。如果读取的温度值不对劲第一步永远是看原始码值而不是看转换后的温度。因为温度转换代码可能引入很多隐藏 bug而原始码值直接对应电路状态更容易定位问题。比如一个 K 型热电偶通道常温下应读到 100 至 200 微伏如果你读到几千微伏基本上就是接线错了如果读到零附近且不变化就要怀疑 PGA 或通道配置。7.4 从源码到产品的固件开发建议如果你准备把这个工程用于自己的产品开发有几点建议一开始就要规划好一是把校准参数做成可读可写的数据结构而不是硬编码。因为每台设备校准数据不一样硬编码意味着每台都要重新编译下载。我这边是定义了一个独立的 Flash 扇区专门存设备 ID 和校准系数上电时检查校验和如果非法则使用默认参数并上报警告。二是注意上电时序。AD7124 需要等一下供电稳定才能访问。如果你在主时钟初始化后立刻访问 AD7124很可能 SPI 通信失败。我在 BSP 的初始化函数里加了一个 200ms 延时这个延时对可靠上电是很有必要的。三是做好看门狗。测温设备一般不会崩溃但万一固件跑飞看门狗恢复是必要的。我在主循环中喂狗并且在 AD7124 通信模块中加入超时判断防止某个寄存器写死导致 while 死循环。8. 常见问题与调试实录8.1 读数一直是满码或零码这个问题在热电偶接入不当时特别常见。满码通常是差分输入被强制拉到某一个电源轨附近或者 PGA 档位配置过低导致信号超量程零码则可能是通道配置错误、SPI 时序错误、或者输入端短接且 PGA 失调为零此时理论码值也接近零。排查顺序我一般这样走先确认 SPI 通信是否正常读取 AD7124 的 ID 寄存器如果读回值和手册不一致SPI 配置有问题。然后确认通道映射寄存器的值是不是被正确写入用读回功能验证。接着检查输入引脚电压用万用表测 AIN 和 AIN- 哪个引脚有异常电压如果输入引脚悬空ADC 读到的可能是噪声随机值此时应该给输入加偏置电阻。有一个更深层的坑AD7124 的基准源输入引脚REF 和 REF-如果没接好比如基准源被短路ADC 读到的码值会异常。你必须确认基准源引脚的电压在合理范围内。这个问题的诡异之处在于ADC 内部有一个检测机制基准异常时状态寄存器会置位但很多工程师没去读状态寄存器的错误位结果一直在排查模拟输入通道浪费大量时间。8.2 冷端补偿误差大的典型原因如果你发现热电偶测温在高温段还能对上常温段误差很大那基本就是冷端补偿的问题。排查冷端补偿时我建议先把 AD7124 的片上温度传感器读数打出来再把外部 Pt100 读数打出来对比一下差值。如果差值超过 2 度请检查 Pt100 的接线和滤波电路。另一个冷端补偿的重大误差源是分度表的数据单位弄混。比如把 K 型的表用了微伏而其他类型的表用了毫伏如果程序在切换类型时没有统一换算单位误差会非常离谱。这种问题通过离线模拟可以很快发现固定冷端温度为 0 度给热端一个已知电压期望的补偿结果应该和实际输出完全一致。还有一点要强调冷端温度传感器放置的位置不应该紧贴发热量大的器件比如电源芯片或者 ADC 旁边。AD7124 本身温度可能比环境温度高几度片上温度传感器的读数可能无法代表真正的冷端环境温度。因此外部冷端 Pt100 应该尽量靠近热电偶接线端子放置才能代表真实的接线端温度。8.3 三线制 Pt100 测量读数抖动如果你用三线制但读数抖动先查激励电流源的稳定性。AD7124 的激励电流源直接输出电压从满量程回来之后电流稳定需要一点时间。如果数据采集速率太快每次切换激励源之后立刻启动转换读数就会波动。解决办法是每次启动转换前给激励电流源一段稳定时间或者采用“激励保持”的模式一直给电流不要频繁开关。另外一个抖动原因是引线电阻的补偿算法引入了噪声。三线制软件补偿如果每次都在变化的环境中测量引线电阻得到的就是带噪声的补偿值。我做了一点平滑处理引线电阻值只在通道切换时重新测量而且每 10 次采集才更新一次补偿值就不会受到瞬时噪声的干扰。8.4 八种热电偶切换后读数不变如果切换热电偶类型后读数完全不变极有可能是在切换时没有把当前通道的转换状态复位或者应用程序读取的是同一个通道寄存器的数据而没有更新。我曾经遇到过因为通道映射寄存器里的通道号没改其他通道寄存器的数据一直是老的值。解决方法是切换前先关掉所有通道的转换使能更新映射之后再重新使能。8.5 常见问题速查表现象可能原因排查方向全码或零码PGA 档位不合适检查通道增益配置和输入电压范围读数周期性抖动滤波参数不够或激励不稳检查滤波器设置、激励电流源冷端补偿误差大Pt100 位置不对或分度表单位混淆对比片上温度和外部温度传感器切换类型后读数不变通道寄存器配置未刷新强制复位通道映射并丢弃空转数据SPI 通信失败CPOL/CPHA 配置错误读取 ID 寄存器验证时序长期漂移明显校准参数丢失或未启用斩波开启极性切换模式检查校准存储9. 实测效果与一些个人心得这套方案做下来最终板卡的实测结果是K 型热电偶在 0 到 1000 度范围内配合四线制冷端 Pt100系统误差控制在正负 0.5 度以内三线制用于普通通道稳定后波动在正负 0.1 度以内。巡检所有通道一遍的时间大约 300ms对于常规温度监控完全够用。如果让我重新设计一次我会考虑这样一个改进点把热电偶线性化和冷端补偿的分度表数据放进一个外挂 Flash 芯片不占 STM32 内部 Flash 空间这样型号升级比较灵活换不同类型热电偶时不需要重刷固件只需要更新表数据。这个设计适合产品化程度高的项目。再分享一个比较玄学但真实有效的经验PCB 布局上热电偶接线端子和 AD7124 之间不要有任何高频数字信号线穿过。之前有一次我布线时 SPI 信号线在模拟输入下方走了一段结果热电偶在低温段出现周期性读数抖动后来把 SPI 线绕开问题完全消失。模拟地和数字地也尽量单点连接不要大面积铺铜混在一起。AD7124 的模拟电源要用 RC 滤波单独供电不要直接和数字电源接在一起。最后说一句关于工程模板的体会测温系统这种项目最怕的不是硬件坑或者是算法坑而是你做了一堆功能之后发现没有一套可靠的调试手段。我的建议是无论项目大小调试日志一定要从第一天就做好。你会发现当软硬件联合调试的时候有一份忠实记录 ADC 原始码值的日志比任何仿真器都好用。这套 STM32 加 AD7124 的方案只要把前面的这些核心环节吃透了后续扩展更多通道、更多类型其实都只是体力活。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑