“ADS122U04IPWR 这个型号第一眼看上去确实容易劝退人字母多、数字杂尾部还带一串封装代码。拆开看其实并不复杂——它是 TI 的一颗 24 位 Δ-Σ 型 ADC四路模拟输入内置可编程增益放大器PGA和两路恒流源最特别的是通信接口不是常见的 SPI/I2C而是 UART。也就是说不需要像伺候 SPI 器件那样拉一堆时钟线和片选线接上 TX、RX 两根线就能和 MCU 对话。把它和 ATmega32 搭配起来做工业和 HVAC 系统的温度测量算是一个很务实的经典组合ATmega32 虽然被不少人嫌老但它 USART、GPIO、定时器都够用资料多到翻不完胜在稳定和便宜。ADS122U04 负责把 RTD 或热电偶的微弱信号变成高分辨率数字量ATmega32 负责下发命令、读数据、跑滤波再转发给显示屏、变送器或上位机分工很清晰。这篇文章按我实际调试这套系统的顺序来写包括硬件接线、软件协议、RTD 和热电偶两种接法以及我在工业现场踩过的几个坑。不需要你从零啃几十页数据手册按文中的流程先搭一套能跑通的样板再回头去抠寄存器细节会快很多。1. 为什么要用“UART 型 ADC”做温度采集1.1 从应用场景倒推器件选型先看项目标题里的两个关键词工业、HVAC。工业场景的温度采集测点往往不在电控柜旁边。风管里、冷水管上、电机轴承附近、冷却塔回水口传感器线拉个十米二十米很正常。现场还有变频器、接触器、大功率泵阀一启动就是一堆电磁干扰。HVAC 系统也有类似问题尤其是空调机房、冷站强电和弱电经常挤在一个桥架里走。这类应用对温度测量的要求其实很明确精度能到 0.1~0.5°C分辨率最好到 0.01°C抗干扰要强长线传输不能有明显误差。如果直接用 ATmega32 内部那个 10 位 ADC理论分辨率也就 5V/1024≈4.88mV折算到 PT100 大概是 0.0128°C 一个码不对实际 PT100 灵敏度约 0.385Ω/°C1mA 激励下信号变化 0.385mV/°C10 位 ADC 的分辨率连 1°C 都费劲。就算用内部基准加过采样零漂和噪声也很难压下去。所以外挂一个高分辨率 ADC 是必然选择。至于为什么选 UART 接口的 ADC除了少两根线这个直观优势还有一个现实原因长线传输时如果走 SPISCK、MISO、MOSI、CS 四根线对时序要求更严格线一长波形就变形还得降速。UART 本身就是为异步串行通信设计的电平标准成熟中间还能加隔离芯片、转 RS-485改造起来非常灵活。ADS122U04 这颗芯片选了 UART 做接口等于把主控和 ADC 之间的距离限制放宽了一大截。1.2 ADS122U04IPWR 的核心能力拆解先把型号拆开看。ADS122U04 是主型号I 表示工业温度等级工作范围 -40~125°CPWR 是 TSSOP 封装加卷带包装。也就是说这货不是给玩具用的设计目标就是奔着工业现场去的。核心参数层面几个关键点24 位分辨率Δ-Σ 架构内部有数字滤波器支持 50Hz/60Hz 工频抑制4 路模拟输入可以配置成 2 组差分输入或 4 路单端输入PGA 增益 1~128 倍可选适合接热电偶这类毫伏级信号两路可编程电流源 IDAC1/IDAC2专为 RTD 激励设计电流值可配置内置温度传感器可用于热电偶冷端补偿UART 接口支持 2400 到 19200 甚至更高波特率帧格式带偶校验和双停止位这里最值钱的是两个东西第一是内置 IDAC搞 RTD 测量时不用额外配恒流源直接输出激励电流第二是内置温度传感器搞热电偶时冷端补偿不用再外挂一颗数字温度芯片。这两点能把 BOM 简化不少。关于 ATmega32我选它不图性能图的是成熟。AVR 架构的寄存器手册写得很规整USART 模块支持偶校验和两位停止位正好能满足 ADS122U04 的 UART 帧要求。采样速率也就是每秒几十个点ATmega32 主频 16MHz 绰绰有余还能剩不少 CPU 时间处理 Modbus 协议等。2. 系统硬件搭建与接口设计2.1 ATmega32 与 ADS122U04 的接线方式先给一张最简接线关系照着焊就能跑通。ADS122U04 这一侧需要的引脚是 DVDD、AVDD、DGND、AGND、TXD、RXD、RDYN、/RESET、AIN0~AIN3、IDAC1/IDAC2、REFP0/REFN0。ATmega32 一侧主要用到 PD0/RXD、PD1/TXD、PD2/INT0、一个普通 GPIO 做复位控制以及电源引脚。具体连接如下ATmega32 PD1(TXD) → ADS122U04 RXDADS122U04 TXD → ATmega32 PD0(RXD)ADS122U04 RDYN → ATmega32 PD2(INT0)ADS122U04 /RESET → ATmega32 普通 GPIO 或者直接接上拉电阻调试时用 GPIO 控制更方便AVDD 和 DVDD 统一接 5VAGND 和 DGND 单点连接TXD 和 RXD 之间不需要电平转换ADS122U04 支持 2.3~5.5V 电源5V 逻辑电平可以直接接到 ATmega32。如果为了更稳妥可以在串口线上各串一个 33Ω 电阻防止现场浪涌打坏引脚这个是我吃过亏后加的习惯。RDYN 是数据就绪信号低电平时表示 ADS122U04 已经有新的转换结果可以读了。把它接到 ATmega32 的外部中断 INT0理论上效率最高数据好了立刻进中断读不用轮询。实际上我后来改成了普通 GPIO 轮询因为采样率本来就不高几毫秒的延迟无所谓还能少写一个中断上下文。关于 CS 引脚ADS122U04 的 UART 模式里 CS 更多是起到同步和数据方向控制作用不是传统 SPI 那种片选。具体按数据手册接有一点可以肯定不要把 CS 悬空不当回事工业现场悬浮引脚容易耦合噪声宁可接个电阻固定电平。2.2 电源、接地与去耦工业现场的第一道坎很多人在实验室里跑得好好的板子一到现场就乱跳八成是电源和接地没处理好。ADS122U04 虽然是一颗 24 位 ADC但它不是神仙模拟电源纹波直接决定噪声底。我的做法是5V 模拟电源经过一颗磁珠或者 10Ω 电阻后再进 AVDDAVDD 和 DVDD 各配一个 1µF 陶瓷电容加一个 0.1µF 高频电容尽可能靠近芯片引脚。AGND 和 DGND 在 PCB 上单点连接不要大面积铺铜把它们连成一片不然数字开关噪声会顺着地平面灌进模拟前端。传感器屏蔽线也是个常规坑点。屏蔽层只能在主机端单点接地绝对不能两端都接——两端接地会形成地环路共模干扰变成差模干扰反而更糟。工业现场里这个错误的典型表现是温度读数有一个缓慢的、和现场其他设备启停相关的漂移。电源如果实在不干净还有一个简化方案让 ADC 用比例测量架构RTD 激励电流同时决定参考电压这样电源纹波在一定程度上被共模抵消。这个方法我在后面 4.1 节详细讲。3. 固件实现UART 帧格式、寄存器配置与读数流程3.1 ATmega32 串口如何匹配 ADS122U04ADS122U04 的 UART 协议要求帧格式是1 个起始位、8 个数据位、1 个偶校验位、2 个停止位。ATmega32 的 USART 完全可以满足只要在初始化时把 UCSRC 寄存器对应位配好。里面有一个必须注意的点UCSRC 和 UBRRH 在 ATmega32 上是共用地址的需要通过 URSEL 位来区分。写 UCSRC 时 URSEL 必须置 1写 UBRRH 时 URSEL 必须清 0。这个寄存器阴影问题坑过无数新手很多人上电后波特率不对、帧格式不对都是因为这一位没处理对。初始化代码可以直接用这一份主频按 16MHz、波特率按 9600 算#define F_CPU 16000000UL #define BAUD 9600UL void uart_init(void) { uint16_t ubrr F_CPU / (16UL * BAUD) - 1; UBRRH (uint8_t)(ubrr 8); UBRRL (uint8_t)(ubrr 0xFF); UCSRA 0x00; UCSRB (1 RXEN) | (1 TXEN); // URSEL1 表示写 UCSRC // UCSZ1:UCSZ0 11 - 8位数据 // UPM1:UPM0 10 - 偶校验 // USBS 1 - 2个停止位 UCSRC (1 URSEL) | (1 UCSZ1) | (1 UCSZ0) | (1 UPM1) | (1 USBS); }9600 波特率是我反复试过之后的推荐起点。再往上当然也能跑但工业现场长线上9600 的容错空间明显更大而且 ADS122U04 的采样率本身不高9600 绝对不会成为瓶颈。3.2 初始化序列与单次/连续转换逻辑上电后第一步是复位。建议通过 ATmega32 的 GPIO 控制 /RESET 引脚先拉低 10ms 再拉高然后延时 20ms 等内部振荡器稳定。比直接发复位命令更可控尤其调试现场复位时序时方便很多。复位之后要配置寄存器。ADS122U04 的寄存器组包括 ACR、CFR0、CFR1、CFR2分别管 ADC 配置和三个工作参数配置。它们各自管理的内容大致如下寄存器主要控制内容ACR转换模式、通道选择、PGA 增益、基准电压选择CFR0数据格式、50/60Hz 滤波、CRC 开关、内部温度传感器CFR1电流源路由决定 IDAC1/IDAC2 接到哪个引脚CFR2激励电流档位、转换时钟等人选项寄存器位到底怎么排布以数据手册为主我这里不替它背这个锅但配置逻辑是可以复用的先写 CFR2 确定电流大小再写 CFR1 把电流引到对应引脚再写 CFR0 打开滤波最后写 ACR 选通道和增益。顺序不要太随意尤其不要把 ACR 放太前面因为 ACR 里可能包含启动转换的位一步没配完容易出半初始化状态。写寄存器的指令序列是通用的发写寄存器命令字再发寄存器地址再发要写入的值。读寄存器类似命令字、地址、再读取若干个字节。我封装了几个最简单的小函数void ads_write_reg(uint8_t reg, uint8_t val) { uart_tx(ADS_CMD_WREG); // 命令字按数据手册指令表填写 uart_tx(reg); uart_tx(val); } uint8_t ads_read_reg(uint8_t reg) { uart_tx(ADS_CMD_RREG); uart_tx(reg); return uart_rx(); }转换模式一般选单次模式。每次需要采集时配置好寄存器后触发转换等待 RDYN 拉低读走结果。这样一个测点一个测点地轮询逻辑最简单也最容易排查问题。如果你的系统要求几个通道连续监测那可以用连续模式RDYN 每个转换周期都会拉低一次MCU 收到中断后读走最新数据即可。3.3 24 位数据读取与符号处理ADS122U04 是 24 位 ADC读回来的数据是三个字节顺序是高字节、中字节、低字节。这三个字节需要拼成一个 32 位变量并且要做符号扩展。因为输入信号可能是双极性的比如热电偶冷端温度逆向时电压可能为负所以 24 位码值是有符号数。拼完三个字节后要检查最高字节的符号位如果为 1 就要把 int32_t 的高 8 位全部补 1否则直接左移拼接就行。代码可以这么写int32_t ads_read_data(void) { uint8_t b2 uart_rx(); // 高字节 uint8_t b1 uart_rx(); // 中字节 uint8_t b0 uart_rx(); // 低字节 int32_t raw ((int32_t)b2 16) | ((int32_t)b1 8) | b0; if (raw 0x800000) { raw | 0xFF000000; // 符号扩展 } return raw; }单片机上做 32 位运算是很轻松的事ATmega32 这种 8 位 MCU 也能胜任无非是快慢问题。真正要注意的是读取时机必须在 RDYN 拉低之后立刻读读的过程中如果 RDYN 又拉高说明这组数据已经开始更新了读出来的可能是半新半旧的拼接结果。稳妥做法是连续读两次读数一致才采用不一致就丢掉重读。这个方法虽然笨但在现场调试时真的省心。4. 两种主流温度传感器的接入与调校4.1 三线制 RTD比例测量架构RTD 是工业和 HVAC 中最常见的温度传感器PT100 和 PT1000 用得最多。选 PT100 还是 PT1000主要看导线长度和系统功耗PT1000 灵敏度更高同样的导线电阻误差占比更小但需要检查 ADC 的 PGA 是否撑得住PT100 更皮实工业现场存量最大。聊到 RTD 测量无论如何绕不开三线制接法。两线制把激励电流和测量电压走同两条线导线电阻直接串进 RTD 阻值里10m 线就能引入 0.5Ω 以上的误差PT100 算下来可能偏好几度。三线制用三条线分担配合比例测量能把导线电阻误差压低到可接受范围。ADS122U04 做三线制 RTD 的思路是这样的用 IDAC1 和 IDAC2 输出两路电流分别经过 RTD 的两侧引线在 RTD 上汇合后流过一个精密参考电阻。测量 RTD 两端的电压同时把参考电阻上的电压当作 ADC 的基准。因为 RTD 电压和参考电压都由同一个 IDAC 电流产生所以电源和电流源的漂移会被当成共模量抵消掉。这个架构就是比例测量理论上只和 RTD 阻值与参考电阻的比值有关不依赖绝对电压。实际配置时我会把 PGA 增益和激励电流放在一起算。以 PT100、0~150°C 量程、1mA 激励为例PT100 在 0°C 时约 100Ω在 150°C 时约 157.3Ω电压变化范围是 100mV 到 157.3mV。如果参考电阻取 2kΩ参考电压就是 2V。要让 RTD 电压在 0~150°C 范围内尽可能占满 ADC 量程PGA 增益取 8 比较合适此时 157.3mV×8≈1.26V比 2V 参考低不少还有余量。如果量程改成 0~50°C 这种 HVAC 常见范围可以换更小的参考电阻或提高增益原则就是在不削顶的前提下尽量放大别浪费 24 位分辨率。配置好之后的数据换算也简单码值和电阻近似线性RTD 的常见温度系数约 0.00385Ω/Ω/°CIEC 60751 标准用查表或者 Callendar-Van Dusen 公式都能反推出温度。查表对 ATmega32 更友好把 -40~150°C 的电阻-温度对照表放进flash二分查找加线性插值误差在 0.1°C 之内。4.2 热电偶PGA 增益与冷端补偿HVAC 系统里偶尔也会碰热电偶比如监测冷冻机组排气温度、锅炉烟道温度或者一些被测点温度超过 200°C 的场合。热电偶的好处是测温范围宽、响应快、探头便宜耐造缺点是输出信号极其微弱K 型热电偶灵敏度大约 41µV/°CJ 型也就 55µV/°C 上下。这种信号不放大根本没法治。所以热电偶通道的 PGA 增益必须拉到最大档 128 倍。此时等效满量程等于参考电压除以 128如果用内部 2.048V 参考满量程约 16mV对应 K 型热电偶约 390°C 的温差。如果你的应用只需要 0~200°C这个范围够用如果现场要测 400°C 以上就得调整参考电压或者分压方案别硬套默认配置。冷端补偿是热电偶测量里最容易出错、也最影响精度的环节。原理大家都知道热电偶测的是热端和冷端的温差而不是绝对温度。ADS122U04 内置了温度传感器直接把它的读数当冷端温度省了外挂芯片。但要注意这个内置传感器的位置在芯片内部它的温度代表的是 PCB 上芯片附近的温度不等于热电偶接线端子处的真实温度。想做到 0.5°C 以内精度光靠芯片内置传感器有时候不够。我常用的方案是热电偶接线端子尽量贴近 ADS122U04 放置减小热阻冷端补偿用芯片内部温度传感器然后做一次两点校准。比如把探头顶进冰水混合物0°C和沸水100°C注意海拔修正里记下系统算出来的误差在固件里做线性补偿。这个方法成本极低效果立竿见影。热电偶信号处理流程是读取热电偶电压码值乘以 LSB 大小得到实际电压读取芯片内部温度作为冷端温度查热电偶分度表得到冷端温度对应的热电动势把两个电压相加反查分度表得到真实温度。这些查表运算在 ATmega32 上跑起来大概几毫秒完全能接受。4.3 传感器自热与激励电流选择RTD 测量本质上是给传感器通电流测电阻电流必然会产生焦耳热这就是自热效应。PT100 在静止空气中1mA 激励下的自热误差可能到 0.1~0.3°C在流动空气中会好一些。HVAC 风管里的风速大散热好问题不大但如果是管道表面贴装或者浸在导热硅脂里自热影响会更明显。ADS122U04 的 IDAC 电流档位是可以编程的从几百微安到毫安级。我通常先看传感器的自热系数数据没有数据就保守一点用 500µA。500µA 激励下 PT100 在 0°C 时电压只有 0.05V信号确实变小了但配合 PGA 增益完全能把这个信号撑起来而且自热误差能压到 0.05°C 以内。注意一味追求高分辨率去把电流调大最后可能精度没提升反而被自热误差拖累。我自己调过的一个栗子某次现场RTD 读数总是比实际水温高 0.4°C 左右怎么校准都校不掉。后来发现是上一版固件把 IDAC 设在 2mAPT100 自热严重。改成 1mA 再配合校准温差就下来了。这就是从代码上看不出、但实际影响很大的问题。5. 实测中的典型问题与排查记录5.1 常见问题速查表这部分是我的排查经验汇总整理成表格现场遇到问题可以直接对号入座。现象可能原因排查动作串口永远读到 0xFFRX/TX 接反或波特率偏差过大用示波器看 TX 波形确认起始位、停止位电平读寄存器返回全 0帧格式不对停止位不足或校验位不对检查 UCSRC 的 USBS、UPM1/UPM0第一次读数正常后面全是重复值单次模式触发逻辑不对没重新启动转换确认 ACR 中转换启动位是否被正确置位读数跳变幅度大但均值稳定PGA 刚切换通道后的第一个转换结果不稳丢弃切换到新通道后的头 2~3 次转换读数随导线长度明显漂移两线制 RTD 或参考电阻接法不对改三线制比例测量参考电阻放主机端接热电偶一直是 0°C 附近乱跳PGA 增益过低信号被噪声淹没把增益调到 128检查内部参考是否开启读数偏大并且波动传感器自热降低 IDAC 电流改为 500µA 或 1mA 并重新校准数据偶尔错一位UART 校验或电平毛刺用示波器抓波形检查线路长度和接地必要时降低波特率还有一个最容易忽视的问题传感器探头刚接入时ADC 需要时间稳定。内部滤波器有很多“历史数据”尤其是开启 50Hz/60Hz 滤波后稳定时间会变长。固件里最好的处理方式是开机后先执行几次无效转换再正式开始采样我一般丢弃前 10~20 个转换结果之后的数据才参与计算。5.2 关于 50Hz 工频干扰的那点事HVAC 现场的 50Hz 干扰几乎避不开。空调压缩机、风机、变频器哪个都在工频附近活动。热电偶信号是毫伏级的PGA 拉到 128 倍以后任何一点 50Hz 耦合都会被放大得非常明显。读数如果在 0.2~0.3°C 范围里周期性抖动先怀疑工频干扰。ADS122U04 内部滤波器有 50/60Hz 抑制模式配置好之后对工频及其谐波有明显压制。这个功能我建议默认开除非你的应用对采样速度有很高要求。代价是转换时间变长但对暖通空调的温度采集来说每秒能出 20 个有效数据都算奢侈了根本没人关心 100ms 还是 200ms 出一个数。外部的处理也不能省。传感器电缆要双绞并屏蔽屏蔽层单端接地模拟前端加一个 RC 低通滤波截止频率放 100Hz 左右把高频毛刺先滤一道。别指望全交给 ADC 内部的数字滤波器它解决的是工频这类窄带干扰对宽带脉冲噪声无能为力。5.3 长线传输与多点接地的坑工业现场测温传感器离主机几十米不稀奇。这时候除了干扰还有两个隐形问题地电位差和线间电容。多点接地会造成地电位差这个电位差会以共模电压的形式出现在 ADC 输入端。ADS122U04 的输入端不是完全无限制的共模电压太大超出 PGA 的输入范围读数就会失真而且看起来像是“随机跳变”非常有迷惑性。排查方法是把传感器端暂时断开用万用表测主机地和传感器地之间的电压差如果超过几百毫伏那基本就是地环路的问题。解决思路是采用三线制并保证屏蔽层只在主机端接地必要时用隔离电源和隔离通信把两个系统彻底分开。线间电容的问题更多体现在 UART 通信上。长线传输时TXD/RXD 的沿变缓波特率高了就可能出现误码。我做过最保守的方案是9600 波特率、双绞线、主机端加 33Ω 串阻几十米距离内通信非常稳定。如果还想再稳可以在固件里给每次寄存器读写加校验重试机制读回来不对就再读一次多一层保险。6. 一些个人体会整套系统从画板到现场跑通我最大的感受是ADS122U04 这颗芯片把模拟前端的复杂度降低了不少但真正决定系统精度的往往在电缆、接地和激励电流这些细节上。你可能花了很多时间在寄存器配置上结果最后发现误差源头是传感器线上多出来的一段屏蔽层接地。调试时建议先接 PT100 跑通整条链路再换热电偶。PT100 信号相对强出问题好分析热电偶信号弱出问题容易怀疑这怀疑那反而不好定位。固件里保留一个自检模式上电后自动读一遍内部温度传感器并回报判断芯片本身基本功能是否正常。这个动作只要十几行代码现场排查能省大量时间。最后一个小技巧ADS122U04 的寄存器配置值建议做成常量数组放在程序里每个通道一组。例如“RTD_PT100_3W”一组、“K_TYPE_THERMOCOUPLE”一组切换传感器类型时只需要换数组下标不用改一大段配置代码。我后来维护的几个项目都用这个方式哪怕换不同量程、不同传感器改动量都控制在十行以内出错概率也低很多。硬件平台的稳定性和软件配置的结构化才是这种经典组合能长期服役的根本原因。