
ADS122U04IPWR 这颗芯片在我的工作台上躺了挺长一段时间了。看到这个项目标题就觉得很典型工业或 HVAC 温度采集主控是 STM32F091RCADC 是 TI 的 ADS122U04IPWR。前者是一颗主频 48MHz 的 Cortex-M0Flash 256KB、SRAM 32KB规模不大但外设齐全后者是 24 位 Δ-Σ ADC带 UART 接口、4 路模拟输入、内置 PGA 和两路激励电流源。这两个型号放在一起基本就是一套能覆盖 PT100、PT1000、K 型热电偶和 NTC 的通用温度前端。这篇文章我会从选型原因、硬件链路、固件实现到现场调试四个部分拆开讲适合正在做多路温度采集项目、想把方案从估算变成原理图和代码的工程师参考。1. 方案选型解析ADS122U04IPWR 与 STM32F091RC 的组合逻辑1.1 工业/HVAC 测温先拆信号需求先说应用场景。HVAC 系统里最常见的是冷水机组、风机盘管、风管温度、回水温度监测传感器以 NTC 10K、PT1000 和少量 PT100 为主工业现场则更复杂一些除了 PT100/PT1000还会遇到 K 型热电偶测温范围可能从 -40℃ 到 800℃ 甚至更高。这些传感器输出的信号特征差别非常大。热电偶输出的是毫伏级热电势K 型热电偶典型灵敏度大约 41µV/℃测到 1℃ 的变化才 40 多微伏PT100 在 0℃ 时阻值是 100Ω温度每升高 1℃电阻大约增加 0.385Ω。如果用 1mA 激励电流1℃ 对应的电压变化是 0.385mV比热电偶大一个数量级但依然需要 ADC 在毫伏级分辨率下保持低噪声。NTC 则完全不同它的阻值随温度呈指数变化本身信号很大但非线性极强而且自热效应需要控制。ADC 位数的意义在这里就体现出来了。同样以 2.048V 满量程计算24 位 ADC 的理论最小分辨率大约是 244nV即使实际使用中因为噪声达不到这个极限也足够分辨 0.01℃ 级别的温度变化。而 12 位或 16 位 ADC 在 mV 级信号面前一个 LSB 对应的温度往往已经超过 0.05℃再加上工业现场的共模干扰和 50Hz 工频噪声精度就很难保证。这不是参数党意义上的追求高位数而是传感器信号本身的物理特征决定的。1.2 ADS122U04IPWR 的核心能力与 UART 自动轮询价值ADS122U04IPWR 是 TI ADS1220 系列的 UART 版本型号里的 U 就是 UART 的意思。它保留了 24 位 Δ-Σ 核心集成可编程增益放大器 PGA增益从 1 倍到 128 倍可选内部有 2.048V 基准电压、振荡器和温度传感器两路匹配的激励电流源 IDAC 可以输出 50µA 到 1.5mA 的电流专门拿来驱动 RTD。供电范围 2.3V 到 5.5V工业级温度范围封装是 TSSOP-16。这颗芯片最让我看中的是自动轮询功能。传统做法是主控通过 SPI 每转换一次都要发起命令先写寄存器启动转换再等 DRDY 引脚拉低然后读回 24 位数据。如果系统里要扫 4 路传感器主控就得不停打断当前的控制逻辑中断一多程序状态就容易乱。ADS122U04 在 UART 接口上把这个问题简化了配置好之后进入自动轮询模式ADC 自己按照设定好的通道顺序完成转换然后把结果帧通过 UART 主动发出来。主控这边只需要开一个 DMA 接收收到完整帧后解析通道号和 24 位数据就行。整个过程里主控不需要干预 ADC可以把 CPU 时间留给 PID 环路、通信协议栈或者人机界面。对于 HVAC 控制器这种既要控温又要跑 Modbus 又要刷显示屏的单片机来说这个优势非常实际。1.3 STM32F091RC 的定位够用、顺手、好扩展STM32F091RC 放在这个方案里也很合适。Cortex-M0 内核主频 48MHz用来做查表、线性化计算和浮点换算稍微紧张一点但处理几路温度数据完全够用。温度线性化不追求实时浮点大运算PT100 的 Clarkson 多项式或者预置查找表加上线性插值M0 可以在几百微秒内完成不影响控制周期。F091 系列有 5 个 USART这意味着可以拿出一路专门和 ADS122U04 通信再留一路给上位机或 RS485 模块互不干扰。它还支持 DMA 和空闲中断配合 HAL 库实现 UART 不定长接收非常顺手。我实际用下来自动轮询帧到达后触发一次空闲中断DMA 把整帧数据搬进缓冲区CPU 只需要在回调里做解析负载很低。选择外部 ADC 而不是直接用 STM32 内部 12 位 ADC 也是个明确决定。内部 ADC 的优势是零成本、零接线但 12 位分辨率在 PT100 这种传感器面前太粗糙而且内部基准和输入通道很容易受数字电路噪声影响。工业现场里电机变频器、接触器一动作内部 ADC 的读数经常跳十几二十个字这种问题靠软件滤波治标不治本。把模拟前端独立出去让专业的人干专业的事是这类产品的基本设计原则。1.4 与其他方案的横向对比评估方案时我列过一张表分享给同样纠结过的朋友方案分辨率接口激励电流自动扫描典型应用STM32 内部 ADC12 位内部无无低成本家电、粗略温度保护外部 16 位 SPI ADC16 位SPI需外置无精度要求不高的 RTD 采集ADS122U0424 位UART内置双 IDAC支持工业/HVAC 多通道混合测温MAX3186515 位SPI内置单通道专用 RTD 前端不能测热电偶MAX31865 也是好芯片但它专为 RTD 设计做不了热电偶和 NTC 的灵活接入。ADS122U04 的优势是通用性差分输入可以接热电偶比例式接法可以接 RTD内置 PGA 可以放大毫伏级信号再加上 UART 自动轮询一个 ADC 就能把不同类型的传感器统一到一个通信协议里大大简化主板设计。2. 硬件链路搭建从传感器到 MCU 的每一个引脚2.1 RTD 比例接法这是精度秘密所在RTD 测温最容易踩的坑是激励电流源的漂移。如果用固定电压或者固定电流激励只要电流或电压源有一点温度漂移测量结果就会跟着漂而且很难校准。ADS122U04 支持比例式接法思路是把参考电阻 RREF 和 RTD 放在同一条电流回路里参考电压取自 RREF 两端。假设 IDAC 输出电流是 I流过 RTD 产生电压 I×RRTD流过 RREF 产生参考电压 I×RREFADC 最终得到的输出比例为 RRTD / RREF和电流 I 的绝对值没有关系。哪怕电流从 500µA 慢慢漂到 510µA分子分母同时变化比例值不变测量结果依然稳定。我常用的配置是 PT100 加 500µA 电流RREF 选 4.096kΩ这样参考电压正好是 2.048V芯片内部参考可以直接旁路掉用外部 RREF 作为基准源。满量程对应 4.096kΩPT100 在 850℃ 时电阻约 390Ω即使裕量很大也不会饱和分辨率依然非常充裕。3 线制长线补偿是另一个重点。工业现场传感器往往距离主板十几米甚至几十米两根线缆的引线电阻可能各有 5~10Ω这对 PT100 来说意味着几十摄氏度的误差必须处理。3 线制的核心是用两路匹配 IDAC 给两根引线供同样的电流再通过差分测量把引线压降抵消掉。实际接线时要注意 IDAC 的电流方向和采样点位置尽量让信号线和激励线分开走避免把引线压降叠加到信号回路上。2.2 热电偶与 NTC 输入差分、增益、冷端热电偶不能用比例式接法因为它输出的是热电势必须依赖一个绝对参考电压。我的做法是直接差分接 AIN0/AIN1PGA 设为 32 倍或 64 倍。K 型热电偶在 0~1000℃ 范围内输出约 40mV32 倍增益后信号会放大到 1.28V在 2.048V 参考下动态范围利用得很充分又不会饱和。热电偶的另一个关键点是冷端补偿。ADS122U04 内置的温度传感器可以直接读取芯片附近的温度用来做粗略补偿精度通常在 ±2℃ 左右这取决于芯片自身温度和环境温度的温差。如果项目要求整体精度在 ±0.5℃ 以内建议在接线端子附近额外放一颗高精度 NTC 或小封装 PT100用单独的 ADC 通道采集冷端温度再在软件里做补偿。芯片内部温度传感器可以作为冷端超温保护或者自检用途两套数据互补使用。NTC 最省事但也最容易忽视自热。NTC 阻值高10K NTC 在 25℃ 时阻值就有 10kΩ如果用 IDAC 的 500µA 去驱动功耗高达 2.5mW足够让 NTC 自身升温读数偏高不少。所以 NTC 一般不用 IDAC 驱动而是用普通分压电路把流过 NTC 的电流控制在 100µA 以下或者在软件里做周期性采样用低占空比维持测量减小自热误差。2.3 电源、基准与 PCB 布局注意事项ADS122U04 的模拟供电建议用低噪声 LDO3.3V 通过一个磁珠或 RC 滤波后送给 AVDD数字电源 DVDD 可以和 MCU 共用但也要加独立去耦电容。芯片每个电源引脚旁边放一个 100nF 陶瓷电容10µF 钽电容兜底。模拟地和数字地建议采用单点汇接ADC 芯片下方的地平面保持完整不要让数字信号导线横穿模拟区域。内部基准 2.048V 对大多数场景够用但如果现场电源纹波大或者对长期稳定性要求高我会选择外部精密基准。外部基准可以直接接到 REFP/REFN 引脚和芯片内部基准通过寄存器切换。布线时 REF 引脚周围尽量少走数字线避免高频噪声耦合到基准上。关于 PCB 布局有三个容易忽略的细节输入引脚到传感器的引线尽量短而直形成差分走线模拟输入前端加 RC 低通滤波典型值 R1kΩ、C1nF截止频率约 160Hz既不影响 20SPS 采样又能滤掉大部分高频干扰最后是传感器端子附近要放 TVS 管或钳位二极管防止外部静电和浪涌进入 ADC。2.4 与 STM32F091RC 的接口连接和保护电路STM32F091RC 和 ADS122U04 之间是标准的 UART 连接引脚分配很常规STM32F091RC 引脚方向ADS122U04 引脚说明PA9 / USART1_TX输出SDI / RX单片机发命令PA10 / USART1_RX输入SDO / DOUT接收数据和状态PC0 GPIO输出RESET复位信号PC1 GPIO输入DRDY / BUSY可选判断繁忙状态需要特别提醒的是 UART 的 TX/RX 交叉问题。画原理图时大家都会交叉但画 PCB 或接调试线时经常有人把 PA9 误接到 ADC 的 SDO 上结果收不到任何数据。上电调试第一步最好用示波器或者逻辑分析仪看 TX 引脚有没有波形没有波形就查串口初始化有波形但 ADC 不回数据再查交叉。如果传感器线缆超过 3 米建议在 UART 线路上加数字隔离器比如 ISO7721把模拟前端和主控的电气地断开。工业现场的共地干扰、地电位差和浪涌是导致通信错误和芯片损坏的重要原因。我做过一个项目传感器线缆走到配电柜附近后UART 通信原本稳定的数据开始出现偶发丢帧把电源和信号彻底隔离后才恢复。3. 固件实现让 ADC 自动扫完 4 个通道3.1 初始化流程与复位时序固件初始化第一步不是配置寄存器而是复位。ADS122U04 的 RESET 引脚拉低至少保持数微秒再拉高芯片内部上电复位完成之前任何寄存器写入都可能无效。我习惯在代码里做保守处理void ads_reset(void) { HAL_GPIO_WritePin(ADS_RESET_GPIO_Port, ADS_RESET_Pin, GPIO_PIN_RESET); HAL_Delay(1); HAL_GPIO_WritePin(ADS_RESET_GPIO_Port, ADS_RESET_Pin, GPIO_PIN_SET); HAL_Delay(10); }复位完成之后芯片会进入待命状态。ADS122U04 的 UART 通信波特率需要和主控保持一致常用 115200bps8 数据位、无校验、1 停止位。写入命令的格式是先发命令字节再跟数据字节例如写寄存器命令是 0x40 | 寄存器地址随后发送要写入的寄存器值读寄存器命令是 0x20 | 寄存器地址然后等待 ADC 返回一个字节。整个通信过程用 HAL 的阻塞式收发就能满足因为 ADC 寄存器操作只在初始化阶段执行不会占用太多时间。3.2 寄存器配置每一个字节代表什么ADS122U04 的寄存器不多核心是三个寄存器 0 负责输入多路复用选择和 PGA 增益寄存器 1 负责数据速率、转换模式和参考电压源寄存器 2 负责激励电流源大小和输出路由。我常给 RTD 通道做这样的配置输入选择AIN0/AIN1 差分输入PGA 增益1 倍数据速率20SPS参考源外部 RREF 的差分电压IDAC500µA路由到对应激励引脚选择 20SPS 不是随意定的。ADS 内部的数字滤波器对 50Hz 和 60Hz 工频干扰有很强的抑制能力20SPS 正好和工频周期同步可以最大化滤除电网耦合噪声。我试过把速率调到 1000SPS 后再做软件平均效果反而不如直接用 20SPS一方面是因为混叠另一方面是因为高速率下噪声底更高软件平均的收敛速度跟不上。3.3 自动轮询模式的数据帧解析初始化完成后发送启动命令并开启自动轮询模式。此后 ADC 会按照输入多路复用器的顺序依次转换并把每个通道的 24 位结果主动发送到 UART 总线上。自动轮询的帧结构大概是这样的帧头或通道标识占一个字节后面跟 24 位转换结果再跟一个校验字节。不同固件版本或数据手册的命名可能有差异关键是程序解析要以通道标识作为同步点而不是依赖固定帧长从头到尾对齐。我用的解析方法是状态机每次从 DMA 缓冲区取一个字节通过状态切换把 24 位数据拼出来判断通道号后交到温度换算模块。为了减轻主控负担我用 UART 空闲中断加 DMA 接收void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if (huart huart2) { parse_ads_frames(rx_buffer, Size); HAL_UARTEx_ReceiveToIdle_DMA(huart2, rx_buffer, sizeof(rx_buffer)); } }缓冲区里的数据可能包含半帧也可能包含多帧所以解析函数必须能处理跨缓冲区的帧。最简单的方式是状态机不依赖缓冲区边界每来一个字节就推进状态这样即使一帧数据被拆成两段也不会丢数据。3.4 从原始码到物理温度的计算与线性化拿到 24 位原始数据后第一步是转成电压。ADS122U04 输出的是二进制补码负满量程是 0x800000正满量程是 0x7FFFFF。转换公式是int32_t sign_extend_24(uint32_t code) { return (code 0x800000u) ? (int32_t)(code | 0xFF000000u) : (int32_t)code; } float ads_code_to_voltage(int32_t raw, float vref, float gain) { return (float)raw * vref / (8388608.0f * gain); }这里 8388608 就是 2 的 23 次方表示正满量程一半。对 RTD 的比例式测量其实可以跳过电压换算直接算电阻比例float ratio (float)raw / 8388608.0f; float r_rtd ratio * rref_value;PT100 的电阻温度换算我推荐两种做法。如果 Flash 空间充足用预置表加线性插值最快例如每 5℃ 存一个电阻值查询时先定位区间再线性插值误差小于 0.05℃。如果希望完全用公式PT100 在 0~850℃ 范围内用 Callendar-Van Dusen 方程反向求解用二分法迭代每次迭代 10 次以内即可收敛。热电偶的计算稍微复杂。先把原始码转成电压再用 NIST 多项式或查表把电压反解成温度同时要考虑冷端温度补偿读取芯片内置温度传感器或外部 NTC 的数值作为冷端温度查出该温度对应的热电偶电压加到测量电压上再反查热电偶电压表得到热端温度。这个流程在 M0 上执行时间不到 1ms如果在 20SPS 采样率下CPU 占用完全可以忽略。3.5 校准与冷端补偿的工程做法即使 ADS122U04 本身是 24 位高精度芯片系统里还有其他环节的误差需要校准。偏移误差主要来自传感器引线、放大器和 ADC 的失调增益误差主要来自 RREF 电阻的精度、激励电流的匹配度以及 PGA 的增益误差。我习惯做两步校准第一步把 ADC 输入端短路记录偏移码在数据处理时减去第二步接一个高精度已知电阻替代传感器例如 0.1% 精度的 100Ω 电阻让 ADC 测量后反推出增益修正系数。这两个系数保存到 MCU 的 Flash 里上电后自动加载比每次上电做完整校准省时间。冷端补偿在校准里最容易被忽略。如果只用芯片内部温度传感器做冷端必须让 ADC 芯片和热电偶接线端子温度一致不要让板卡上的发热元件靠近冷端。我实际体会是冷端补偿的误差直接叠加到热电偶最终温度上冷端差 1℃热端就跟着差 1℃。如果要求高建议在端子上放一颗 1% 精度的 NTC和热电偶冷端贴在一起再单独做一阶校正整体精度能提升不少。4. 实测数据与问题排查实录4.1 20SPS 下的真实噪声表现我搭的测试环境比较朴素STM32F091RC 核心板加自制模拟前端板PT100 用 0.1% 精密电阻代替设置 20SPS、PGA 1 倍、内部参考旁路连续采集 500 个点观察波动。结果比较理想。转换码的峰峰波动在 10~20 个 LSB 左右换算成电压大约 2.4~4.9µV对应 PT100 的温度波动大概是 0.006~0.013℃。这个数值已经优于大多数 HVAC 控制回路的精度需求冷水机组出水温度控制能做到 0.05℃ 以内的稳定输出。测试时还有一个发现20SPS 模式下 50Hz 工频抑制效果非常明显手靠近传感器线缆时读数几乎不受影响换成 1000SPS 高速率后即便做滑动平均干扰依然有残留。多通道自动轮询时通道切换瞬间会有短暂建立时间。我观察到的现象是每个通道的前 1~2 个转换结果偶尔会偏大或偏小处理方式很简单丢弃每个通道刚切换后的第一个转换结果或者连续采两次、只保留后一次效果就很干净了。4.2 常见问题排查表从通信到干扰实战中遇到过的问题我整理成了表格基本覆盖了这类 UART 接口 ADC 的典型故障症状可能原因排查动作完全收不到数据TX/RX 接反、波特率不一致、RESET 未释放示波器查 TX 波形核对 UART 配置检查复位电平数据偶尔断帧DMA 缓冲溢出、帧同步错误加大缓冲区检查空闲中断处理逻辑读数整体偏大或偏小RREF 精度不够、增益未校准换高精度电阻做偏移/增益校准读数在固定区间跳变50Hz 工频干扰、地环路改用 20SPS检查模拟地和数字地单点连接通道间互相串扰通道切换建立时间不足丢弃切换后首个转换值降低采样率热电偶读数完全错误冷端未补偿、极性接反检查输入极性加入冷端温度计算NTC 读数偏高且不稳定自热效应降低激励电流或改成分压电路有一类问题我觉得值得单独强调就是地环路。传感器线缆很长时传感器地和主板地之间可能存在电位差导致 UART 通信错误或者模拟输入漂移。解决手段是采用数字隔离器把 ADC 和主控隔开或者用隔离电源给前端独立供电。这个改造在配电柜项目里效果立竿见影原先偶发的丢帧和数据漂移全部消失。4.3 我踩过的三个坑与改进建议第一个坑是 DMA 接收的帧解析。最初我按固定帧长做缓存对齐结果自动轮询模式下数据流连续到达缓存经常被半帧数据占据导致整个帧解析错位。后来改成字节状态机每接收一个字节就推进解析状态不再依赖缓冲区边界这个问题才彻底解决。同样的思路也适用于其他 UART 流式传感器。第二个坑是三线制 PT100 的接线。第一次做长距离测试时我只接了一条激励电流另一路引脚悬空结果引线电阻补偿完全没有生效20 米线缆带来的误差高达十几摄氏度。后来两路 IDAC 都按数据手册接好并且保证两路激励电流的匹配度现场读数才恢复正常。第三个坑是自动轮询模式下的通道配置。一开始我以为所有通道共用同一套寄存器把 RTD 通道的激励电流路由设错了导致热偶通道也被强制导入了电流板上两个传感器互相干扰。后来我在初始化里严格区分每个通道的用途并加了一个通道标识诊断上电后先回读每个通道的配置再做自检避免这类低级错误流入现场。最后给个建议原理图上尽量把每个输入通道的硬件配置做成可跳线的既能接 RTD、也能接热电偶和 NTC。我在板上留了四个区域的跳线位打样后调试非常方便不需要每次改版就能适配不同项目。ADS122U04 和 STM32F091RC 这套组合从成本、灵活性和稳定性上都很适合作为工业温度采集的标准前端如果你手头正好有类似项目完全可以按这套思路先搭一版原型试起来。