UART接口24位ADC与Cortex-M33组合的高精度温度采集方案实战 做暖通空调控制器那阵子温度采集这一路看着不起眼却是最容易让人半夜睡不着觉的地方。盘管风机的回风温度、冷水机组的进出水温差、新风系统的送风温度每一路都直接参与 PID 调节。温度跳 0.1℃ 可能没什么跳 0.5℃ 就会导致风机转速来回抖阀门反复开关整个系统始终稳不住。我最后把方案收敛到 ADS122U04IPWR 配 R7FA4M2AD3CFP 这个组合上。一颗是 TI 的 24 位 UART 型 Δ-Σ ADC另一颗是瑞萨的 Cortex-M33 主控 MCU一个管模拟前端的高精度测量一个管整套控制逻辑和通信各干各擅长的活。这篇不是翻译数据手册是我在 HVAC 项目和工业数据采集模块上反复调出来的实战总结。ADS122U04 负责把温度传感器信号变成可靠的数字结果R7FA4M2AD3CFP 负责读数据、做算法、驱动外部设备两者通过 UART 通信。适合正在做温度采集方案选型、被温漂和噪声折磨、或者想用 UART 型 ADC 节省 MCU SPI 资源的工程师参考。1. 方案整体拆解为什么组合是这两颗芯片1.1 先把需求场景摆出来工业和 HVAC 里的温度测量表面上都是量温度实际要求差得很多。HVAC 系统里送回风温度范围通常在 -10℃ 到 70℃冷冻水温度在 5℃ 到 40℃ 之间信号变化非常缓慢一分钟内变化超过几度就算异常了。精度要求一般在 ±0.1℃ 到 ±0.5℃ 之间不苛刻但需要长时间稳定不能因为环境温度变化或者电源波动把读数带偏。工业场景就不一样了。变送器、环境监测设备可能面对 -40℃ 到 85℃ 的壳体温度热电偶还要测几百度的高温。更麻烦的是工业现场有电机、变频器、接触器这些干扰源走线稍微长一点50Hz 工频干扰和射频干扰都能耦合进传感器信号。这类场景对 ADC 的共模抑制、工频抑制、输入偏置电流和长期漂移都提出了更高要求。所以选型的核心不是“谁的位数高”而是“在干扰下面还能不能保住精度”。24 位 Δ-Σ ADC 这种结构天生适合缓慢变化的温度信号过采样把噪声压下去再用数字滤波把工频干扰滤掉。ADS122U04 属于这类里有 UART 接口的型号前端调理、激励电流源、基准源全部集成在芯片里外部电路只需很少的元件。1.2 ADS122U04 这颗 ADC 解决的不只是精度第一次接触 ADS122U04 的人很容易只盯住“24 位”这个数字实际上这颗芯片的价值在于把前端工程量减下来了。大多数 MCU 内置 ADC 的精度只有 12 位左右加上参考电压漂移和输入噪声想做到 0.1℃ 非常费劲。而外置 24 位 ADC 配合精密基准可以把 RTD 电阻的微小变化分辨出来。ADS122U04 内部有可编程增益放大器处理几十毫伏级别的热电偶信号时可以把 PGA 打开把信号放大后满量程利用 ADC 分辨率。它还有两个可编程的激励电流源可以直接给 RTD 或 NTC 供电电流从 10μA 到 1.5mA 可配。加上内部 2.048V 低漂移基准整个前端不再需要另外的仪表放大器、基准源和恒流源电路。对于做产品的工程师来说少一个器件就少一个故障点也少一块 PCB 面积。最值得说的是它的 UART 接口。ADS122U04 的通信方式不是传统的 SPI 或 I2C而是通过 UART 命令帧配置。这在抗干扰和系统隔离上有天然优势。工业设备和 HVAC 控制器里 MCU 和其他板卡经常存在地电位差异SPI 的时钟线和数据线对时序敏感走线稍长就容易出错。UART 本身是异步通信抗干扰能力强也方便通过光耦或数字隔离器做电气隔离。我把 ADC 和 MCU 之间的 UART 信号用光耦隔开模拟前端和数字部分完全电气隔离有效抑制了地环路噪声这个方案在变频器附近实测效果很明显。1.3 R7FA4M2AD3CFP 在项目里承担什么角色R7FA4M2AD3CFP 属于瑞萨 RA4M2 系列内核是 Arm Cortex-M33主频最高 100MHz。在温度采集方案里用这个级别的 MCU 看起来是杀鸡用牛刀但实际产品不能只看温度测量这一路。HVAC 控制器需要管风机、水阀、压缩机和加热器至少好几路 PWM 或继电器输出还需要跑 PID 控制算法、与上位机或楼宇自控系统通信。带浮点运算能力的 Cortex-M33 算 PID 是很轻松的事余量都花在通信协议栈和人机交互上。RA4M2 提供多个 UART、SPI、I2C 接口以及 CAN FD 外设做扩展很方便。FSP 软件框架把 HAL 驱动都封装好了开发效率比从寄存器裸写高不少。老实说如果你只是做一个单独的温度采集小板用一颗 STM32G0 或者瑞萨 RA2 系列就足够。但整套 HVAC 控制器里MCU 还要承载控制逻辑、故障诊断和通信任务选择 RA4M2 这个级别的芯片软件写起来不用抠脚趾头省资源。这个组合的本质是让 ADC 专注模拟测量让 MCU 专注控制和通信两者各司其职。2. 硬件设计从传感器到 MCU 的通路2.1 传感器选型RTD、NTC、热电偶用在哪温度传感器本身决定了整个测量链路的天花板。HVAC 应用里最常见的是 NTC 热敏电阻和铂电阻。NTC 便宜响应快在常温区间精度也能做到 ±0.2℃ 左右但非线性严重换一个厂家批次的 B 值可能就偏了。RTD铂电阻线性度好、重复性好是工业过程测量的标准选择精度可以做得很高但价格贵一些。热电偶测温范围广、探头耐高温但信号非常微弱而且冷端补偿很容易引入额外误差。传感器典型温度范围信号特点适合场景PT100-200℃ ~ 850℃0℃时100Ω变化率约0.385Ω/℃工业过程、冷冻水、冷却水PT1000-50℃ ~ 500℃0℃时1000Ω变化率约3.85Ω/℃HVAC、高精度系统NTC-40℃ ~ 150℃阻值随温度指数变化灵敏度高成本敏感的 HVAC 控制器热电偶 K/J 型-200℃ ~ 1200℃电压信号几十 μV/℃锅炉、烟气、工业高温在 HVAC 项目里我优先建议 PT1000 配 ADS122U04。PT1000 阻值高导线电阻的误差占比更小用两颗激励电流源配合比例测量两线制也能做到不错的精度。工业场景需要测高温或者传感器探头体积受限再考虑热电偶。ADS122U04 的 PGA 正好可以把热电偶的微弱电压放大内部还有温度传感器可以做冷端基准少一路外部补偿电路。如果产品定位偏成本敏感用 NTC 加查表也可以。但 NTC 要针对每一批物料单独校准生产线上要加老化测试和校准工位综合成本未必比 PT1000 低。我踩过这个坑用便宜的 NTC 做了一版产品最后发现标定工作量太大温度曲线一致性不稳定还是换回了 PT1000。2.2 ADC 前端电路激励电流、基准电阻与滤波保护用 ADS122U04 做比例式 RTD 测量是最稳的方案。比例式测量的意思是 RTD 的电阻值和内部基准电阻的比值相关而不是依赖绝对电压。这样即使参考电压有温漂ADC 两个通道的读数按比例抵消误差就很小了。电路上我用 IDAC1 输出 1mA 激励电流流过 RTD 后到地同时这一路电流流经精密参考电阻 R_REF 产生基准电压接入 ADC 的 REFP 和 REFN 引脚。ADC 先测量 RTD 两端电压再测量基准电阻两端电压两者之比乘以 R_REF 就是 RTD 的实际电阻值。公式简单列一下Rt (Data_RTD / Data_REF) × R_REFR_REF 我选的是 1kΩ、 ±0.1% 温漂系数 5ppm/℃ 的金属膜电阻。需要注意 IDAC 电流不能太大不然 RTD 自热会引入明显的测量误差。1mA 电流在 100Ω PT100 上只有 0.1mW 功耗误差基本可忽略如果用 PT10000.5mA 电流更合适满量程功耗也只有 1.25mW 左右。输入侧的滤波电路不能省。我在传感器差分输入端各串联一个 1kΩ 电阻并联一个 10nF 的 C0G 电容做差分滤波截止频率大约在 16kHz主要作用是抑制射频干扰和 ESD 冲击。严格来说这个滤波器会稍微影响建立时间但对于温度这种缓变信号完全没影响。需要注意电容材质选 C0G/NP0X7R 在直流偏压下容值会变化三分之一以上做精密测量不合适。传感器是外部接入的肯定要做保护。两根信号线上各加一只双向 TVS 管钳位到电源轨再串联 PTC 自恢复保险丝限流。静电放电和错误接线的浪涌很大概率会把昂贵的 ADC 打坏这块成本不能省。2.3 电源、地线和 PCB 布局的细节温度和模拟电路的性能一半看芯片一半看电源和布局。ADS122U04 虽然对电源要求没有某些高端基准那么苛刻但也不能直接把 MCU 的开关电源输出接过来。我给 ADC 的模拟电源使用独立的 LDO从 24V 或者 5V 系统电源先降到 3.3V。模拟供电和数字供电之间用磁珠做单点连接模拟地采用星形接地汇聚到 ADC 的 GND 脚。ADC 的 REFN、AVDD、DVDD 旁边都放了 100nF 和 10μF 的去耦电容靠近引脚放置这是保住 24 位有效位数的基本操作。PCB 布局上最需要注意的是把模拟部分和数字部分分开。ADS122U04 和传感器接口放在板子边缘MCU、继电器驱动、通信接口放在另一侧。底下做一个完整的地平面比什么都重要我见过很多设计把地挖开试图“隔离”结果反而更糟。现代 ADC 的地平面只要连续、干净配合星形接地和磁珠分隔效果远比碎地好。如果现场有强干扰源比如变频器或接触器我倾向在传感器线束上加屏蔽层并把屏蔽层单端接地。工业现场还有一种情况是温度探头距离控制器几十米输入端共模电压可能很高这种情况下建议在 ADC 输入端加运算放大器做电平转换或者加隔离式信号调理模块直接硬接很容易踩坑。2.4 MCU 与 ADC 的 UART 连接方式ADS122U04 和 R7FA4M2AD3CFP 之间用 UART 连接接线看起来就是标准的 RX/TX 交叉连接。实际配置的时候要注意几个点。先看电平。ADS122U04 支持 2.2V 到 5.5V 的宽供电范围其 UART 引脚电平取决于 AVDD/DVDD。如果 MCU 是 3.3VADC 也用 3.3V 供电两边可以直接连。但 ADC 如果用 5V 供电就需要 MCU 那边用带 5V 容忍的引脚或者加电平转换。我个人的习惯是系统统一 3.3V省去转换电路。波特率方面ADS122U04 的 UART 波特率由内部振荡器配置常见可以运行在 9600 到 230400。温度数据率本身只有几十到几百 SPS数据量很小我用 115200 足够兼顾了响应速度和抗干扰能力。UART 命令帧如果连续发送速率过高反而容易在噪声环境下丢帧工业现场没必要追求高波特率。距离和隔离方面ADC 和 MCU 之间若超过 20cm或者中间跨过动力线建议用 RS485 或者透传方式。ADC 板卡做成分体式、靠近传感器安装时最简单可靠的办法是 ADC 板子输出 UART 给一个 RS485 芯片和主控之间走屏蔽双绞线。还有一种做法是直接用光耦隔离 UART 信号我试过用高速光耦隔离 115200 信号电压隔离做干净以后效果很好这比 RS485 还多一层电气隔离。3. 软件实现从寄存器配置到稳定温度值3.1 UART 命令帧和初始化顺序ADS122U04 的上电配置要按顺序进行不然容易踩到“命令发了没反应”的坑。每次上电或复位之后芯片需要先等待内部振荡器稳定再发送配置命令帧。命令帧格式大致是首字节加数据载荷具体指令码以手册为准。我代码里习惯把配置写成宏集中管理这样接线变了改一处就能生效。初始化顺序如下等待至少 10ms确保 ADC 内部上电完成发送复位命令恢复默认寄存器状态写 CFG0 寄存器选择输入通道、PGA 增益、开关滤波写 CFG1 寄存器选择数据速率、工作模式写 CFG2 寄存器配置 IDAC 电流源、参考电压和内部温度传感器启动连续转换模式开始读取数据// 以伪代码形式展示初始化逻辑位定义按实际芯片手册核对 #define CFG0_MUX_AIN0_AIN1 (0x00) // 差分输入通道 #define CFG0_GAIN_8 (0x20) // PGA 增益 8 #define CFG0_FILTER_50_60 (0x08) // 同时抑制 50Hz 和 60Hz #define CFG1_DATARATE_100SPS (0x04) // 数据速率 100SPS #define CFG1_CONTINUOUS (0x00) // 连续转换模式 #define CFG2_IDAC_1MA (0x08) // IDAC 电流 1mA #define CFG2_VREF_INTERNAL (0x00) // 使用内部 2.048V 基准 static const uint8_t ads_cfg[3] { CFG0_MUX_AIN0_AIN1 | CFG0_GAIN_8 | CFG0_FILTER_50_60, CFG1_DATARATE_100SPS | CFG1_CONTINUOUS, CFG2_IDAC_1MA | CFG2_VREF_INTERNAL, }; void ads122u04_init(void) { ads_uart_init(115200); delay_ms(10); ads_send_cmd(CMD_RESET); delay_ms(5); for (int i 0; i 3; i) { ads_write_reg(REG_CFG0 i, ads_cfg[i]); } ads_send_cmd(CMD_START_CONV); }实际使用中我会在读取数据帧时加入 CRC 校验。工业现场通信一旦出错宁可丢一次数据也不要拿错误数据参与 PID 运算否则阀门或者变频器会突然动作一下这在设备调试现场很吓人。3.2 比例式 RTD 测量与温度换算实现温度换算看起来只是套公式实际上细节都在边界条件里。我在 HVAC 项目里用的是 PT1000 查表插值法配合 Callendar-Van Dusen 方程做校准参考代码逻辑可控性强也方便处理负温度。测量流程是每隔一段时间控制输入多路复用器分别采集 RTD 通道和基准电阻通道的转换结果计算电阻比例再用查表法转成温度。查表时我用 0.1℃ 间隔的电阻表二分查找之后线性插值误差小于 0.01K足够 NB 了。// 二分查找 线性插值将电阻值转换为温度 float rtd_resistance_to_temp(float rtd_res) { if (rtd_res RTD_TABLE[0].res || rtd_res RTD_TABLE[RTD_TABLE_SIZE-1].res) { return NAN; // 超出量程交给故障处理 } int low 0; int high RTD_TABLE_SIZE - 1; while (high - low 1) { int mid (low high) / 2; if (RTD_TABLE[mid].res rtd_res) { low mid; } else { high mid; } } const rtd_entry_t *e0 RTD_TABLE[low]; const rtd_entry_t *e1 RTD_TABLE[high]; float frac (rtd_res - e0-res) / (e1-res - e0-res); return e0-temp frac * (e1-temp - e0-temp); }负温区的处理尤其要小心。RTD 在 0℃ 以下电阻不再是简单的线性关系查表法天然规避了曲线拟合的复杂度。我在表格里直接覆盖 -50℃ 到 150℃HVAC 场景完全够用。如果做工业高温测量就需要用 Pt100 表格或者直接用 CVD 方程迭代求解代码复杂度会上去但精度也能做到更好。代码里读到的原始 ADC 数据不要直接拿来算温度。先做软件滤波再换算电阻最后查表出温度。这个顺序不要搞反因为噪声经过电阻-温度转换曲线之后会变成非线性误差先滤波能压掉很多莫名其妙的跳动。3.3 软件滤波与工频干扰抑制硬件上有差分滤波软件里还要再做一道滤波才能达到控制回路能用的稳定度。温度信号变化本来就慢用任何滤波都不会带来明显滞后这是温度测量和电流测量最大的区别。我用的是二级结构先做滑动中值滤波剔除野值再做移动平均。中值窗口取 5 个点能有效丢掉偶发的尖峰脉冲移动平均窗口根据数据率调整100SPS 时取 20 个点等效时间常数 0.2 秒足够平滑也不会掩盖真实的温度变化趋势。float temp_soft_filter(float raw_temp) { // 1. 插入环形缓冲区计算中值 insert_ring(temp_ring, raw_temp); float median_val median_of_window(temp_ring); // 2. 对中值输出做滑动平均 return moving_average(ma_filter, median_val); }关于 50Hz 和 60Hz 干扰ADS122U04 内部有数字滤波器配置 CFG0 选 50Hz 和 60Hz 同时抑制即可。如果数据率取 100SPS还需要注意采样周期和工频周期的整倍数关系。我用 20 SPS 的数据率配 50/60Hz 抑制效果也非常稳。高速率对于温度测量没有意义还会把高频噪声带回系统所以不要盲目追求高 SPS。3.4 故障检测断线、短路和超量程温度传感器装在设备现场断线、短路甚至接错线都是常态。没有故障检测的采集系统在传感器断线时往往会显示一个离谱的温度值比如 -300℃ 或者 500℃控制逻辑可能因此做出危险动作。ADS122U04 的输入端有故障检测机制配合软件可以完成大部分诊断。我的做法是周期性检查转换结果的边界值。正常 PT1000 在 -50℃ 到 150℃ 对应的电阻范围大约 800Ω 到 1500Ω。转换后计算出的电阻如果低于 500Ω大概率是短路或传感器错误高于 3000Ω基本确定是断线。另外还可以用 ADC 的输入诊断电流往传感器注入小电流再测量进一步判断断线位置。软件检测到异常后不要只保存一个错误标志要同时记录是哪一路传感器、异常类型是什么。HVAC 控制器维修时看到“回风温度断线”和看到“温度显示 -40℃”是两种完全不同的体验。设备代码里把故障信息通过 UART 上报现场调试和维护效率高很多。4. 常见问题与调试避坑实录4.1 温度读数走势正确但相对值抖动很大这个是最常遇到的问题表现是传感器用水浴加热时整体趋势是对的但读数上下跳 0.2℃ 甚至更多。先查传感器激励电流是否稳定再看参考电阻温漂最后排查输入滤波电容。我遇到过一次非常隐蔽的情况就是因为输入滤波电容用了 X7R 材质滤波电容值随直流偏压变化导致差分滤波器不平衡共模干扰变成差模干扰进入 ADC。换回 C0G 电容后问题立刻消失。这件事给我的教训是精密测量电路里每个电容材质都要写清楚到 BOM不能让采购随便换。还有一次跳动原因让人哭笑不得是 ADC 的 UART 帧里偶发一位错误而我的代码当时没有做 CRC 校验把错误的转换结果当成有效数据参与平均。后来加上校验和重发机制后读数立刻稳定下来。这个问题在厂内测试很难复现到了现场变频器一开就出现就是因为噪声耦合进长线 UART 导致通信误码。4.2 工业现场通信不稳定、偶发连续读不到数据如果 ADC 和 MCU 之间距离超过一米或者走线经过动力电缆槽光靠 TTL 级别的 UART 铁定不稳。解决方案从上到下依次是加屏蔽、降波特率、做隔离、换 RS485。我在一个工业采集模块项目里ADC 板卡装在设备壳体里和主控板之间约 30cm 排线连接。设备原来用的是 230400 波特率一开变频器就频繁丢数据。后来把波特率降到 115200丢数据概率明显下降但没根治。最后把排线换成双绞屏蔽线主控端加光耦隔离才算彻底解决。如果你的系统里有继电器开关继电器触点闭合瞬间产生的火花干扰甚至能通过供电线路影响 ADC。这种情况下电源引脚要加 TVS模拟地和数字地之间加磁珠必要时把 ADC 板卡的供电改成 RC 滤波单独供电。干扰问题是综合性的不要指望单一措施能解决所有现场问题。4.3 上电后 ADC 无响应恢复默认配置也读不到数据先排除供电问题接着用示波器量 UART 的 RX 引脚是否有命令波形。ADS122U04 上电启动时间比较长不是 1ms 级别如果你在 MCU 初始化后立刻发送命令芯片可能还没准备好。我建议上电后至少等 100ms 再开始配置。还有一个容易忽略的点是 ADS122U04 的 UART 接口默认可能处于非标准状态比如由硬件引脚配置了地址匹配模式导致主机发送的帧在地址过滤时被丢弃。遇到这种情况先用引脚复位信号重新初始化再看手册确认地址匹配寄存器的默认值。4.4 校准实战不需要太贵设备也能做温度采集模块生产后一般要做离线校准。虽然比例式测量已经消掉了很多误差但 ADC 的偏移误差和增益误差、精密电阻的实际阻值偏差仍然存在。我的校准流程很简单零点和一点高温两点直线校正。零点用冰水浴把传感器探头插入碎冰和水的混合物中确保充分搅拌等读数稳定后记录偏移量。高温点用干井炉或者恒温水浴设置在 100℃ 或者 80℃记录增益偏差。对于要求高的客户可以加第三点中间温度验证线性。校准数据直接存放在 MCU 的 Flash 备份区域代码里每次上电读取并修正温度值。这里注意校准系数更新后要立即回读验证防止写入失败导致下次启动用旧数据否则生产现场会出现“这台机器校了怎么还是偏”的怪现象。生产测试软件里还要把校准后的读数与标准表比对偏差大于阈值直接报失败避免人工抄录出错。5. 从温度采集到完整产品的扩展方向5.1 多通道扩展和成本平衡ADS122U04 本身输入通道有限但实际 HVAC 控制器至少要测送风温度、回风温度、盘管温度、室外温度好几路。扩展方案有两种一种是每路传感器配一颗 ADS122U04另外一种是通过模拟多路开关共用一颗 ADC。如果对测量速度要求不高我更倾向于每路独立 ADC。当前 ADS122U04 的成本在整体控制器里占比有限但换来的好处是通道隔离、互不干扰而且某一颗 ADC 故障时只是丢失该路数据不会影响其他传感器。多路开关方案虽然省成本但开关导通电阻会影响测量精度加热器和阀门动作时的噪声也容易串到公共通道调试起来更费劲。5.2 让测量结果真正服务于控制系统温度测量只是整个项目的第一步后面藏着 PID 控制、设备保护、能效优化一系列逻辑。数据稳不稳定直接影响控制效果。我把采样结果做了时间戳管理MCU 每次收到新的温度值都记录接收时刻控制调度时根据数据新鲜度决定使用还是保持上一次控制量。这个思路在 HVAC 系统里很实用因为传感器故障时控制器不会突然撒手不管而是保持当前输出并报警给现场人员留出处理时间。5.3 MCU 资源还能用来做什么RA4M2 跑完温度采集和 PID 之后资源还留有大量富余我顺便把 RS485 通信、Modbus 从站、本地按键显示和故障记录都塞进去了。原来需要两颗 MCU 的功能现在一颗搞定整个控制器的器件数量少了很多。这里分享一个我自己的体会系统设计时把功能拆分到合理的主角身上ADC 专心测量、MCU 专心控制和通信比在单个 MCU 里硬扛所有任务要好得多。ADS122U04 的 UART 接口看似简单实际为系统隔离和布局带来了巨大的灵活性。如果你也在做类似的控制器不妨先画原理图把 ADC 前端、传感器接口和电源隔离想清楚了再写代码硬件稳了软件事半功倍。