最近在给一套小型工业温控系统做核心采集板主控用了 STM32F042K6温度采集前端的链路绕了一圈最后定下来用 TI 的 ADS122U04IPWR。这枚 24 位 Δ-Σ ADC 通过 UART 和主控通信省掉了一堆 SPI 时序上的麻烦事。趁着项目刚收尾把整套方案从选型、硬件接线到固件实现的一次性经验整理出来希望能给同时踩在 HVAC 和工业温度采集这条线上的同行一点参考。这个方案解决的核心问题其实很朴素工业现场和 HVAC 系统里温度传感器类型杂热电阻、热电偶、NTC 都有而 MCU 自带的 ADC 分辨率不够干扰环境下读数漂得没法看。ADS122U04 把采集前端的问题打包解决掉STM32F042K6 只管通过串口发命令、收温度数据开发和调试的复杂度一下就降下来了。如果你手里正好有这类中小规模测温需求又不打算为此上复杂的高端采集方案这篇文字应该能帮你少走不少弯路。1. 方案整体设计与选型思路1.1 为什么最终选了 ADS122U04IPWR 而不是普通 ADC先坦白讲一开始我也没第一时间就锁定这颗料。早期方案里考虑过用 MCU 内置 ADC 直接采也考虑过外挂一颗常见的 16 位 SPI 型 ADC但最后都因为实际需求被否掉了。这个项目的输入信号有 RTDPt100/Pt1000、K 型热电偶、还有 4~20mA 变送器转出来的电压信号三路信号幅值差异大现场还有电磁干扰普通 12 位 ADC 的噪声和温漂完全不够看。ADS122U04IPWR 最吸引我的几个点第一是 24 位分辨率理论上低位数的有效精度能压到微伏级别这对小信号采集来说属于质变。第二是它内部集成了可编程增益放大器和一个 2.048V 基准源针对热电阻做比例式测量时基准源直接驱动传感器桥路外部几乎不需要额外的高精度电阻网络。第三也是最关键的一点这颗 ADC 用的是 UART 接口而不是 SPI。UART 接口这件事懂的人都懂。SPI 在短距离、低噪声环境里没有问题但工业现场的线缆经常要走一两米SPI 的时钟信号容易在这类环境下引入串扰和反射。换成 UART 之后我可以用很低的波特率跑比如 9600bps两根线搞定通信抗干扰能力比 SPI 强不少。再加上 STM32F042K6 的 USART 外设本身就带 FIFO 和中断控制处理起来相当于在跟一个“温度采集传感器”对话而不是在低位操作 SPI 寄存器。这颗 ADC 还有一个低调但非常实用的特性内部有输入多路复用器支持差分输入可以用来同时接不同类型的传感器。我之前用过一些单端输入的 ADC接热电偶时负端很容易被地线上的噪声污染差分输入直接从物理层面上规避了这个问题。1.2 STM32F042K6 在这个链路里的分工STM32F042K6 在我看来选得刚刚好它是一颗 Cortex-M0 内核的芯片主频 48MHzFlash 32KBRAM 6KB。从数字上看性能不算出彩但温度采集这种应用场景真正吃性能的不是算力而是外设的合理性和配置灵活度。STM32F042K6 内置了多个 USART其中至少有一个能支持我们需要的异步串口通信。它的 USART 外设支持 LIN 和 IrDA功能比较全但更实用的是它的 DMA 和中断配合能力。我在代码里把 USART 接收中断打开之后每收到 ADC 返回的一帧数据就置一个标志位主循环检测到标志位后解析数据、做滤波、计算温度值整个过程完全不阻塞主流程。另外一个需要夸一下的地方是它的供电范围宽我这边模拟和数字混合供电STM32F042K6 工作在 3.3V而 ADS122U04 同样支持 2.3V~5.5V 供电两边直接共用一条 3.3V 电源轨省了一路 LDO。这种“同轨供电”看似小事情实际在板卡布局时少了很多电源处理上的麻烦。这套组合还有一个我比较喜欢的点就是 MCU 这边没有复杂的启动时序要求上电之后初始化串口、拉高 ADC 的复位引脚、延时几十毫秒、发一条命令ADC 就开始正常工作了。相比之前用过的某些 FPGA 配合专用采集芯片的方案这套东西对嵌入式工程师太友好了一个人几个小时就能把链路调通。1.3 针对 HVAC 场景的一些额外考虑HVAC 场景和纯工业设备有一条很大的区别就是空间限制往往很严格。中央空调的控制板就这么大一块地方没办法给你放一个大尺寸的隔离电源模块和屏蔽罩。ADS122U04IPWR 是 TSSOP-16 封装占板面积非常小搭配一个 STM32F042K6 的 TSSOP-20 封装整个采集板可以做得很紧凑。HVAC 系统里还有一个不容易注意到的细节就是传感器线缆长度和走线位置往往紧挨着压缩机、风机这类感性负载。这种环境下的共模干扰非常明显。ADS122U04 的差分输入在这里发挥了明显作用配合我在 PCB 上做的输入滤波电容读取到的数据稳定度比之前的设计高了一个档次。对于 HVAC 这种长期通电、无人值守的设备稳定比性能上限更重要这也是我不选那些带宽极高但抗干扰稀烂的方案的原因。2. 硬件细节设计与数据手册没明说的坑2.1 最小系统的搭建与供电设计ADS122U04IPWR 的供电设计看起来很简单数据手册给的是 AVDD 和 DVDD 可以短接在一起但我实际测试后发现如果直接用同一个 LDO 输出供电采集数据的底噪会高出不少。原因是 MCU 的串口通信翻转和高频数字逻辑会通过电源轨耦合到 ADC 的模拟部分。我的解决办法非常简单ADC 的 AVDD 和 DVDD 分别串一个 10Ω 的小电阻再接 LDO电阻和引脚之间各放一个 0.1μF 和 10μF 的电容。这属于最廉价的电源隔离方案实测下来效果明显底噪大概降了 40%。对于手持设备和空间有限的应用来说这种做法的性价比非常高。AVDD 我这里最终用了 3.3V虽然 ADC 支持 5V但考虑到 STM32F042K6 的串口电平是 3.3V如果 ADC 用 5V 供电它的 UART 输出高电平很可能接近 5V虽然 STM32 的引脚标注 5V 容忍但为了稳妥我还是统一到了 3.3V。如果你的系统里恰好只有 5V 电源记得在 TTL 串口之间加一级电平转换别直接硬连。参考电压这个点也要说一下。ADS122U04 内部有一个 2.048V 的基准电压我用它来做比例式 RTD 测量时基准的正负两端分别接到 RTD 的激励电路上。需要注意 REFP 和 REFN 之间也需要加一个 0.1μF 的旁路电容位置越靠近芯片越好。我第一次画板时把电容放远了 1 厘米左右结果读数在不同增益档位下出现了明显的偏差改回靠近引脚之后就正常了。2.2 传感器接入方式与滤波电路RTD 和热电偶的接入方式完全不同这一点是项目里最需要仔细拆解的部分。RTD 接法是比例式三线制这是工业现场最常见的接法。三根线分别为红线、白线和另一根同色线其中一根线连接 RTD 的一端另外两根线分别连接到 RTD 的另一端和桥路补偿端。ADS122U04 内部自带恒流激励源我配置激励电流为 250μA。这样做的好处是电流经过 RTD 产生的电压直接和参考电压成比例不会因为激励电流的绝对误差产生温度偏移。三线制测量的原理其实就是为了抵消导线电阻。两条等长度导线产生的压降分别在激励回路和检测回路里等量出现ADS122U04 的差分输入能够把两者的差值提取出来。实际接线时只要保证两根导线材质、长度一致在常温下测量精度能到 ±0.2℃ 以内这个水平对 HVAC 系统完全够用。热电偶则是另一套玩法。因为热电偶输出的是微弱电压信号且必须冷端补偿我把 K 型热电偶直接接到 ADC 的差分输入通道并在板卡靠近热电偶端子处放置了一颗 NTC 热敏电阻用于测量冷端温度。ADS122U04 的高阻抗输入不会从热电偶分走明显的电流所以不用额外加运放这是这颗 ADC 很省事的点。我在每个模拟输入通道上都加了一个简单的 RC 低通滤波器电阻用 1kΩ电容用 0.1μF截止频率大概在 1.6kHz 左右。这能滤掉风机、电机换向带来的射频干扰但不会拖慢传感器的响应速度。要注意的是RC 滤波器的电阻如果太大会产生额外压降在测量热电偶时会造成误差1kΩ 是经验上比较平衡的值。2.3 PCB 布局的一些手工经验PCB 布局里有三件事是绝对不能省的模拟地分割要干净、输入信号和数字信号不能平行走线、去耦电容必须靠近电源引脚。ADS122U04 的模拟输入引脚非常敏感我吃过一次亏因为布线时图方便让数字串口线从模拟输入通道下方经过导致测量回路里始终存在一个周期性的毛刺干扰。后来重新布线把串口线的走线层和模拟输入走线层分开并用整块地平面做隔离这个问题才消失。所以如果你在画板务必要注意物理层面的隔离这比任何软件滤波都有效。TSSOP-16 封装的引脚间距很小手工焊接时两个相邻引脚之间容易连锡。我建议焊完用放大镜检查一遍同时用万用表测一下电源和地之间有没有短路。ADS122U04 这种芯片一旦电源短路内部基准和 LDO 电路很容易烧掉而且烧坏之后表现可能是“能通信但读数全错”特别隐蔽。如果条件允许还是让工厂打板贴片回流焊的可靠性远超手工焊接。我这次是手焊的原型板焊完检查了两遍最终跑起来还算稳定不过手工焊明显影响了一些高频信号的稳定性所以评估阶段用没问题量产千万别这么干。3. 固件实现UART 协议与 STM32F042K6 驱动3.1 命令帧结构和读取流程ADS122U04 和主机之间的通信格式非常简洁主机发命令ADC 返回数据。它支持多种命令类型包括读取数据、写寄存器、启动转换等。我实际用到的命令就三种写配置寄存器、开始转换、读取转换结果。首先说一下最常用的写寄存器操作。ADS122U04 的寄存器共有 7 个 8 位寄存器但我通常只需要配置 0x00 到 0x05。发送格式是命令字节加上数据字节比如我要配置输入多路复用器选择 RTD 通道并启动 PGA我发送的指令格式大致是命令头 0x42后面跟寄存器地址和数据具体字节顺序是0x4X AA DD其中 AA 是寄存器地址DD 是写入的数据。ADC 收到后会把写入的数据回发主机可以据此校验通信是否正常。这一步别嫌啰嗦我在调通之前因为搞错了字节顺序浪费了半小时最后发现是把地址和数据的先后搞反了。读转换数据的命令是一次性的主机发一个特定命令字节ADC 会返回 24 位转换结果。这里有一个细节ADS122U04 返回的字节顺序是高字节、中字节、低字节组装时要自己移位拼起来。如果不小心把低字节当高字节移位算出来的电压值会错得离谱而且是那种“看起来有点道理但不正确”的错很难排查。3.2 STM32F042K6 端的关键代码片段STM32F042K6 这部分我主要用了标准外设库风格来做虽然现在网上流行用 HAL 库但我觉得这种小项目里用寄存器操作反而更直接。下面是我初始化 USART 和中断接收的核心片段你可以直接参考void USART_Init(void) { RCC-AHBENR | RCC_AHBENR_GPIOAEN; RCC-APB1ENR | RCC_APB1ENR_USART2EN; GPIOA-MODER ~(GPIO_MODER_MODER2_Msk | GPIO_MODER_MODER3_Msk); GPIOA-MODER | GPIO_MODER_MODER2_1 | GPIO_MODER_MODER3_1; GPIOA-AFR[0] | (1 8) | (1 12); USART2-BRR 48000000 / 9600; USART2-CR1 USART_CR1_UE | USART_CR1_RXNEIE | USART_CR1_TE | USART_CR1_RE; NVIC_EnableIRQ(USART2_IRQn); }中断里我把接收到的字节按状态机塞进缓冲区uint8_t rx_buf[8]; uint8_t rx_index 0; void USART2_IRQHandler(void) { uint8_t data; if (USART2-ISR USART_ISR_RXNE) { data USART2-RDR; rx_buf[rx_index] data; if (rx_index 8) { rx_index 0; rx_complete 1; } } }读取 ADC 转换数据的完整流程是主循环里先清空接收缓冲然后调用UART_SendByte(0x22)这种命令再等待中断把数据收满最后把三个字节拼成一个 32 位整数。这个流程写起来不长但调试串口时最需要注意的是波特率。我一度因为忘记了 STM32F042K6 的内部时钟默认是 HSI 8MHz而代码里按 48MHz 算波特率导致串口完全收不到数据。检查时钟树配置比检查代码逻辑更快发现这个问题。3.3 配置 ADS122U04 寄存器的实际参数我这次项目用了两路输入一路是 Pt1000 三线制 RTD另一路是 K 型热电偶。为了切换测量不同的传感器我必须每次测量前重新写寄存器而不能让 ADC 一直停留在同一配置。以 Pt1000 为例我配置MUX[3:0]为 AIN0 和 AIN1 差分对PGA 增益设为 8 倍内部基准使能激励电流源恒流 250μA 从 AIN2 输出。这样接法有一个好处激励电流同时流过 Pt1000 和参考电阻两者形成的比例关系能直接消掉电流源的温漂。void ADC_SetRTDMode(void) { uint8_t cfg0 (0x10 0) | 0x02; // AIN0-AIN1 差分PGA8 uint8_t cfg1 0x20; // 250uA 激励电流 uint8_t cfg2 0x00; ADC_WriteReg(0x00, cfg0); ADC_WriteReg(0x01, cfg1); ADC_WriteReg(0x02, cfg2); }如果是 K 型热电偶则把 MUX 切到另一对输入引脚激励电流关闭PGA 增益设为 32 倍同时片内冷端补偿只靠外部 NTC 读取。这两个配置之间需要加一点转换稳定时间我实际延时了 50ms 再做下一轮转换这样能保证 MUX 切换和 PGA 建立时间足够。初始化寄存器之后建议读回来做一次校验。我写了一个ADC_ReadReg函数把读到的寄存器和期望值做对比如果不一致就报错并且隔一秒重试。这个方法在现场排查时特别管用因为很多间歇性故障其实就是上电瞬间芯片没完全启动寄存器配置没写进去。4. 实际调试过程与常见问题排查4.1 串口通信无反应的排查顺序我调试这套系统时碰到过好几次“MCU 发命令后 ADC 完全不应答”的情况。这类问题有一个非常典型的排查顺序建议你按这个顺序来别上来就改寄存器配置。先量 ADC 的供电电压和复位引脚确认芯片处于工作状态。ADS122U04 有一个 RESET 引脚低电平有效。如果这个引脚被 MCU 的高低电平拉住ADC 会一直处于复位态怎么发命令都没反应。我看到过有人把 RESET 悬空然后发现上电后能通信但跑一会儿突然不工作其实就是复位引脚受到了噪声干扰自动复位。最好用 10kΩ 电阻上拉确保上电后自动释放复位。然后是查串口电平反转没有。ADC 的 UART 默认输出极性可能和你期望的不同如果用示波器看发送命令时的 TX 线和接收数据的 RX 线上有波形但不能正确解析多半是电平反转配反了。ADS122U04 支持正常 UART 电平但有些配置寄存器位会导致极性反转需要仔细读一下配置字的对应位。最后再考虑波特率偏差。STM32F042K6 的内部时钟精度有限如果系统里没有外部晶振而在 9600bps 下工作基本不会有问题。但如果你强行把波特率拉到 115200内部 RC 振荡器的偏差会导致误码率直线上升。我的惯例是宁可慢一些用 9600bps这样就算时钟偏差达到 1%UART 也能正确采样。4.2 读数跳变的干扰来源调试测温数据时最让人头疼的莫过于读数不断跳动。我遇到过数据在几个 LSB 之间来回跳、偶尔还蹦出几个大幅度的尖刺。排查下来有几个常被忽略的源头。第一个是供电质量。如果你用的是便宜的开关电源模块给 STM32 和 ADC 供电输出的纹波可能达到几百毫伏。ADC 内部虽然有电源抑制比但 Δ-Σ 调制器对高频纹波依然敏感。解决办法是给 ADC 电源前再加一级低噪声 LDO或者至少把供电电容加大到 22μF 左右。第二个是接地点选择。我在实验室用 USB 供电调试时电脑的地和电源的地之间有几十伏的电位差这不稀奇。如果 ADC 信号源和 MCU 不在同一地电位差分输入能抑制一部分共模干扰但无法完全解决。正确的做法是把模拟地、数字地在单点汇合然后通过星形接地连到电源地。第三个是激励电流的开启和关断。如果测量热电偶时忘了把激励电流源关闭帕尔贴效应会让热电偶因为电流流过而产生额外的电动势这个误差不是固定的它会随电流方向而变化。这类问题在数据上看起来像是噪声实际上是物理层面的测量错误。我在代码里对不同的传感器类型做了严格的寄存器分开配置就是为了杜绝这种坑。4.3 温度值转换公式与系统校准ADS122U04 返回的原始码值需要转换成电压再由传感器分度表换算成温度。这里把链路拆开看每个环节都有各自的换算系数。ADC 输出的 24 位原始码是无符号整数还是二进制补码取决于配置如果是差分输入模式正常读取为二进制补码格式。把补码值除以 2^23再乘以满量程电压就能得到电压值。例如 PGA1 时满量程是 ±2.048V电压值就是这么算出来的电压值 ADC码值 ÷ 8388608 × 2.048这个电压值在 RTD 场景下直接参与比例计算。由于参考电压驱动传感器桥路实际温度换算可以用比例方式我用的是查表加线性插值。先把 Pt1000 的电阻-温度表存在 Flash 里然后用算出的 RTD 电阻值二分查表线性插值出温度。这种方式比直接套多项式公式更快而且查表法对任意传感器的非线性都适用。热电偶那边则复杂一些因为除了要算热端电压还要做冷端补偿。我先把 NTC 测到的冷端温度换算成相应的热电势加到 ADC 测量的热电偶电压上去再用 K 型分度表反查温度。这个过程中 NTC 的精度直接影响最终结果所以我选了容差 1% 的 NTC并在关键温度点做了一次两点校准。做完整链路校准的时候建议至少用三个温度点室温、冰水混合物的 0℃、沸水的 100℃。用恒温槽当然更好但条件不具备时冰水浴和沸水已经能定位大部分系统误差。我在沸点校准那一步发现整板读数偏低了大约 0.5℃排查到最后是 NTC 的位置离热电偶端子太远空气传导造成冷端温度估计偏差。调整 NTC 位置后误差收回到 0.15℃ 以内。5. 性能评估与经验总结5.1 最终实测数据表现经过两轮 PCB 修改和多种传感器的接入测试这套 ADS122U04 STM32F042K6 的采集链路能稳定输出 15 位左右的有效位数这已经是把干扰算在内的保守估算。RTD 通道的整机精度在 -40℃~85℃ 范围内可以做到 ±0.3℃主要误差来源于参考电阻和 NTC 校准精度ADC 本身的贡献非常小。把 RTD 的激励电流从 250μA 提升到 500μA 能进一步改善信噪比但这样会让 RTD 自热效应变得更明显在 HVAC 这种气流环境下还好静止空气中的 RTD 自热可能导致 0.1℃~0.2℃ 额外偏差。你需要根据传感器的封装和介质环境权衡。热电偶通道在冷端补偿校准完成后常温段精度大约为 ±0.5℃超过 200℃ 后因为分度表整体增益平滑实际表现依然稳定。但我必须说一句热电偶的长期漂移和 NTC 年老化率是这套方案的主要短板所以如果条件允许把 NTC 换成精度更高的数字温度传感器冷端补偿的长期可靠性会好很多。5.2 我从这个项目里总结的实用经验如果从头再来一次我会在项目早期就做三件事第一把 UART 的校验机制做进协议里第二把每个传感器通道的校准系数做成可配置的 Flash 参数第三在 PCB 上预留 SPI 接口的测试点方便以后换用其他 ADC 时做对比测试。ADS122U04 的 UART 通信虽然方便但它的命令协议比较自定义化不同批次的芯片固件可能有细微差异尤其是寄存器读写时序的响应时间。建议在代码里把所有命令都封装成函数并且把超时重试逻辑加上这样即使芯片响应变慢也不会导致整个系统卡死。STM32F042K6 的 Flash 只有 32KB我最初担心存储分度表会吃紧后来发现 K 型热电偶分度表只要存稀疏点再线性插值占十几 KB 依然能放下。如果你想塞更多传感器的分度表可以改用外挂 SPI Flash 或者把表格压缩成二次拟合系数。5.3 硬件调试中不可忽略的测量工具调这种小信号采集链路示波器是必备的但更重要的是先调通信后调模拟。我建议先用逻辑分析仪抓 UART 波形确认命令和返回数据的字节顺序没问题再拿万用表量传感器端的电压是否符合预期。很多人一上来就盯着 ADC 的读数分析噪声结果半天找不到问题是通信就没通。另外如果你手头有信号发生器可以在 ADC 输入端叠加一个已知幅值的直流电压比如 100mV然后看上位机读取的温度值是否和理论值一致。这种“注入已知量”的验证方法对筛掉硬件故障和配置错误效率极高。我这一版板子调试时就是用这个方法在三分钟内定位出 PGA 增益配置错误的问题的。对于长期运行的系统日志至关重要。我在 STM32 固件里加了一个简单的诊断输出每分钟输出一次当前 ADC 配置寄存器的回读值、最近十次的原始 ADC 码、计算后的温度值以及 NTC 冷端温度值。通过查看日志很多间歇性故障都能在现场定位出来。这些诊断信息虽然不直接影响控制逻辑但在后续维护时是救命的信息。方案做完回头再看ADS122U04IPWR 和 STM32F042K6 这套组合最大的价值不在于单个指标的极致而是在功耗、体积、开发速度、精度和抗干扰能力之间找到了一个非常好的平衡点。很多项目其实只需要这个档位的性能盲目上高指标方案反而会让成本、发热和调试复杂度都失控。如果你的项目正好也有多类型温度传感器接入的需求又不想被 SPI 时序和复杂的模拟前端折磨这套组合确实值得试试。按我上面的硬件布局和固件流程走一遍应该能在很短时间内跑出稳定读数来。我后来在做第二批样机时直接把这套代码和原理图稍微改动就复用了那种顺畅感可能是这个方案最好的背书。
阅读完成 · 觉得有帮助?