前阵子帮楼宇自控项目改一套冷冻水温度采集系统,原来用的是 PT100 两线制直接进 PLC 模拟量模块,现场线缆走了七八十米,还要穿过变频柜,结果读数能飘 2°C 还多,冬天调试的时候来回跑,人都快被折腾疯了。后来把方案换成 ADS122U04IPWR 加 STM32F030R8 这套组合,问题才算彻底解决。如果你也在做 HVAC(暖通空调)或者工业设备里的温度测量,这个组合很值得抄作业:ADS122U04 是 TI 的 24 位 delta-sigma ADC,带 UART 数字接口,内置可编程增益放大器(PGA)和激励电流源;STM32F030R8 则是意法半导体性价比很高的 Cortex-M0 芯片,UART 资源充足。两者配合,可以把温度传感器信号在源头就地数字化,再通过 UART 传给主机,长线传输、抗干扰以及传感器类型适配这些老大难问题一次扫平。
这套方案适合谁?适合搞过 HVAC 控制器、变频器、楼宇自控的软件和硬件工程师,也适合做工业仪表、需要对 PT100/PT1000、热电偶、NTC 温度做高精度采集的开发者。你在意的是抗干扰、稳定性和实现成本,而不是追求花哨的算法的话,这篇文章应该能帮上忙。下面按我实际踩坑的顺序,把选型逻辑、硬件接线、固件实现和现场排查经验逐条说清楚。
1. 方案选型与整体设计:为什么是 ADS122U04 + STM32F030R8
1.1 从传统模拟量采集到本地数字化测温
先说最根本的问题:HVAC 现场为什么温度测量这么容易翻车?传统做法是 PT100 两线制,传感器通过两根线接到 PLC 模拟量输入模块。两线制有两个天然缺陷,一是导线电阻直接叠加到传感器阻值上,铜导线每 0.1Ω 的误差在 PT100 上就对应大约 0.26°C,线一长必然不准;二是长线经过变频器、接触器附近,共模干扰和差模干扰很容易耦合进毫伏级的传感器信号,模拟量模块的滤波再努力效果也有限。
解决思路其实不复杂:把 A/D 转换放到传感器旁边,让 mV 级信号只走很短一段距离,之后传输的都是数字电平。ADS122U04 就是为这种情况设计的,它本身就是 24 位的高精度 ADC,能在传感器端完成所有转换,然后用 UART 把数据发出来。MCU 选 STM32F030R8,是因为它只需要干三件事:定时读取 ADC 数据、做线性化换算、把结果通过 Modbus 或者其他协议上报,这些活儿 48MHz 的 Cortex-M0 绰绰有余,成本还压得很低。
这个架构的好处是:传感器信号链的精度主要由 ADC 的参考电压、PGA 和采样的传感器决定,和线缆长度基本无关。现场那七八十米的线,传输的是 3.3V 电平的 UART 信号,干扰能力和正确率远不是模拟信号能比的。如果你在 HVAC 项目里被长线温飘搞到崩溃,先别急着换更高级的传感器,把信号数字化才是治本。
1.2 UART 接口 ADC 的优势与选型对比
ADS122U04 在 TI 的 ADC 家族里属于比较特别的一个,因为它的数字接口不是常见的 SPI 或者 I2C,而是 UART。当时我手头其实还有其他芯片可选,简单对比一下你就会明白为什么最后选它。
| 芯片 | 接口 | 精度 | 内置激励电流源 | 适配传感器 | 长线场景表现 |
|---|---|---|---|---|---|
| ADS1115 | I2C | 16 位 | 无 | NTC、电压型传感器 | 差,I2C 对线电容敏感,距离受限 |
| ADS1220 | SPI | 24 位 | 有 | PT100、热电偶、NTC | 中,SPI 适合板内,远距离需要额外转接 |
| MAX31865 | SPI | 15 位+ | 有 | 仅 PT100/PT1000 | 中,专用性强但通吃性差 |
| ADS122U04 | UART | 24 位 | 有 | PT100/PT1000、热电偶、NTC | 好,UART 天然适合点对点传输和 485 组网 |
ADS115 便宜是便宜,但 16 位分辨率做热电偶这种微伏级信号很吃力,I2C 在板外走线又有电平、速度、抗干扰多重限制,现场用起来麻烦。ADS1220 性能和 ADS122U04 相当,但它走 SPI,MCU 得时刻管着时钟和片选,从设备一多还要飞线,隔离也好做但成本不低。MAX31865 是 RTD 专用芯片,测 PT100 很省心,可一旦需要混接热电偶,它就没戏了。ADS122U04 的方案最直接:CLK、MOSI、MISO 那套时序全部交给 UART 硬件,MCU 发一个字节收一个字节,不用自己拉时序,后面想加 RS485 收发器也就是一颗芯片的事。
再说 STM32F030R8。这颗 MCU 是 64 脚封装,64KB Flash、8KB SRAM,主频 48MHz,有几个 UART,价格在 MCU 里属于很平民的档位。它在采集链路里不抢戏,但也不会拖后腿:跑一个 8 通道、20SPS 的轮询采集任务,CPU 占用可能都不到 10%,剩下的资源还能做 PID 控制、通信协议栈。CubeMX 生成初始化代码也很成熟,对工程师来说上手几乎没有门槛。
2. 硬件搭建:接线、供电与不同传感器的接入细节
2.1 ADS122U04 与 STM32F030R8 的最小接线
硬件接线是整个方案里最值得上心的地方。ADS122U04 的供电是模拟电源 AVDD 和数字电源 DVDD,实际工程中我把两个引脚都接到同一路 3.3V,但电源质量必须把控好。强烈建议不要直接拿开关电源的 3.3V 给 AVDD 供电,开关噪声对高精度 ADC 是灾难级的。我在板子上先用一个 LDO 单独供 AVDD,DVDD 则通过磁珠和 π 型滤波后接入,效果比共用一路电源好很多。模拟地和数字地在 ADC 芯片下方的焊盘附近单点汇合,再引回电源地,能明显减少数字开关噪声对模拟部分的干扰。
信号线连接很直接:MCU 的 TX 接 ADS122U04 的 DIN,MCU 的 RX 接它的 DOUT,DRDY 接一个普通 GPIO 并配置成下降沿中断。CS 是使能引脚,我用一个 GPIO 控制而不是直接接地,这样调试时方便把 ADC 动态复位。ADS122U04 数字接口的电平以 DVDD 为准,所以只要 DVDD 和 MCU 一样是 3.3V,就可以直接互联,不用加电平转换。如果板子上 MCU 是 5V 系统,那必须在中间加电平转换或者加电阻分压,别硬接。
参考电压这块,ADS122U04 内部有 2.048V 参考源,温漂系数控制得不错,精度要求不高时可以直接用。但如果走 PT100,我建议用外部精密参考电阻配合比率测量,这样比依赖内部参考更稳,因为内部参考虽然温漂小,还是有漂移,而比率测量的结果不随激励电流和参考电压的绝对值变化,只和电阻比值相关。具体接法在后面 RTD 部分细说。
2.2 PT100/PT1000、热电偶和 NTC 在实际项目中的接法
RTD 测温是 HVAC 里最常见的需求。PT100 在 0°C 时阻值 100Ω,灵敏度大约 0.385Ω/°C,三线制接法是性价比最高的方案。我用的 ADS122U04 有一个很实用的功能,内置两个可编程激励电流源 IDAC1 和 IDAC2。简单接法是:IDAC1 输出 1mA 恒流,流经 PT100,再经过外部精密参考电阻回流到地;PT100 两端压降用一对差分输入测量,参考电阻两端的压降用另一对差分输入或者直接作为参考电压输入。最后通过两个 ADC 码值的比值乘上参考电阻阻值,就得到 PT100 的实际电阻。这个“比例测量”能抵消激励电流源的温漂,算出来的电阻精度主要取决于参考电阻本身的精度和温漂。
需要注意三线制的引线补偿思路:三根导线如果材质、长度一致,则两根感测线上的压降会同时出现在差分输入的正负端,共模部分自然被差分输入抵消,剩下的主要由一路回路上的导线压降产生的微小误差,可以通过软件再校准。四线制效果更好,但 HVAC 现场一般三线制足够,二线制只适合很短距离和很低精度需求。PT1000 同理,只是阻值大、自热更小,激励电流可以选 500µA,长线压降的影响也更轻。
热电偶的接法更简单,K 型热电偶直接接在 ADC 的两个差分输入上,PGA 增益开到 128 倍,测量灵敏度大约每摄氏度对应 41µV 的电压变化。关键点在冷端补偿,热电偶测量的是热端和冷端的温差,所以必须知道接线端子处的温度。ADS122U04 内部有温度传感器,可以把 MUX 切换到内部传感器通道去读取结温;如果板子离热电偶端子较远,我建议在端子旁边放一个高精度 NTC 或 LM20 那种温度传感器,用 MCU 的 ADC 读端子处温度,软件上叠加补偿值。这个细节看着小,实际影响很大,冷端差个 1°C,最终测出来的温度就差 1°C。
NTC 热敏电阻的接法有两种,一个是用 ADC 内置 IDAC 恒流源激励 NTC,然后测两端电压,好处是线性度好于分压;另一种是标准分压电路。HVAC 里 10k NTC 非常常见,用 100µA 甚至更小的激励电流可以有效避免自热,分压法的话要选好串联电阻值和供电电压,确保在温度量程末端不超 ADC 输入范围。
3. 固件实现:寄存器配置、UART 读取与温度换算
3.1 配置寄存器的思路和关键参数
固件层面,第一步是把 ADS122U04 配置成我们想要的模式。ADS122U04 的寄存器体系延续了 ADS122 系列的结构,主要有四个配置寄存器。核心操作只有几类:复位、写寄存器、读寄存器、读转换数据。写寄存器命令一般以写命令开头,后面跟着寄存器起始地址和要写入的数据字节。具体命令字节,打开芯片手册的 Command Table 对照即可,不同版本芯片的命令基本一致,但移植到新批次时我仍然会核对一遍。
四个寄存器要设置的关键项包括:输入多路开关,即选择哪一路 AIN 作为正负输入,是单端还是差分;PGA 增益,从 1 到 128 倍可选,决定了输入信号量程和分辨率;数据速率和数字滤波器,HVAC 环境强烈建议选 20SPS,这个速率下内置滤波器对 50/60Hz 工频干扰有很强的抑制能力;激励电流源设置,包括电流大小和流向哪个引脚。举个例子,配置 PT100 三线制测量,我会把 MUX 选为差分输入,PGA 设成 8 或者 16,数据速率 20SPS,IDAC 激励电流 1mA;而测量 K 型热电偶时,PGA 设成 128,数据速率还是 20SPS,IDAC 就不需要了。配置完成后,发送启动转换命令,之后只需要等待 DRDY 信号。
还有一个使用习惯值得记住:ADS122U04 上电后我会主动发一次复位命令,再写入全部寄存器配置。很多“读不到数据”的问题,根源就是上电时序不对、寄存器没写进去,多一次复位相当于给通信链路兜了个底。程序初始化时把配置寄存器写三遍,第一遍可能被芯片上电时序吃掉了,第二遍通常能成功,写三遍又花不了多少时间,却能省去大量排查精力。
3.2 STM32 端代码框架:从 UART 初始化到读数据
STM32F030R8 用的 USART1,直接由 HAL 库初始化,代码非常简单。波特率选 115200,在与噪声环境做隔离后的长线上效果依然可靠。ADS122U04 的 UART 支持多种波特率,实际项目看需求定,如果线特别长或者现场环境特别差,降到 9600 更稳。
static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart1); }读写 ADS122U04 的底层函数也很直接,发命令、收数据。ADS122 系列的读数据命令是 0x1F,发完这个命令之后,芯片会返回三个字节的转换结果,这三个字节就是 24 位补码格式的 ADC 值。
#define ADS_CMD_READ_DATA 0x1F #define ADS_CMD_RESET 0x06 static int32_t ads122u04_read_data(void) { uint8_t cmd = ADS_CMD_READ_DATA; uint8_t buf[3] = {0}; HAL_UART_Transmit(&huart1, &cmd, 1, 50); HAL_UART_Receive(&huart1, buf, 3, 50); uint32_t code = ((uint32_t)buf[0] << 16) | ((uint32_t)buf[1] << 8) | ((uint32_t)buf[2]); if (code & 0x800000UL) { code |= 0xFF000000UL; // 24位补码符号扩展到32位 } return (int32_t)code; }一个非常重要的细节是等待 DRDY。ADS122U04 在完成一次转换后会把 DRDY 拉低,通知 MCU 数据已经准备好了。如果不管 DRDY 直接发读命令,很可能读到旧数据或者转换到一半的数据,导致码值跳变。我在工程里把 DRDY 接到 PA12 并配置成下降沿中断,中断置一个标志位,主循环里检查到这个标志后才去读取。如果长时间等不到 DRDY,则需要考虑是不是没有发启动转换命令,或者芯片进入休眠状态。
3.3 从 ADC 码值算电阻,再算温度
拿到 24 位 ADC 码值后,硬件工程师最容易在这里翻车,因为直接把码值往电压公式里面套,算出来的温度和实际温度对不上。ADC 的码值对应的是输入电压相对于参考电压的比例,而不是绝对电压。对于双极性输入,码值范围是 -2^23 到 2^23-1,满量程对应 ±Vref / PGA。所以实际输入电压公式为:
电压 = (ADC码值 / 2^23) × (参考电压 / PGA)
如果用内部 2.048V 参考、PGA 倍数为 16,屏敝码值是满量程的 80%,那输入电压就是 (0.8 × 2.048) / 16 = 0.1024V,换算到传感器电阻还需要知道激励电流是多少。
不过 RTD 比例测量更推荐用下面的算法:同时读 RTD 通道码值和参考电阻通道码值,直接用比值乘参考电阻阻值得到 RTD 电阻,完全绕开参考电压和 PGA 绝对值误差。
float rtd_resistance(int32_t code_rtd, int32_t code_ref, float ref_resistor) { float ratio = (float)code_rtd / (float)code_ref; return ratio * ref_resistor; }得到 RTD 电阻后,查表是最稳的做法。PT100 的 Callendar-Van Dusen 方程很成熟,HVAC 常用范围在 0°C 到 100°C,直接用线性近似也能做到 0.1°C 级别,公式是温度 = (电阻 - 100) / 0.385。但低于 0°C 时线性近似误差会变大,建议把完整的查表数组编译进去,一劳永逸。热电偶的换算更麻烦,先把 ADC 码值换算成电压,再借助 NIST 多项式完成电压到温度的换算,最后叠加冷端温度。
多通道轮询也不复杂。ADS122U04 硬件上只有一个 ADC,通道切换靠 MUX 完成。我的调度逻辑是:先切换 MUX 到目标通道,写配置寄存器,然后等待 DRDY 下降沿,读取数据,再切下一个通道。如果配 20SPS,每个通道要等 50ms,8 个通道一轮就是 400ms,HVAC 的温度控制回路响应速度完全够用。唯一要注意的是切换通道后,要丢弃第一次转换结果,因为上一个通道的信号还残留在滤波器里,这个 ack 大多数新手会忘,然后会看到某一个通道的数据带上了一个通道的影子。
4. 常见问题与排查技巧实录
4.1 通信和读取异常:读不到数据、码值固定、DRDY 无响应
我在现场和实验室里碰到的最典型异常,无非是以下几种,这里把现象和排查方向一起列出,按优先级排序。
| 现象 | 可能原因 | 排查/解决 |
|---|---|---|
| 读到的码值固定为 0x7FFFFF 或 0x800000 | 传感器开路、MUX 配置错、增益太低 | 先检查传感器接线,再用万用表量输入电压 |
| UART 发命令后没有返回数据 | 波特率不匹配、CS/使能引脚没拉对、复位没执行 | 用示波器看 DATA 线上有无波形,检查波特率寄存器 |
| 码值随机跳变,偶尔出现 0xFFFFFF | 电源噪声、地电位不等、UART 帧错误 | 示波器看 AVDD 纹波,检查模拟地和数字地连接 |
| 某个通道的数据覆盖了上一个通道 | 切换通道后没有丢弃第一次转换结果 | 切换后读一次数据并丢弃,再正常采集 |
| 温度偏高且波动 | 激励电流偏大导致电阻自热 | 降低 IDAC 电流,比如 PT100 从 1mA 降到 500µA 或 250µA |
其中,DART 无响应的坑经常出在波特率上。ADS122U04 的 UART 不是所有波特率都默认支持,上电时的默认波特率、校验位和停止位可能和你配置不一样。我的习惯是上电先发复位命令 0x06,然后写配置寄存器,再发启动转换。如果示波器看到 TX 有波形但 RX 完全没反应,先怀疑是不是芯片的 UART 配置需要额外的同步字节,对照手册里的 UART 帧格式检查一下起始位和校验位设置。
4.2 精度与干扰:长线、参考电压和电源噪声如何逐一干掉
现场测温精度飘,十有八九不是 ADC 芯片本身的问题,而是外围参考、电源和接线挖的坑。一次在项目上遇到温度读数随压缩机启停一起抖,查到最后是 ADC 和变频器共用开关电源,开关噪声直接灌进了参考电压引脚。解决办法是给 ADC 的模拟电源换独立 LDO,并在参考电压引脚旁边加足够容量的去耦电容,抖动的现象立刻消失。所以我强烈建议从一开始就把电源和参考当作系统设计的一部分去考虑,而不是等出了问题再补。
参考电压的选择也有讲究。用内部 2.048V 参考最省事,但它的温漂和长期稳定性虽然指标不错,在冷冻水这种全年温差大的环境里,还是会产生零点几个摄氏度的缓慢飘移。外部参考电阻加比率测量是更好的选择,选 0.1% 精度、25ppm/°C 温漂的金属膜电阻,带来的稳定性提升非常明显。比例测量还能抵消激励电流源的漂移,这正是现场精度稳定的秘密。
长线干扰的物理层防护也不能忽略。传感器信号线和 UART 线缆应该避开变频器动力线,至少保持一定间距,做不到的话就穿金属管或者使用屏蔽双绞线,屏蔽层单端接地。UART 线上如果跨越较远距离,加 TVS 管和共模电感是标配,现场工业环境里这些保护元件能省掉大量通信故障。还有一点容易被忽略的是接地方式,前后设备都要确保地电位一致,地环路造成的干扰比普通噪声还难排查,最好在板子上设计一个跳线或 0Ω 电阻位,方便现场调整。
5. 工业与 HVAC 场景的参数配置参考
5.1 HVAC 常见测点的推荐配置表
HVAC 里的温度测点非常多,冷冻水供回水、风管送风温度、回风温度、室外温度、压缩机排气温度,每一个的传感器类型和量程都不同。下面这张配置表是我实际项目里用过的参数,可以直接拿来当模板。
| 测点 | 传感器 | 接线形式 | PGA 增益 | IDAC 电流 | 参考源 | 备注 |
|---|---|---|---|---|---|---|
| 冷冻水供/回水温度 | PT100 | 三线制 | 8 | 1mA | 外部参考电阻 | 比率测量,精度优先 |
| 风管送风温度 | PT1000 | 两线制 | 16 | 500µA | 内部参考 | 距离近,自热小 |
| 室外温度 | NTC 10k | 两线制 | 4 | 100µA | 内部参考 | 量程宽,注意自热 |
| 压缩机排气温度 | K 型热电偶 | 差分直连 | 128 | 不使用 | 内部参考 | 需要冷端补偿 |
冷冻水测点对精度要求最高,所以用 PT100 三线制加外部参考电阻。风管温度 PT1000 阻值大,自热比 PT100 小,两线制在短距离内误差可接受,PGA 16 增益能把量程覆盖到常见的 -20°C 到 80°C。室外温度测点最重要的是宽温度范围和长期稳定,10k NTC 用 100µA 恒流激励,自热造成的误差可以忽略。压缩机排气温度如果是热泵系统里的,K 型热电偶会很合适,PGA 开到 128 倍之后整个系统分辨率能到 0.02°C 左右,完全超出 HVAC 需求。
5.2 从 HVAC 扩展到工业测温的思路
这套方案虽然是为 HVAC 优化的,但放到工业里也一样能打。工业温度采集最常见的问题是要跨越更远的距离、更强的干扰,以及更多的通道数。ADS122U04 的 UART 接口很自然地能接到 RS485 收发器上,变成标准的 485 从机节点,主机通过 Modbus 协议轮询,一个 485 总线上挂几十个采集节点毫无压力。STM32F030R8 的 Flash 完全装得下 Modbus 从站协议栈,再加上看门狗、掉电保存、参数校准这些功能,资源也不会捉襟见肘。
在变频器密集或者有大电流设备的工业现场,我会在 MCU 和 ADC 之间加上数字隔离器,比如 ISO7741 之类的四通道数字隔离芯片,把模拟前端完全浮空。隔离之后再接 RS485,不仅能解决地环路问题,还能让整个采集模块的共模耐压能力提升一个档次。对于 4-20mA 变送器输出的传感器,比如带变送器的温度探头,也可以用 ADS122U04 采样变送器的电压输出,关键是做好前置滤波和分压,把信号调理到 ADC 允许的输入范围内。多一点调理电路,这套方案就能覆盖更多现场仪表,不用为每种传感器重新设计板子。
最后分享一个我自己的体会。这套方案最大的价值在于现场问题少:HVAC 现场最怕的就是模拟量长线被干扰,读数在控制器上飘来飘去,排查几天下不了结论。换成 UART 接口 ADC 后,传感器信号在源头就被转成数字量,剩下需要担心的事情就只有 UART 电平质量,而这是示波器一眼就能看出来的问题。如果你准备上这个方案,第一次打样时记得把 DRDY 引脚和复位引脚都引出来,调试时用示波器同时观察 DRDY 和 DOUT,能少走很多弯路。