
1. 从项目标题看本质为什么非要用“UART口ADC Cortex-M4”的组合拿到“ADS122U04IPWR 与 STM32F411RE 做工业和 HVAC 温度测量”这个标题我先拆解一下ADS122U04IPWR 是一颗 24 位 Δ-Σ ADCUART 接口STM32F411RE 是一颗 Cortex-M4F 内核 MCU主频 100MHz512KB Flash、128KB SRAM。这两个芯片放在一起解决的不是“能不能测温度”的问题而是“在工业/HVAC 现场环境下怎样把毫伏级温度信号稳定、准确、低延迟地变成远程上位机可读的数据”的问题。这类项目在暖通空调控制器、冷水机组、锅炉房温度采集、楼宇自控系统里太常见了。现场走线往往几十米甚至上百米探头分布在风管、水管、室外机、机房各个角落电磁干扰源又多变频器、水泵电机、接触器吸合瞬间的浪涌随便一个都能让未经验证的温度采集方案产生几度的跳动。选 ADS122U04 的最大理由就是它的 UART 接口。相比 SPI、I²C 这类同步串行接口UART 是异步差分传输线缆要求低抗干扰能力强传输距离长而且可以和 RS-485 收发器直接配合随便一对双绞线就能把多块 ADC 挂在总线上。这就是把 ADC 芯片做成“传感器节点”的最佳形态。至于 STM32F411RE它在整个系统的位置是“主控制器”。F411 算 STM32F4 家族里的均衡选手性能比 F1 强不少但又不至于像 H7 那样贵。内部的硬件 USART 可以开 DMA接收 ADC 上传的数据帧时几乎不占 CPU512KB Flash 装下完整的温度标定查找表、滤波算法和 MODBUS 协议栈也够用128KB SRAM 跑实时操作系统或者裸机状态机都绰绰有余。工业产品不是做毕设核心诉求是“长时间稳定跑不重启”F411 的成熟度、供货量、Flash/SRAM 容量都正好卡在性价比甜点上。如果你也是第一次接触这类“串口型 ADC”的方案我建议你把这个项目理解成传感器侧用一块带 UART 接口的高精度 ADC 做模拟前端MCU 侧用 DMA 接收数据帧温度换算、校准、越限报警等逻辑全部交给嵌入式软件处理。这套架构最大的好处是传感器和主机之间解耦探头坏了换探头ADC 节点挂了不影响总线上的其他节点。下文我会把硬件设计、UART 协议、寄存器配置、温度算法和实际调试中踩过的坑全部分享出来目标是让有单片机基础的工程师照着做一周内能跑通两路 PT100 的实时测温。2. 传感器选型与硬件设计一张图看懂模拟前端2.1 工业测温里RTD、热电偶、NTC 到底选谁标题只写了“工业和 HVAC 应用中的温度”并没有限定传感器类型所以这正好是第一个要决策的点。我在实际项目里通常按测温范围和成本拆成三个阵营RTDPT100/PT1000-200℃ 到 600℃ 范围线性度最好长期稳定性最好HVAC 的水温、风温、回风温度检测基本都选它。缺点是价格偏高且需要激励电流源三线制/四线制接线才能抵消导线电阻。热电偶K 型、T 型测温上限高成本低但输出是微伏到毫伏级信号冷端补偿麻烦HVAC 场景一般很少用工业窑炉、排烟温度才会优先考虑。NTC 热敏电阻便宜、灵敏度高、响应快25℃ 时阻值几 kΩ 到几十 kΩ适合 HVAC 室内温控器这种近距离、精度要求不苛刻的场景。缺点是 B 值离散性大、温度上限通常 150℃ 以下。ADS122U04 这四路输入、两个可编程激励电流源IDAC、内置 PGA说穿了就是为了兼容以上三类信号设计的。但做产品要克制不要妄图一个板上啥都能接。我建议把 RTD 作为这套系统的主力因为 HVAC 场景下精度要求通常就是 ±0.5℃ 以内PT100 配合 24 位 ADC 很容易达到同时把 ADC 的第二路输入留给 NTC作为风管湿度补偿用的辅助温度热电偶采集则留给另一块从板避免模拟前端互相干扰。这个思路在工程上最稳妥。2.2 激励电流、PGA 增益和比率测量把“为什么这么配”讲清楚ADS122U04 内部有两个 IDAC可以输出 50µA 到 1500µA 的激励电流。测 PT100 标准做法是IDAC1 电流流过 RTD再流到基准电阻 RREF最后回到 IDAC2。RTD 两端的电压进入 ADC 差分输入RREF 两端的电压作为外部参考电压 REFP/REFN。这种接法叫“比率测量”核心好处是激励电流的大小波动、温漂对测量结果的影响会被同时抵消掉。你不需要一个高精度恒流源只需要一只温漂系数低于 10ppm/℃ 的精密电阻 RREF成本能降一大截。具体参数怎么定我举一个实际配置PT100测温范围 -40℃ 到 150℃选 IDAC 500µAPGA 增益 8外部基准 RREF 2.49kΩ1kΩ 会不够见后面的计算。按照 PT100 的 Callendar-Van Dusen 公式150℃ 时阻值约 158.84Ω压降 0.5mA × 158.84Ω 79.42mV-40℃ 时阻值约 84.27Ω压降 42.14mV。ADS122U04 内部参考默认 2.048V但用了外部基准后满量程差分输入电压 Vref / Gain (0.5mA × 2.49kΩ) / 8 155.6mV。也就是说-40℃ 到 150℃ 的信号摆幅只占 ADC 量程的 27%~51%余量很充裕就算接线引入 2Ω 接触电阻也不会顶到饱和。激励电流不是越大越好500µA 是自热和信噪比之间的平衡点电流每增加 1 倍RTD 自身发热功率增加 4 倍在 0℃ 冰点校准的时候自热造成的温升可能直接吃掉 0.1℃ 的精度。再看 ADC 的分辨率能不能覆盖 0.01℃ 级别24 位数据LSB Vref / (Gain × 2^23)。按 Vref 1.245V0.5mA × 2.49kΩ、Gain 8 计算LSB ≈ 18.5nV对应到 PT100 的电阻灵敏度约 0.385Ω/℃换算成温度分辨率大约 1.48e-5℃/LSB。这个数值远远超过实际需要真正的瓶颈是噪声、参考电阻温漂和传感器自身精度而不是 ADC 位数。那些“24 位 ADC 测温度一定准”的说法恰恰是新手最容易踩的误区。2.3 PCB 布线与电源处理比写代码更早决定成败ADS122U04 是 Δ-Σ ADC对模拟电源和数字电源的噪声都很敏感。我的板子上做了三个关键处理一是 AVDD 和 DVDD 分别供电中间串磁珠模拟地和数字地单点连接ADC 下方不要铺数字地平面二是 REFP/REFN 差分走线周围包地远离 USART 的 TX/RX 走线因为 UART 信号跳变沿的电流冲击会通过寄生电容耦合到高阻抗参考输入上造成转换值周期性跳动三是 RTD 激励电流的走线尽量短且宽减少铜箔电阻的温漂误差。还有一个细节ADS122U04 是 TSSOP-16 封装芯片底下没有散热 pad热耦合到 RTD 探头的量其实很小但 PCB 上不要把它放在发热元件比如 DC-DC 电感、LDO旁边。HVAC 控制器机箱里经常有变压器和继电器这类强干扰源离 ADC 尽量远必要时用屏蔽罩把模拟区罩起来。硬件上这些小习惯会让后面的调试省掉一半时间。3. UART 通信与驱动设计不靠 SPI关键帧格式要搞透3.1 ADS122U04 的 UART 帧地址、命令、数据、CRC 一个都不能少ADS122U04 与 MCU 的通信没有标准寄存器堆那种“拉低片选、写寄存器”的直观操作而是走命令帧/响应帧。一般帧由四部分组成器件地址字节、命令/寄存器标识字节、数据字节写寄存器时有最后是 CRC8 校验字节。地址字节的低 4 位是器件地址通过 ADDR1/ADDR0 引脚配置高 4 位用于寄存器选择或者命令类型。某一条典型命令是“写 CONFIG0 寄存器”主机连续发送“器件地址 寄存器号 配置值 CRC”ADC 收到后校验通过回一帧确认下一次转换周期就应用新配置。我强烈建议拿到芯片后第一步不要写业务代码先用一个 USB 转 TTL 的调试工具接上 ADC 的 TX/RX手动敲十六进制命令确认芯片能正常回数据。这个习惯帮我避免了很多“程序没问题但硬件不通”的盲区。比如我最开始把地址引脚接反了导致命令总是发给“不存在的设备”ADC 完全没有任何响应。一旦确认数据链路通了再往下写 STM32 驱动就很快。CRC 多项式是 0x07和常见的 CRC-8/ITU0x31不一样不能用现成的 CRC8 表格直接套。我在这块栽过一次程序里复用了 I²C 校验的查表法结果每次读回来的数据都报 CRC 错误后来对照数据手册逐位推了一遍才发现多项式弄错了。驱动里记得单独写一个“ADS122U04 专用 CRC8”初始值、输出异或值都按手册定义来。3.2 STM32F411RE 的接收状态机与 DMA 配置MCU 侧我用 USART2 接 ADS122U04115200bps 或 19200bps 都可以取决于 ADC 内部的波特率配置。要注意这个芯片的波特率来源于内部振荡器标称精度一般长帧在高波特率下偶尔会出错所以工业现场我反而选低波特率19200bps 更稳一个 5 字节的响应帧也就 2.6ms完全够用。接收侧的核心思路是 DMA IDLE 中断。配置 USART2 的 RX DMA 到一块 32 字节的环形缓冲区开启总线空闲IDLE中断。ADC 每次转换完会主动推一帧MCU 收到一帧后总线空闲进入中断此时 DMA 剩余的传输计数就是帧长度。这种方式比逐字节进中断高效得多CPU 占用几乎为零。代码如下// 假设 DMA1_Stream5 是 USART2_RX缓冲区 recv_buf[32] void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_IDLE) ! RESET) { // 读 SR 再读 DR清 IDLE 标志 (void)USART2-SR; (void)USART2-DR; // 计算帧长32 - DMA_GetCurrDataCounter(...) frame_len 32 - DMA_GetCurrDataCounter(DMA1_Stream5); if (frame_len 3 frame_len FRAME_MAX) { pending_frame 1; } DMA_Cmd(DMA1_Stream5, DISABLE); // 重置 DMA 传输计数到缓冲区起始位置 DMA_SetCurrDataCounter(DMA1_Stream5, 32); DMA_Cmd(DMA1_Stream5, ENABLE); } }业务层则是一个有限状态机收到完整帧后先解析地址再校验 CRC通过后把 24 位原始数据拆出来置“数据就绪”标志供上层温度换算任务轮询。如果连续 3 帧 CRC 错误我会上报一次通信故障事件并重新初始化 UART。千万不要在主循环里做阻塞等待否则 ADC 的连续转换模式会把 CPU 时间全部吃掉。3.3 寄存器配置的“实战参数表”与注意事项ADS122U04 有几个关键寄存器需要初始化配置输入多路开关选哪两个引脚作为差分输入、PGA 增益、数据速率、IDAC 电流档位、转换模式单次还是连续、基准源选择。我基于 PT100 三线制 连续转换模式贴一份参考配置值配置项设置值说明输入通道AIN0 IN, AIN1 -INRTD 差分输入PGA 增益8满足 -40℃ 到 150℃ 量程基准源外部 REFP/REFN接 RREF实现比率测量IDAC1 电流500µA激励电流流向 RTDIDAC2 电流500µA回流电流流向 RREF数据速率20SPS或按滤波需求20SPS 时工频抑制较好转换模式连续转换适合实时采集具体的位域赋值请一定以你拿到芯片的最新版数据手册为准不同批次、不同后缀IPWR 代表封装和温区的配置字可能有更新。我的做法是在工程中建一个ads122u04_config.h把所有配置值用宏定义封装方便后续移植。还有一个容易忽略的坑如果用了外部基准CONFIG 寄存器里必须把基准源明确选为外部否则芯片缺省用内部 2.048V 参考你测量的电压范围会变数据就会整体偏差。这个错误发生得很隐蔽因为芯片不会报错只是转换结果莫名其妙地“不对”。我当时排查了很久最后是逐位读回寄存器才发现基准选择位没写对。4. 温度计算与校准从原始码到 0.1℃ 的最后一公里4.1 原始码换算成电压和电阻假设你从 ADC 读回一个 24 位补码数据 raw首先要判断符号最高位是 1 表示负电压要手动扩展符号位。然后把 raw 乘上 LSB 电压得到差分输入电压。LSB 的计算式是LSB Vref / (Gain × 2^23)例如 Vref 1.245V、Gain 8则 LSB ≈ 18.5nV。代码里为了效率我不用浮点数乘除而是直接用 64 位整型算出“电压×10^9”的纳伏值再做除法。RTD 的电阻值 差分电压 / 激励电流。由于是比率测量如果 RREF 和 RTD 在同一个电流回路里其实可以直接用码值比例算电阻避免浮点R_rtd RREF × raw_rtd / raw_ref其中 raw_ref 是 RREF 两端电压数字化后的码值。前提是 RREF 的温漂足够小我选的是 10ppm/℃ 的金属膜电阻零下 20℃ 到 60℃ 的环境变化对结果影响小于 0.04%。4.2 RTD 非线性修正CVD 公式与查表法PT100 的电阻-温度曲线不是绝对线性0℃ 以上通常用二项式就能做到不错的效果更严谨的是 Callendar-Van Dusen 方程当 t ≥ 0℃ 时R(t) R0 × (1 A·t B·t²)当 t 0℃ 时R(t) R0 × (1 A·t B·t² C·(t-100)·t³)标准系数 A 3.9083×10⁻³B -5.775×10⁻⁷C -4.183×10⁻¹²。工程里两种实现路线查表法IEC 60751 标准分度表 线性插值适合 MCU因为数组可以预先生成代码里直接二分查找直接公式法适合量程不大、对 FLASH 占用敏感的场景。我在 F411 里用的是查表-40℃ 到 150℃ 每 1℃ 一个点共 191 个点占用不到 400 字节插值后的误差小于 0.01℃。有个细节值得提醒查表基准必须和传感器等级一致。工业 PT100 有 AA 级、A 级、B 级之分A 级允差是 ±(0.15 0.002·|t|)℃B 级是 ±(0.30 0.005·|t|)℃。如果你的传感器本身是 B 级ADC 算得再准也没有意义整体误差会被探头吃掉。楼主位项目描述里没提传感器精度但做 HVAC 温控器我一般直接定 A 级 PT100价格差异很小带来的客户投诉差异却很大。4.3 现场校准零点和斜率漂移的修正方法硬件焊好之后不要急着标定。我的标准流程是先用高精度电阻箱替代 RTD 接入板子分别给 100Ω0℃、138.51Ω100℃、158.84℃150℃三个值记录 ADC 原始码建立一条直线“码值→电阻”得到实际增益和偏移写进 Flash 的校淮区。这一步能修正 RREF 的初始误差、PCB 导线电阻、差分放大器的输入偏置电压。然后做冰点槽和沸水槽验证把 PT100 探头插入 0℃ 冰水混合物和 100℃ 沸水读数应该在 0.0℃ ± 0.1℃ 和 99.9℃ ± 0.2℃ 内受气压影响沸点略低我这个只做定性检查。校准数据要设计成可在线更新我用的是 F411 内部 Flash 末尾的一个扇区上电时读取配合一个简单的校验和。产线校准时通过串口命令下发三点校准值避免每台设备都要改固件。5. 实际调试中踩过的坑噪声、自热、通信和地线相关的血泪史5.1 转换值漂移和显示跳动先怀疑自热噪声而不是算法一次在现场调试时ADC 读数总是周期性上下跳 0.3℃起初我怀疑滤波算法不够。后来把探头捏在手里跳变周期和手接触的节奏对上了才发现问题出在 IDAC 电流设置太大探头自身被加热了。当时为了追求“分辨率更高”把激励电流设成了 1mAPT100 在 0℃ 时功耗 100µW由于探头热阻约 300℃/W内部温升直接来到 0.03~0.04℃再加上空气流动波动显示自然就抖了。解决办法是回到 500µA同时软件里做一阶低通滤波时间常数 0.5s 左右。HVAC 的风管温度本来就变化慢不需要毫秒级响应。5.2 UART 通信偶尔丢帧或 CRC 报错这个现象在实验室基本复现不出来一到现场就出现原因往往是电磁干扰灌进了 UART 线。UART 是异步通信空闲时 TX 为高电平如果现场有变频器频繁启停线缆等效天线会把差模噪声耦合进信号。解决办法有两层硬件上MCU 与 ADC 之间不要直接飞线用带屏蔽的双绞线屏蔽层单端接地软件上代码要支持自动重同步而不是报错后死等。我写的状态机在连续收到错误帧时会主动清空接收缓冲、复位 DMA、重新发送一次“读取转换结果”命令让通信恢复。实测在接触器动作的瞬间偶尔丢一帧但系统能在几十毫秒内自愈。5.3 参考电阻的温漂成为精度瓶颈一个容易被忽视的“隐形误差”比率测量消除了激励电流的温漂但 RREF 本身的温漂不会自动消失。曾经有个项目在北方冬天室外机柜里跑白天误差正常晚上温度降到 -20℃ 时整机示值偏了 0.5℃。排查到最后发现 RREF 用的是普通 1% 贴片电阻温漂系数大约 100ppm/℃在 -20℃ 到 25℃ 之间变化 45℃电阻值变化 0.45%换算成 PT100 电阻就是 0.45Ω温度误差约 1.2℃。这个教训让我把 BOM 里这个电阻强制指定为 10ppm/℃ 以下的精密电阻量产前必须做温度循环测试。有时候硬件设计里最不起眼的元件才是系统精度的天花板。5.4 三线制远比两线制实用现场压降的实测对比刚开始图省事我把 PT100 接成两线制认为“导线电阻很小就算有 1Ω校准一次也能消掉”。结果探头到板子距离一拉长问题就来了导线电阻会随温度变化夏天和冬天相差好几欧姆校准值跟着漂。改用三线制后一根线专门用于补偿IDAC 电流回路的压降不再叠加到测量回路中实测在 50 米线缆下读数稳定度从 ±1.2℃ 降到 ±0.1℃ 以内。如果你的系统允许走线根数多一点请直接上三线制或四线制这是工业测温性价比最高的一个改进项。5.5 波特率不匹配导致的全是乱码ADS122U04 的波特率由内部寄存器决定我这块板子上一开始按 115200 跑偶尔出现第一个字节丢失或者帧尾 CRC 错。后来示波器抓波形发现 ADC 实际发送的位宽和标准 115200 有约 2% 的偏差多字节帧累计误差会让接收端采到错误的位。降到 19200bps 后位误差占比缩小通信非常稳定。所以工业现场除非传输数据量真的大到必须高速否则我建议 UART 口一律 19200 或者 9600。这不算保守是被现场噪音教育出来的经验。6. 后续还能怎么扩展一套硬件吃下更多测点这个方案的可扩展性很好。ADS122U04 的地址引脚支持在同一 UART 总线上挂多个 ADC一个 F411 最多能管理 4 路 ADC 节点每路 ADC 又是 4 通道差分输入相当于一个主控可以覆盖最多 16 路温度测点。在 HVAC 项目里通常需要同时采集供水温度、回水温度、室外温度、风管温度、机房温度一套主控板 4 块 ADC 子板就够了。子板和主控之间走 RS-485 电平抗干扰和传输距离都更可靠。软件上还可以加一个简单的 MODBUS RTU 从站协议让楼宇自控的 PLC 或者上位机直接通过 RS-485 读取温度值这样就不需要额外写上位机协议。F411 的资源完全够用因为温度采集本身的数据率不高MODBUS 轮询 20ms 一次也不是问题。我自己在项目里就是这么扩展的主循环把最新温度值存进一个共享结构体MODBUS 线程读取时加临界区保护PLC 端只需要配置寄存器地址就能看到每路温度、报警状态、传感器断线标志。整套系统从测温探头到上位机显示形成了一个完整链路后续换探头类型、加测点、改通信协议都不用重新设计硬件。最后分享一个小技巧给每一路温度通道加一个“断线检测”逻辑通过读回来的电阻值判断。PT100 开路时 ADC 读到的电压接近正满量程短路时接近零软件里设置上下阈值一旦越限就把该通道标记为故障在 MODBUS 寄存器里用一个位来表示。这个功能在 HVAC 现场特别实用因为传感器线缆老化、端子松动是迟早的事。有了断线报警运维人员才能第一时间发现哪一路在“假测温”而不是等到系统误动作了才去查问题。