
做工业温度测量和暖通空调HVAC系统集成的人应该都体会过那种“看着简单、做起来一地鸡毛”的采集板开发。传感器无非是PT100、PT1000或者K/N型热电偶但要把信号搬出来、转成精确温度、耐得住现场的长线干扰方案搭配其实很讲究。我手头这版温控采集模块主控用的STM32F303VE采集前端用的TI的ADS122U04IPWR——一颗24位的Δ-Σ ADC自带PGA、内部基准、激励电流源最关键的是它走UART而非SPI传感器模块和主板之间拉两根线就能通信。整套方案测PT100能做到±0.2℃以内测K型热电偶在冷端补偿做好时也能做到±0.5℃以内正好覆盖HVAC冷热水系统、风管温控以及电机轴承温度监测这类场景。这篇文章就把我的方案选型、电路设计、固件实现和现场调试经验完整写出来给正在做类似项目的人一个可以直接抄作业的参考。1. 整体设计思路这套ADCMCU组合到底解决了什么问题1.1 需求先行的方案定位做项目第一步不是选芯片而是把需求定死。我接到这个任务时甲方只给了六个字“多点温度采集”。但落地到现场需求就拆成了这么几条传感器类型既有PT100铂电阻又有K型热电偶不能做成两套硬件必须一块板子兼容。精度指标PT100通道要求±0.3℃以内热电偶通道在0~300℃范围要求±1℃以内HVAC水系统则希望回风温度和供水温度能稳定显示到小数点后一位。传输距离传感器到采集板之间的线缆长度从3米到30米不等模拟小信号长距离传输必须有对策。环境干扰现场有变频水泵、风机、接触器电磁环境不干净普通12位ADC根本顶不住。成本与维护整机要批量供货物料成本要压但也不能牺牲可维护性。这需求一看就知道MCU内部ADC不用想12位分辨率对热电偶的微伏级信号完全无能为力。必须搭一个独立的高精度信号链。ADS122U04这类芯片就是为这种场景准备的它把模拟前端该干的活全干完了精密基准、可编程增益、输入多路复用、激励电流源全集成在芯片里MCU只需要通过UART发几条命令、收三个字节的转换结果剩下的温度换算和逻辑控制交给STM32F303VE。1.2 ADS122U04 的核心价值拆解很多朋友一听24位ADC就觉得“精度肯定好”但24位只是必要条件不是充分条件。真正让这套系统能用的是以下这几个特性组合起来的效果可编程增益放大器PGA增益从1到128可调。热电偶信号满量程可能只有几十毫伏没有PGA就只能把信号先送外部运放放大这会引入额外失调和噪声。PGA内置后微伏级的温差信号也能被ADC精确量化。双匹配激励电流源电流从10µA到1.5mA可编程且两个电流源相互匹配。这是做RTD比例测量的灵魂。没有它PT100就得靠外部恒流源或电桥精度和温漂都难控制。内部2.048V基准省掉一颗外部基准芯片。虽然我在实际设计中还是留了外部基准的焊盘位但纯靠内部基准已经能拿到相当不错的结果。UART接口这其实是ADS122U04和它的孪生兄弟ADS1220最大的差异。SPI需要SCLK、MOSI、MISO、CS四根线在长距离传输时不仅占用GPIO还容易受干扰UART只要TX、RX两根线配合高波特率照样可以跑到1kSPS。对现场施工来说线少一根是一根。片内温度传感器热电偶冷端补偿需要测接点温度片内传感器虽然精度不算顶级但作为低成本方案完全够用后面我会细讲怎么用好它。ADS1220和ADS122U04的核心模拟前端几乎一样区别主要在接口。如果你手头资源是SPI充裕用ADS1220也行但如果你想把ADC放在传感器探头附近通过长线把数字信号送回主板ADS122U04是更省心的选择。1.3 STM32F303VE 为什么够用主控方面我选了STM32F303VE看中的不是它的ADC而是它的综合能力和性价比。Cortex-M4F内核带FPU72MHz主频512KB Flash、128KB RAM这在F3系列里属于大容量型号。温度线性化计算中涉及浮点多项式FPU直接硬件算不用软件模拟代码能简化不少。另外F303VE的串口资源丰富我一共挂了两个ADS122U04和一路RS485 ModbusUSART数量还有富余。如果你做多点采集建议把主控制器的串口数量和DMA通道数量提前算清楚避免选型时翻车。F303VE在这个项目里既要管理ADC采样时序又要跑Modbus协议还要做冷端补偿查表和线性插值整体负载大约在30%左右余量充足。2. 硬件电路设计接线和布局才是精度的分水岭2.1 ADS122U04 外围电路关键点ADS122U04采用TSSOP-16封装引脚不多但电源和基准处理不仔细后面所有精度指标都会打折。我的做法是AVDD和DVDD分开走线各自去耦。每个电源引脚都放一颗100nF陶瓷电容就近打孔到地再在芯片附近放一颗10µF钽电容或大容量MLCC做低频储能。AVDD和DVDD之间加了一颗600Ω/100MHz的磁珠数字侧的开关噪声不至于串进模拟侧。芯片底下铺了完整的实心地平面。不要为了美观把地铜皮切开Δ-Σ ADC对地弹噪声极其敏感。REFP和REFN引脚即便使用内部基准也要各放一颗100nF电容到地我用的是C0G材质容值稳定且温度系数小。RESET引脚通过10kΩ电阻上拉到DVDD同时引到STM32的一个GPIO方便固件做硬复位。上电后我习惯让MCU主动拉低RESET再释放确保ADC以已知状态启动。注意ADS122U04的数字接口电平取决于DVDD我直接把DVDD接到3.3V和STM32F303VE的IO电平完美匹配。如果DVDD接5V则STM32侧必须做电平转换否则会超出引脚耐压。2.2 PT100 三线制接法线长问题这样解决PT100是最常见的铂电阻温度传感器0℃时阻值100Ω温度每升高1℃阻值大约增加0.385Ω。两线制接法最简单但导线电阻直接叠加到传感器电阻上。我用的是20米屏蔽线两线制实测冷态就偏了1.2℃左右完全不可接受。所以RTD必须采用三线制接线并且要利用ADS122U04的双激励电流源做抵消。接线逻辑是这样的IEXC1输出激励电流经过第一根导线到达RTD的一端同时在RTD的这一端并联一根测量线接到ADC的正输入端。电流流过RTD后从另一端的导线流出再经过第三根线回到IEXC2。测量电压时正输入端的参考点是RTD本体而不是芯片引脚所以第一根导线上的压降不参与测量。低端的三线制和两线制差异主要体现在电流回路上关键在于两个电流源的匹配度。实际接线图如下以AIN0/AIN1作为差分输入为例IEXC1引脚 → 导线L1 → RTD高端RTD高端 → 导线L2 → AIN0INPRTD低端 → 导线L3 → AIN1INNRTD低端 → 导线L4 → IEXC2引脚等等严格来说这是四线制的接法。三线制和四线制的区别我来捋清楚。三线制是把L3和L4合并成一根线电流和电压测量共用低端引线。四线制则完全分开精度更高。我实际项目里传感器端做成四线引出但接插件只留三根线在端子处把IEXC2和AIN1短接在一起。这种半四线做法兼顾了现场布线和精度最终在20米线上误差小于0.1℃。2.3 热电偶接法偏置电阻和冷端测量K型热电偶输出的是微伏级热电势大约41µV/℃0~100℃的量程就只有4.1mV。这样的小信号必须用PGA增益64或128放大。接线本身不复杂热电偶的正负极分别接AIN2和AIN3即可但有几个细节必须处理热电偶是浮地信号源没有直流共模电位。我的做法是在AIN2正端与AVDD之间接一颗10MΩ偏置电阻把共模电平抬到接近电源电压的位置保证信号落在ADC允许的输入共模范围内。冷端补偿不能靠猜。K型热电偶测到的是热端与冷端的温差冷端温度每偏差1℃就是1℃的测量误差。用ADC片内温度传感器读冷端时必须保证芯片温度能代表接线端子处的实际温度。我在PCB上把接线端子尽量靠近芯片放置并且避免让高功耗器件比如MCU、电源芯片紧贴ADC。工业现场如果要求热电偶精度到±0.5℃以内我更推荐用外部PT1000做冷端补偿传感器贴在端子座底部读到的才是真正的接点温度。这一点我在第5章会展开讲实测数据。2.4 与 STM32 的 UART 连接ADS122U04到STM32F303VE之间只需要三根线TX、RX、GND。TX和RX交叉连接ADC的TX接STM32的RXADC的RX接STM32的TX。需要注意的是MODE引脚决定ADC在UART总线上的设备地址我把它直接接GND默认使用第一组地址。如果一条总线上挂两个ADS122U04第二个芯片的MODE引脚需要接DVDD选择另一组地址并且软件里发送命令时要带上地址字节否则两个从机都会响应。我用的是USART2波特率1152008位数据无校验1位停止位。这个波特率对应ADS122U04在1000SPS数据速率下完全够用不会成为瓶颈。连接时我还串了33Ω电阻在TX和RX线上起到轻微的阻抗匹配和限流作用调试时如果发现波形振铃明显可以调整这个阻值。3. 固件实现UART 协议、寄存器配置与数据读取3.1 寄存器配置的完整流程ADS122U04的配置寄存器和ADS1220大体兼容都是通过WREG/RREG命令读写。上电后我建议按以下顺序初始化硬件复位STM32拉低RESET引脚至少10µs再释放等待ADC启动完成。写CONFIG0寄存器设定PGA增益。RTD通道用增益4热电偶通道用增益64或128。数据速率我统一设在50SPS这个速率下数字滤波器对50Hz工频干扰有不错的抑制效果如果现场以60Hz为主就设60SPS。写CONFIG1寄存器设定正常工作模式选择是否启用内部温度传感器。写CONFIG2寄存器配置输入多路选择器决定当前通道是AIN0/AIN1差分RTD还是AIN2/AIN3差分热电偶配置基准源为内部2.048V配置电流源方向和大小。写CONFIG3寄存器使能内部基准配置两个激励电流源。RTD激励电流我设500µA热电偶通道不需要电流源就全部关闭。写UART配置寄存器确认波特率。默认115200通常不用改但如果要降速省电或升速提高吞吐必须严格匹配MCU侧设置。回读所有寄存器逐字节比对防止写入失败。写完配置后我还建议发送自校准命令。自校准能消除PGA的失调和增益误差尤其在热电偶小信号测量中效果明显。校准期间不能读取数据等校准完成标志或固定延时50ms后再进入正常转换。3.2 UART 命令帧格式和状态机ADS122U04的命令帧不是简单的“发一个字节、收三个字节”。协议里包含命令字节、可能的参数数据、以及一个CRC校验字节。我第一次用的时候没仔细看手册直接按裸串口方式发命令结果设备完全没反应后来抓波形才发现少算了校验字节。核心命令主要有这几个RDATA0x10读取一次转换结果从机返回3字节。RREG0x20 | 寄存器地址读寄存器从机返回1字节。WREG0x40 | 寄存器地址写寄存器主机需再发1字节数据。RST0x06软复位。STM32侧我用一个简单的状态机来接收。因为UART本身有字节中断接收流程可以这样组织typedef enum { RX_IDLE, RX_CMD, RX_DATA, RX_CRC } uart_rx_state_t;发送RDATA命令后把接收状态切到RX_CMD等待第一个字节收到后切到RX_DATA继续收3字节的转换结果最后收CRC校验字节根据计算结果判断本次读取是否有效。这个状态机代码量不大但能避免因干扰导致的数据错位。如果CRC校验连续失败多次说明通信链路有问题我会上报错误状态而不是继续使用脏数据。3.3 连续转换模式下的数据读取节奏ADS122U04支持单次转换和连续转换两种模式。我调试阶段用单次转换方便观察每次命令的效果正式固件里用连续转换模式让ADC自由运行然后由MCU按固定周期发RDATA取数。读取时序上要注意三个字节的拼接顺序。返回数据是MSB在前也就是先收到最高字节最后收到最低字节。三个字节拼成一个int32后还需要考虑24位补码的符号扩展。ADS122U04输出的是24位二进制补码格式我常用的拼接代码如下int32_t raw (rx_buf[0] 16) | (rx_buf[1] 8) | rx_buf[2]; if (raw 0x800000) { raw | 0xFF000000; // 符号扩展到32位 }我取数的时钟由MCU定时器驱动比如100ms取一次数据。因为ADC数据速率是50SPS也就是20ms出一笔新数据100ms周期正好能保证每次拿到的都是新鲜结果又不会频繁打扰CPU。如果未来把数据速率提高到1000SPS取数周期也要相应加快同时UART中断和DMA的负载要重新评估。3.4 用DMA减轻CPU负担STM32F303VE的USART2支持DMA收发。我最终版本把RDATA读取改成了DMA方式MCU每100ms触发一次定时器启动一次USART的DMA接收长度4字节数据3字节CRC 1字节接收完成后在DMA中断里做CRC校验和温度换算。这样CPU几乎不用管字节级的中断主循环可以专心跑Modbus协议栈和人机交互。如果你刚开始调试不建议直接上DMA先用中断方式把协议跑通确认寄存器配置和时序都正确后再优化传输效率。这样出问题时排查范围更小。4. 从原始码到真实温度算法、公式与标定实战4.1 比例测量法的数学推导RTD测量必须用比例法这是整个精度体系的地基。比例法的核心思路是用同一个激励电流同时流过RTD和一颗精密参考电阻RREF然后把RTD上的电压和参考电阻上的电压做比值。因为电流是同一个电流的绝对值波动会在比值计算中自然抵消。在ADS122U04上配置IRSET让IEXC输出500µA电流流过RTD产生电压VRTD同时流过RREF产生参考电压VREF。ADC输出的数字码近似等于CODE (VRTD / VREF) × 2^23代入VRTD I × RRTDVREF I × RREF电流I约掉后得到RRTD (CODE / 2^23) × RREF这里RREF就成了唯一的基准它必须选低温漂高精度电阻。我用的是一颗0.1%精度、±10ppm/℃的金属箔电阻阻值3.32kΩ。为什么要3.32kΩ而不是2kΩ因为我希望0℃时VREF在1.66V左右既给满量程留了余量又不会因为电流源负载能力不足导致压降异常。换算法则的校验电阻温漂直接影响RTD通道的全量程精度这块不能省。PT100在0℃时CODE的估算值大约是252000200℃时约439000。24位ADC看似只用了很小一段量程但分辨率仍然极高。按RREF/2^23折算1个LSB对应的电阻变化约0.4mΩ折合温度不到0.002℃。当然实际噪声会把有效分辨率拉低到0.01~0.02℃级别但应对±0.3℃的指标仍然余量充足。4.2 PT100线性化查表为主公式校验为辅PT100的温度-电阻关系不是绝对的线性0~850℃范围内可以用Callendar-Van Dusen方程描述但工程上我更推荐IEC 60751标准电阻表。我的做法是在STM32里存储一份从-50℃到250℃、每1℃一个点的标准电阻表这部分Flash占用大约600字节对512KB Flash来说可以忽略。查表时先计算出RRTD然后用二分查找定位到温度区间再做线性插值$$T T_L (R_{RTD} - R_L) / (R_H - R_L) \times 1$$其中TL是区间起点温度RL和RH分别是起点和终点的标准电阻值。查表法的好处是透明、可控、没有高次多项式溢出的风险将来如果要支持PT1000只需要换一张表并调整激励电流。我还把CVD方程写成了独立函数在产线标定时用它来生成校验点两个独立算法互相验证避免同源错误。4.3 热电偶冷端补偿的实现细节热电偶测温必须做冷端补偿这个环节误差最大。我踩过的坑是一开始直接用ADS122U04内部温度传感器做冷端温度在实验室恒温环境下一切正常一到现场板子放进控制柜MCU和高频开关电源一发热内部温度传感器读出的冷端温度比端子座实际温度高了3~5℃热电偶整体偏高3℃多。后来改成外部PT1000冷端补偿方案在端子座底部贴一颗PT1000用另一路模拟输入通道测量PT1000的引线越短越好。固件里冷端补偿的处理流程是从ADC读取热电偶通道的热电势E_meas。从ADS122U04内部温度传感器或外部PT1000通道读取冷端温度T_cjc。根据热电偶类型查表得到冷端温度对应的热电势E_cjc。总热电势E_total E_meas E_cjc。用E_total反查温度表得到真实热端温度。K型热电偶的查表范围我做到−50~500℃步长1℃线性插值足够满足±0.5℃精度。如果项目要求更高可以使用NIST多项式但多项式在高阶部分容易发散必须严格控制输入范围并做分段处理。冷端温度采样的更新频率不用太高环境温度变化不会瞬间突变我每10秒更新一次冷端值。这样既减少了ADC的通道切换次数也降低了计算开销。4.4 软件滤波和标定流程硬件采集头处理得再好软件滤波仍然是最后一道防线。工业现场最常见的干扰是50Hz工频及其谐波ADS122U04的数字滤波器在50SPS速率下已经对50Hz有不错的抑制但我还是在软件里加了一阶低通y[n] y[n-1] α × (x[n] - y[n-1])α取0.1~0.2时响应时间大约0.5~1秒对HVAC温度控制来说完全够用还能滤掉变频器起停引起的尖峰干扰。如果你需要更快响应α可以调大如果更关注稳定显示可以把α压到0.05温度显示几乎纹丝不动。标定是我在生产前必做的一步。RTD通道我通常用标准电阻箱做三点标定0℃对应100Ω、50℃对应119.4Ω、100℃对应138.51Ω。记录每个点的CODE值和换算出的电阻误差然后用最小二乘法拟合一条一次修正曲线把增益误差和失调误差同时补偿掉。热电偶通道则用台式干体炉放一个标准探头在100℃和300℃两个点做对比修正冷端补偿和查表残余误差。做过标定之后整套模块的批次一致性会好很多换传感器也不至于出现系统性偏移。5. 现场调试常见问题、排查流程与经验速查5.1 读数全零、全满或持续漂移这类问题出现频率最高绝大多数不是ADC坏了而是配置或接线有问题。我总结了一套排查顺序第一步回读所有配置寄存器确认实际值和你写入的值一致。UART传输过程中如果CRC校验没过寄存器可能根本没写进去。第二步把输入端AIN和AIN−短接读到的CODE应该接近0。如果偏差很大说明PGA失调未校准先做自校准再看。第三步把AIN接到一个已知电压比如1.0V对照理论CODE判断量程和基准是否正常。第四步检查输入共模电压是否在允许范围内。热电偶如果没加偏置电阻共模电压可能接近地电位超出输入范围后读数会异常。读数漂移方面最常见的原因是AVDD纹波大或参考电阻温漂。用示波器AC耦合看AVDD的纹波如果超过10mV就要检查电源去耦电容和磁珠位置。RREF温度每变化1℃RTD通道误差约1.2℃因为RREF在公式里是分母所以RREF要远离发热元件必要时给它做个铜皮散热。5.2 冷端补偿不准的实战分析冷端补偿不准的表现是热电偶测量值整体偏高或偏低且偏差随控制柜温度变化。我在第4章已经提过内部温度传感器的问题再补充一个实测案例控制柜里MCU满载运行时芯片温度比端子座高4.2℃MCU休眠时差距缩小到1.1℃。这种随负载漂移的误差很难通过软件固定修正唯一的出路是使用外部冷端传感器。改用外部PT1000后整体偏差从2~4℃降到0.3℃以内。需要注意的是外部PT1000自身的精度误差会直接叠加到冷端温度上所以我选了一颗0.1%精度的薄膜PT1000并且在固件里允许对冷端温度做一阶偏移修正。如果你手头有恒温槽最好把冷端传感器在0℃和50℃各标定一次把偏置修掉。5.3 三线制RTD仍然误差大很多人在两线制模块上直接改三线制接线加了一根线但IEXC2没有正确配置结果精度没有任何提升。排查方法很简单断开RTD但保留三根线用万用表分别测L1、L2、L3的直流电阻如果三根线阻值差异较大说明你要重新配对线缆。三线制补偿的前提是两端的线电阻相等实际屏蔽线出厂时阻值可能有差异我见过现场用不同长度线拼接导致的误差。另一个隐蔽问题是IEXC1和IEXC2的匹配度。ADS122U04的两个电流源虽然做了匹配但如果配置成不同电流值补偿就失效了。配置完后读一遍寄存器确认两个电流源电流值一致且都指向正确方向。5.4 传感器断线检测与故障诊断温度采集系统最怕的不是读数不准而是传感器断了之后读数显示正常。RTD断线时RTD阻值变成无穷大CODE会迅速跳到接近满量程的正向极限。热电偶断线时也有类似现象。我在固件里专门加了诊断逻辑CODE绝对值大于满量程的95%判定为传感器开路温度显示“----”并触发报警。连续多次读取结果跳变超过50℃且没有恢复趋势判定为接触不良。CODE持续为零同时检查通道配置可能是MUX切换没生效或者接线短路。HVAC项目里这个功能尤其重要。风管温度传感器的线缆经过吊顶、桥架极易被老鼠咬断或被施工踩断断线报警能省大量售后排查时间。我在Modbus寄存器里单独定义了一个故障状态字每个通道的开路、短路状态都映射到独立位上位机可以直接读取。5.5 现场EMC问题与整改记录首次过EMC测试时我的板子在静电放电±8kV空气放电和电快速瞬变脉冲群±2kV两项上都没扛住。主要表现是热电偶通道读数瞬间跳变几十度甚至出现UART通信CRC连续失败。整改措施有三条热电偶输入端加RC低通滤波电阻100Ω、电容1nF截止频率约1.6MHz对射频干扰和脉冲群都有衰减。电容要用C0G材质X7R在高压下容值会掉。UART的TX/RX线上各加一颗33Ω电阻靠近STM32侧放置同时串一颗100pF电容到地形成简单的RC滤波。传感器屏蔽线的屏蔽层在控制柜端子处单端接地不要在ADC侧再接地形成环流。整改后复测热电偶读数基本稳定。有一点要提醒输入滤波电容过大会影响信号建立时间如果读者把RC时间常数调太大ADC的采样结果可能会出现微小滞后对高速变化的温度场景不利具体参数需要根据你的应用折中。5.6 常见问题速查表现象直接原因排查/解决办法UART无响应命令帧缺少CRC或TX/RX接反抓串口波形核对协议检查交叉连接读数全0信号输入共模过低热电偶加偏置电阻确认MUX通道配置读数接近满量程传感器开路检查RTD/热电偶断线确认PGA增益是否过大温度漂移明显参考电阻受热RREF远离热源选低TCR电阻热电偶整体偏高冷端补偿失效换外部PT1000修正冷端偏移读数跳动大电源纹波或空间干扰加固去耦输入加RC滤波屏蔽层单端接地DMA接收错位帧同步丢失增加状态机保护CRC失败时重新同步PT100精度差三线制未生效确认IEXC1/IEXC2匹配检查线电阻一致这套方案我在产线上跑了半年最深的体会是ADS122U04走UART这件事乍看很友好但协议帧、寄存器时序、冷端补偿和接地策略任何一个环节藏着问题最终都会在精度数字上现出原形。返工时间往往都花在电源、地线和接线上而不是代码本身。如果你也在做类似的温控采集板建议先把PCB的电源地和信号地规划好然后在单板上完整跑通一路RTD加一路热电偶精度稳定后再扩展多通道。拿我最初那版来说第一次打样就急着把四路通道全接上结果调试时根本分不清是接线问题还是配置问题白白浪费了两周。先把一条链路吃透后面所有通道都是复制粘贴的事。