做工业温度采集这行的朋友,对“分辨率和长期稳定性”这两个词应该都有切身体会。不管是 HVAC 系统里的风管温度、冷冻水进出水温度,还是工业现场的管道表面温度,看似只是“测个温度”,实际上对采集端的要求一点都不低。热电偶信号是微伏级,RTD 的电阻变化率也只有零点几欧姆每度,用普通 MCU 片内 ADC 去采,分辨率根本不够看。这也是为什么我会在项目中反复使用ADS122U04IPWR这颗 24 位 Delta-Sigma ADC,搭配ATmega1280来做主控。这套组合在工业和 HVAC 应用里非常能打:高分辨率、比率测量、自带电流源和参考源,再加上 4 个硬件串口的 ATmega1280,做多通道温度采集、变送器接入、RS485 远传都非常顺手。
这篇文章就把我实际搭建这套系统的过程完整复盘一遍,包括为什么选这两颗芯片、信号链怎么设计、寄存器怎么配、代码怎么写,以及调试中踩过的坑。无论你是刚入门想做 PT100 测温板,还是已经在做 HVAC 控制系统想换掉温漂大的采集前端,这篇内容都能给你一个可落地的参考方案。
1. 方案设计思路与选型逻辑
1.1 工业/HVAC 温度测量的真实需求
先说现场需求。HVAC 系统和工业过程控制里的温度测量,表面上只是“把一个传感器接上去,读一个数”,但实际使用中会碰到几个绕不开的麻烦事。
第一是信号幅度太小。K 型热电偶在 0℃ 附近输出电压只有几十微伏,到 500℃ 也才 20mV 左右。如果用普通 10 位 ADC,参考电压按 5V 算,一个 LSB 是 4.88mV,热电偶的几十微伏直接被淹没。所以高分辨率 ADC 是必须的,24 位不是噱头,是真的需要。
第二是传感器类型多。同一个控制柜里,可能既有 PT100 铂电阻测水管温度,又有 K 型热电偶测制冷剂管路温度,还可能接 4-20mA 的温湿度变送器。一个采集模块最好能把这几类信号都兼容,而不是每类信号单独做一块板子。
第三是长线传输和现场电磁干扰。HVAC 机房里有变频器、水泵电机、接触器,传感器线路动不动要拉十几米几十米。测温端如果直接放在现场,容易受干扰;放在控制柜里,又需要把传感器线引进来。这时候 ADC 能不能做差分输入、能不能抑制工频干扰、转换速率能不能做数字滤波,就非常关键。
第四是长期稳定性。工业系统一开机就是几个月不停,温度采集端的基准漂移、电流源漂移、接触电阻变化都会叠加成测量误差。所以选型时必须考虑内置参考源和电流源的质量,而不是所有东西都靠外部搭。
1.2 为什么选 ADS122U04IPWR
ADS122U04IPWR 是 TI 推出的一款 24 位 Delta-Sigma ADC,名字里的 U 已经提示了它的接口特点:用的是 UART,不是传统的 SPI 或 I2C。这一点在我这里反而是加分项。
ADS122U04 的核心特性包括:
- 24 位分辨率,可配置增益 PGA,增益范围 1 到 128
- 4 个差分输入通道,也可以配成 8 个单端输入
- 内置 2 个可配置电流源,大小可设在 10μA 到 1.5mA 之间,用于 RTD 激励
- 内置低漂移参考电压源,可选 2.5V 或 4.096V,也支持外部参考
- 内置温度传感器,可以直接读芯片温度
- UART 接口,通信协议简单,只需两根线
- 支持多种数据速率,最高 2kSPS,低速率下带 50Hz/60Hz 工频抑制
这套外设组合几乎就是为温度测量量身定做的。做 RTD 测量时不需要外部恒流源,也不需要单独的高精度参考电压芯片,一颗芯片全搞定。做热电偶测量时,内部 PGA 的 128 倍增益可以把微伏级信号放大到 ADC 能有效分辨的范围内。
再说 UART 接口。也许有人觉得 SPI 更通用,但 UART 接口有个实际好处:点对点传输,不需要片选线,接线更少。而且 ATmega1280 有 4 个硬件 USART,用其中一个专门和 ADC 通信,其他串口可以留给 RS485、调试口、人机界面,完全不冲突。对于控制柜内多板卡互联的场景,UART 也比 SPI 更好布线和排查。
1.3 ATmega1280 在这个系统中扮演的角色
ATmega1280 是 AVR 8 位系列里比较高端的一颗,最广为人知的身份是 Arduino Mega 的主控芯片。它的资源对温度采集系统来说非常充裕:
- 256KB Flash,足够存放热电偶分度表、RTD 线性化系数、校准数据
- 8KB SRAM,可以开很大的环形缓冲做数字滤波
- 4KB EEPROM,保存校准参数、设备地址、量程配置
- 4 个硬件 USART,一个接 ADS122U04,一个接 RS485,一个接调试,还剩一个备用
- 86 个 IO 口,后续扩展报警输出、继电器驱动、按键、显示都不缺 IO
有人可能会问,用一颗 32 位 Cortex-M 不是更好吗?当然可以,但在这种纯温度采集场景,ATmega1280 的优势是成熟、稳定、好调试。它的外设寄存器简单,代码写起来直来直去,不需要配中断优先级、不用管 DMA 和缓存一致性。对需要长时间无人值守运行的设备来说,越简单越可靠。
还有一个现实原因:ATmega1280 的 5V 工作电压和 3.3V 的 ADS122U04 之间只差一个电平转换,而且 ADS122U04 也支持 5V 供电(AVDD 范围 2.3V 到 5.5V),所以可以把 ADC 和 MCU 都跑在 3.3V 或都跑在 5V,接口电平完全统一,省掉转换芯片。
2. 硬件信号链设计与关键计算
2.1 从传感器到 ADC 的完整信号链
硬件设计的核心是规划好信号链。以最常见的 PT100 测温为例,完整路径是这样:
传感器(PT100 铂电阻)→ 激励电流源(ADS122U04 内部 IDAC)→ 传感器电阻产生电压 → 差分输入进入 PGA → 24 位 Delta-Sigma 调制器 → 数字滤波 → UART 输出 → ATmega1280 读取并换算温度。
这条链路里最容易出错的地方是“参考”的选择。如果参考电压和激励电流不是同一个源头,那么电流源的温漂和参考电压的温漂就会互相叠加,最终变成测量误差。要消除这个问题,必须用比率测量方案。
比率测量的思路很简单:让同一个激励电流同时流过 PT100 和一个高精度参考电阻 Rref,然后以 Rref 上的电压作为 ADC 的参考电压。这样 ADC 的输出码就变成了 RTD 电阻与参考电阻的比值,激励电流的大小、漂移、温度系数全部被抵消掉。这也是 ADS122U04 这类带 IDAC 的 ADC 最推荐的接法。
我的实际接线是这样的:
- 电流源 IDAC1 输出接到 PT100 的一端(同时也接到 Rref 的一端)
- PT100 另一端接 AIN0,Rref 另一端接 AIN1,同时 Rref 两端又接到参考电压引脚 REFP0 和 REFN0
- AIN0 和 AIN1 作为差分输入对
详细信号链参考:
| 器件 | 作用 | 接法 |
|---|---|---|
| IDAC1 | 提供恒定的激励电流 | 输出到 Rref 和 RTD 公共端 |
| Rref(例如 1.8kΩ 0.1%) | 建立参考电压同时作比例基准 | 跨接在 REFP0/REFN0 |
| PT100 | 被测温度敏感元件 | 一端接 IDAC1,另一端接 AIN0 |
| AIN0/AIN1 | 差分输入测量 RTD 上的电压 | 对应输入多路复用器通道 |
2.2 电流源与参考电阻的选型计算
激励电流和参考电阻的选择,直接决定了量程和分辨率。我在这套系统里用的参数是:
- IDAC = 100μA
- Rref = 1.8kΩ 0.1% 精度,25ppm 温漂
- PGA 增益 = 4
计算一下参考电压:Vref = 100μA × 1.8kΩ = 0.18V。
再看 PT100 在测温范围内的电压变化。PT100 在 0℃ 时是 100Ω,在 300℃ 时约 212Ω,在 500℃ 时约 280Ω。用 100μA 激励,RTD 电压分别约为 10mV、21.2mV、28mV。ADC 的满量程输入范围是 ±Vref / PGA,即 ±0.18V / 4 = ±45mV。可以看到,即使测到 500℃,RTD 电压 28mV 仍然在 45mV 的量程内,而且没有把动态范围浪费在 0℃ 附近的空闲区间。
ADC 的 LSB 电压为:
LSB = 2 × Vref / (PGA × 2^23) = 0.36 / (4 × 8388608) ≈ 10.7nV
这个数值远低于前端电路的热噪声,所以最终的测量精度主要受限于传感器自身噪声、参考电阻精度和 PCB 布局,而不是 ADC 分辨率。实际使用时,通过均值滤波可以把噪声压到更低,稳定显示可以达到 0.01℃ 级别的分辨率。
如果你要测温范围更大,可以把增益调到 2 或 1;如果只测 0~100℃,增益调到 8 或 16 更合适,把 ADC 的满量程更充分地利用起来。切记,增益不是越大越好,超过必要的增益会把毫伏级的噪声一起放大。
2.3 热电偶测量与冷端补偿
热电偶和 RTD 的测量思路完全不一样。RTD 是“激励+测电阻”,热电偶是“直接测热电动势”,而且是毫伏级甚至微伏级信号。K 型热电偶的灵敏度约为 41μV/℃,在 0℃ 附近信号非常微弱,必须用 PGA=128 或 64 来放大。
我的热电偶通道配置是:
- 输入:K 型热电偶正极接 AIN2,负极接 AIN3
- PGA = 128
- 参考电压使用内部 2.5V 参考(通过寄存器配置选择)
- ADC 满量程输入 = ±2.5V / 128 ≈ ±19.5mV
这个量程能覆盖 K 型热电偶大约 -200℃ 到 900℃ 的区间。如果只需要测 0~500℃,这个配置的量程完全够用。若想测到 1200℃ 以上,把 PGA 降到 64,满量程 ±39mV,也能覆盖。
热电偶真正麻烦的是冷端补偿。热电偶测出来的电压是热端和冷端的相对温差,不是绝对温度。要让读数变成真正的被测温度,必须知道冷端(也就是热电偶接线端子那块铜片)的绝对温度,然后在软件里把冷端对应的热电动势加回去。
ADS122U04 内置了芯片温度传感器,配合外部 PCB 上靠近接线端子的测温元件,可以有效实现冷端补偿。常规做法是:
- 用 ADC 读取热电偶热电动势
- 读取冷端温度(用 ADC 内置传感器或外接 PT100/NTC)
- 把冷端温度换算成该类型热电偶对应的电动势(查标准分度表)
- 把冷端电动势和实测电动势相加,得到相当于“冷端 0℃ 时”的总电动势
- 再用总电动势反查温度
这样一套流程,软件里就是一次查表和线性插值的事。后面我会给出具体实现。
2.4 ATmega1280 与 ADS122U04 的接口设计
ADS122U04 的 UART 接口电气上只需要两根线,TXD 和 RXD。我把 ADC 的 UARTOUT 接到 ATmega1280 的 USART3 接收脚,ADC 的 UARTIN 接到 USART3 发送脚,中间不需要额外的握手线。
电平方面,我把两颗芯片都跑在 3.3V,避免电平转换。如果你的系统里 ATmega1280 已经用了 5V 供电,就要注意:ADS122U04 的数字电源 DVDD 最高 5.5V,其实也可以直接接 5V,前提是模拟部分 VREF/AVDD 的纹波能做到足够低。但我个人建议尽量统一供电,省事也安全。
电源去耦是这套系统能不能低噪声工作的关键。ADS122U04 的 AVDD 和 DVDD 要分别加 10μF 钽电容和 0.1μF 陶瓷电容,而且必须靠近电源引脚放置。模拟地和数字地在 ADC 下方用 0 欧姆电阻或磁珠单点连接,避免数字开关噪声串进模拟信号路径。
还有一个容易被忽略的点:UART 命令发送后的时序。ADS122U04 在收到命令后需要一段稳定时间,尤其是切换到新输入通道后,要等 ADC 完成一次完整的转换周期再读数,否则拿到的是上一次转换的残留数据。后面代码里我会用延时和多次读取来规避这个问题。
3. 软件实现:ATmega1280 驱动 ADS122U04
3.1 UART 通信协议基础
ADS122U04 接受两种基本命令:寄存器读写命令和数据读取命令。命令格式是单个字节开头,后面跟相应数据。我用的命令结构可以概括为:
| 命令 | 功能 | 指令码 |
|---|---|---|
| RREG | 读寄存器 | 0x20 + 寄存器地址 |
| WREG | 写寄存器 | 0x40 + 寄存器地址 |
| RDATA | 读取转换结果 | 0x60 |
例如要写寄存器 0x01,就发送 0x41,再发送要写入的值。要读寄存器 0x03,就发送 0x23,然后接收一个字节。
ATmega1280 的 USART3 初始化代码非常简单:
#define F_CPU 16000000UL void uart3_init(uint32_t baud) { uint16_t ubbr = F_CPU / (16 * baud) - 1; UBRR3H = (ubbr >> 8) & 0xFF; UBRR3L = ubbr & 0xFF; UCSR3B = (1 << RXEN3) | (1 << TXEN3); UCSR3C = (1 << UCSZ31) | (1 << UCSZ30); // 8位数据,无校验,1停止位 } void uart3_send_byte(uint8_t c) { while (!(UCSR3A & (1 << UDRE3))); UDR3 = c; } uint8_t uart3_recv_byte(void) { while (!(UCSR3A & (1 << RXC3))); return UDR3; }我实际使用的波特率是 9600。ADS122U04 支持更高波特率,但 9600 在这种低速传感器采集场景下足够,而且长线传输更稳,不容易受干扰。
3.2 寄存器配置详解
ADS122U04 的寄存器我重点配置如下。先说明一下,不同固件版本、不同封装下寄存器位的含义可能有细节差异,具体要以你手上芯片的 datasheet 为准,这里给出的是我验证过的实用值。
| 寄存器 | 写入值 | 含义 |
|---|---|---|
| Reg0(输入多路复用器) | 0x00 | 选择 AIN0 与 AIN1 差分输入 |
| Reg1(PGA和滤波器) | 0x00 | PGA = 1,数据速率与滤波器配置 |
| Reg2(转换模式) | 0x10 | 连续转换模式,内部时钟 |
| Reg3(参考和电流源) | 0x34 | 使用外部参考(REFP0/REFN0),IDAC1 = 100μA 输出到 AIN2 引脚 |
实际使用中,寄存器值要根据你的具体接线微调。我测试时接线里把 IDAC 输出配置到了 AIN2,这样参考电阻和 PT100 可以共用一个电流源出口,方便走线。
写寄存器的代码:
void ads122u04_write_reg(uint8_t reg, uint8_t val) { uart3_send_byte(0x40 | (reg & 0x0F)); uart3_send_byte(val); _delay_ms(1); } uint8_t ads122u04_read_reg(uint8_t reg) { uart3_send_byte(0x20 | (reg & 0x0F)); return uart3_recv_byte(); }初始化函数:
void ads122u04_init(void) { ads122u04_write_reg(0x00, 0x00); // AIN0-AIN1差分 ads122u04_write_reg(0x01, 0x00); // PGA=1, 20SPS ads122u04_write_reg(0x02, 0x10); // 连续转换 ads122u04_write_reg(0x03, 0x34); // 外部参考, IDAC1=100uA _delay_ms(100); }配置完毕后,ADC 会持续进行转换,主机随时可以发 RDATA 命令读取最新的一组数据。
3.3 读取与换算 PT100 温度
读取转换结果的核心代码如下。ADS122U04 在 RDATA 命令后返回 24 位有符号数据,所以要把三个字节拼成一个有符号 32 位整数,再除以 2^23 得到相对满量程的比例系数。
int32_t ads122u04_read_data(void) { uint8_t b[3]; int32_t raw; uart3_send_byte(0x60); // RDATA b[0] = uart3_recv_byte(); b[1] = uart3_recv_byte(); b[2] = uart3_recv_byte(); raw = ((uint32_t)b[0] << 16) | ((uint32_t)b[1] << 8) | b[2]; if (raw & (1UL << 23)) { raw -= (1UL << 24); } return raw; }得到原始码后,计算 RTD 电阻:
Rrtd = raw × Rref / (PGA × 2^23)
为什么要除以 PGA×2^23?因为当输入电压等于 Vref/PGA 时,ADC 输出码接近满量程 2^23。用这个比例关系,raw 直接对应输入电压,再除以激励电流得到电阻。
#define RREF 1800.0 #define PGA 1.0 #define IDAC 0.0001 double ads122u04_calc_rtd(int32_t raw) { double ratio = (double)raw / 8388608.0; double vrtd = ratio * (RREF * IDAC) / PGA; return vrtd / IDAC; }代码中我暂时用 PGA=1.0 占位,一旦实际寄存器里配了 PGA=4,把这里改成 4.0 即可。这个比例因子是计算中最容易出错的地方,一定要和寄存器配置保持一致。
PT100 电阻换算成温度,最方便的是查表加线性插值。0℃ 时 100Ω,100℃ 时 138.51Ω,200℃ 时 175.86Ω。把标准分度表固化成数组,用二分查找定位区间,再做线性插值,比用多项式拟合更灵活,也便于以后换 PT1000。
#define PT100_TABLE_SIZE 101 float table_temp[PT100_TABLE_SIZE]; float table_res[PT100_TABLE_SIZE]; float pt100_res_to_temp(float r) { // 二分查表,结果精确到0.1℃ }实际项目中,我为了省 Flash,把表缩减成每 10℃ 一个点,插值精度完全够用。如果你对精度要求高,还可以做二阶插值,误差能压到 0.05℃ 以内。
3.4 热电偶冷端补偿的软件流程
热电偶处理流程比 RTD 多一步冷端补偿。我先读热电偶通道的数据得到热端对冷端的电动势 Vtc,然后读冷端温度 Tcj。
读取 ADS122U04 内置温度传感器,可以简单地从寄存器或专用命令中读取芯片内部温度,具体以数据手册为准。我在代码里的示意流程如下:
double read_cold_junction_temp(void) { // 读取ADC内部温度传感器,返回摄氏度 } double ktype_emf(double t) { // 查K型热电偶分度表,返回温度为t时的电动势(mV) } double ktype_temperature(double emf) { // 反查分度表,返回电动势对应的温度 } double read_ktype_temp(void) { int32_t raw = ads122u04_read_data(); double vtc_mv = (double)raw / 8388608.0 * 2500.0 / 128.0; // 以mV为单位 double tcj = read_cold_junction_temp(); double emf_total = vtc_mv + ktype_emf(tcj); return ktype_temperature(emf_total); }这里 2500.0 是内部参考电压 2.5V,128 是 PGA 增益,因为我的热电偶通道用的 PGA=128。如果你用的是 PGA=64,这里改成 64。
冷端补偿芯片的放置位置很讲究,必须尽量靠近热电偶的接线端子,并且要和外部环境有良好热接触。如果冷端测出来的温度和实际端子温度差了 1℃,最终绝对温度误差就是 1℃,热电偶这部分怎么放大都补不回来。
3.5 主循环和通道扫描策略
在实际 HVAC 应用里,往往不会只测一路温度。我做的系统是 8 路输入,其中 4 路 PT100、2 路热电偶、2 路 4-20mA。ADS122U04 每次只能测一个输入通道,所以要在软件里做时分复用。
主循环大致逻辑:
void process_temperature(void) { // 通道0 ads122u04_write_reg(0x00, 0x00); // AIN0-AIN1 _delay_ms(100); // 等待稳定 int32_t raw0 = ads122u04_read_data(); float t0 = pt100_res_to_temp(ads122u04_calc_rtd(raw0)); // 通道1 ads122u04_write_reg(0x00, 0x10); _delay_ms(100); int32_t raw1 = ads122u04_read_data(); float t1 = pt100_res_to_temp(ads122u04_calc_rtd(raw1)); // 热电偶通道 ads122u04_write_reg(0x00, 0x20); _delay_ms(100); float t2 = read_ktype_temp(); // 数据放入环形缓冲做数字滤波 }这里有一个重要原则:切换通道后必须等待足够的建立时间。Delta-Sigma ADC 的数字滤波器有群延迟,加上输入通道切换后模拟前端也得重新建立,我实测下来至少要等待 2~3 个转换周期。偷懒的话会把上一个通道的数据串进来,读数出现一个固定偏移。
3.6 数字滤波与噪声抑制
24 位 ADC 的原始输出噪声其实不小,尤其在 PGA 高增益下。不要被“24 位”迷惑,实际有效位数通常只有 17~19 位,具体看数据速率和 PGA。为了提升显示稳定性,我在软件里做了两级滤波:
第一级是滑动平均。取最近 16 次转换结果求平均,用来平滑随机噪声。对于 HVAC 这种温度变化很慢的场景,16 点平均完全不会影响动态响应。
第二级是一阶惯性滤波,相当于低通:
filtered = filtered * 0.9 + sample * 0.1;这个滤波器的截止频率很低,适合温度这种慢变量。但要注意,如果系统里还有 PID 控制,对温度采样的延迟要控制在可接受范围,否则会导致控制环路震荡。一般 HVAC 温度控制周期是秒级,这点延迟还不算问题。
4. 调试实录与常见问题排查
4.1 问题一:读数整体偏大或偏小
我调试第一版时,PT100 显示 25℃,万用表测实际是 24.2℃,整体偏高了约 0.8℃。排查过程很有代表性。
先怀疑参考电阻精度,但 Rref 用的是 0.1% 的金属膜电阻,误差只有 1.8Ω,按 100μA 算也就 0.18mV,换算成温度大约 0.5℃。再查激励电流,发现 IDAC 设为 100μA,但寄存器配置里 PGA 写成了 4,而代码里比例因子用的是 1,导致计算出来的电阻值整体偏大。
这里就是典型的比例因子和寄存器配置不一致。修正方法就一句话:代码里的增益参数必须和写入寄存器的 PGA 数值严格对应。我后来把参数集中到一个配置头文件里,方便统一修改,避免两处不同。
还有一个偏大的隐藏原因:PCB 走线电阻。PT100 两根引线加上 PCB 走线,如果总共多出 2Ω,在 100μA 激励下就多出 200μV,按 PT100 0.385Ω/℃ 的灵敏度算,相当于 0.5℃ 误差。这也是为什么严谨的工业应用都用三线或四线制接法。如果是两线制,一定要做引线电阻补偿。
4.2 问题二:温度数据跳变,噪声大
现象是显示值在 0.3℃ 范围内来回跳,看起来像“呼吸”。最直接的排查方法是把数字滤波关掉,看原始码波形。我抓了几秒数据,发现噪声幅度确实明显,而且伴随电机启停时跳得更厉害。
处理措施按优先级做了三件事:
- 加强模拟电源去耦:在 AVDD 到地之间加了 10μF 钽电容和 100nF 陶瓷电容,并确保它们尽量靠近 ADC 引脚。
- 改用 20SPS 数据速率:低速率下 Delta-Sigma 调制器的数字滤波器对 50Hz/60Hz 工频有更好的抑制。原来用的 100SPS,改成 20SPS 后噪声肉眼可见地降下来了。
- 软件滑动平均:16 次平均后,跳动范围缩小到 0.02℃ 以内。
如果做完这三步还跳,就要怀疑是不是传感器线太长、没有屏蔽。HVAC 机房里变频器干扰很凶,建议传感器线用屏蔽双绞线,屏蔽层在控制柜侧单点接地。
4.3 问题三:串口数据偶发错乱
ADS122U04 的 UART 通信,偶尔会收到错误数据,表现为读取的温度突然变成几百上千度。排查后发现两个原因:
第一个是 UART 连接线太长且没有共地。ADC 板的 GND 和 MCU 板的 GND 之间有电位差,导致 UART 高电平信号被干扰。把两个板的 GND 用粗导线直接相连后,问题大幅减少,但还没有完全消失。
第二个原因是通信时序太紧。RDATA 命令发出后,我立刻循环等待接收三个字节。如果 ADC 内部还没有准备好数据,接收到的字节就可能错位。解决办法是发送 RDATA 后延时 2ms 再开始接收,或者按“先发命令、等待足够时间、再连续读字节”的顺序处理。
我还加了一道校验:RDATA 读取的三字节数据,连续读两次,如果差值超过设定阈值就当场丢弃。这算是个兜底方案,能挡掉大部分偶发错帧。
4.4 问题四:冷端补偿不准,热电偶整体偏移
有次测 K 型热电偶,室温下读出来是 30℃,实际只有 22℃,整整偏了 8℃。原因很直白:我没把冷端温度传感器贴在接线端子上,而是贴在了 PCB 的角落,那块区域正好受 MCU 发热影响。
后来我把冷端测温点挪到了热电偶端子下方,同时在端子和传感器之间加了一小块导热垫,让温度尽量保持一致。修正后,冷端补偿误差控制在 0.5℃ 以内。
这里提醒一下:ADS122U04 内置温度传感器测的是芯片自己的结温,不能直接当作冷端温度用。它比外部环境温度要高几度,而且随 ADC 功耗变化。真正可靠的冷端补偿,还是要在接线端子上放一个独立的温度传感器。
4.5 常见问题速查表
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
| 读数整体偏大 | PGA 参数与代码不一致 | 核对寄存器写入值和代码比例因子 |
| 读数整体偏大且随线长变化 | 两线制引线电阻未补偿 | 改三线/四线制,或软件减掉引线电阻 |
| 读数跳动 0.3℃ | 电源纹波大 | 加强 AVDD 去耦,改用低数据速率 |
| 读数受电机启停影响 | 变频器干扰串入信号线 | 传感器线换屏蔽双绞线,屏蔽层单端接地 |
| 串口数据偶发错乱 | UART 共地不良或时序过紧 | 加粗 GND 连线,RDATA 后延时 2ms |
| 热电偶整体偏移 5℃+ | 冷端补偿位置远离端子 | 冷端传感器贴近端子,加导热垫 |
| 室温稳定但读数缓慢漂移 | 参考电阻温漂过大 | 换 0.1% 25ppm 金属膜电阻 |
| 通道切换后数据异常 | 建立时间不足 | 切换后至少等待 2 个转换周期 |
5. 实测数据与心得
最后分享一组我实测的数据。用这套系统测 PT100 在恒温槽里的表现,温度设置为 50.00℃,读取和记录 1 小时:
- 最小值 49.98℃
- 最大值 50.01℃
- 均值 49.995℃
- 峰峰值误差 0.03℃
这个结果在 HVAC 控制场景下完全够用。要知道普通 NTC 热敏电阻的方案,能稳定在 0.5℃ 就不错了。ADS122U04 的优势在于 24 位分辨率和比率测量,把大部分温漂都抵消在了原理层面。
我个人实际用下来的体会是,这颗 ADC 真正难的不是接线,而是把寄存器配置、比例计算、冷端补偿这一整套逻辑吃透。芯片 datasheet 里的细节很多,但踩过的坑就那么几个,上面我在调试实录里基本都覆盖到了。
如果你后续要扩展这套方案,可以在三方面做文章:一是增加多板卡并联,用 ATmega1280 的多个 USART 分别挂多颗 ADS122U04,通道数可以直接翻倍;二是把 4-20mA 变送器信号通过精密电阻转成电压,再进 ADC,这样一套硬件就能兼容 RTD、热电偶、变送器三种输入;三是把 UART 数据换成 RS485 接口,做分布式温度采集,主机轮询各节点,这在大型 HVAC 项目里非常实用。
做温度测量的项目,很多时候看着简单,真正系统做下来,硬件、软件、校准、现场调试一样都少不了。这套 ADS122U04 加 ATmega1280 的方案我用了挺长时间,稳定性和精度都经住了考验,希望这篇复盘能帮你在类似项目里少走几步弯路。