☰
UART接口24位ADC与DSC组合在工业测温中的工程实践
2026/11/5 5:01:31 网站建设 项目流程

做工业测温这么多年,ADS122U04 与 dsPIC30F4013 这套组合是我印象比较深的一个方案。一台 24 位 UART 接口 ADC,一颗老将级 16 位 DSC,把 RTD、热电偶、NTC 这些常见的工业温度传感器信号全部吃下来,用在场站仪表、机房监控、HVAC 送风/回风温度采集这类场景里,整体链路简洁,成本可控,性能也够稳。

在真正画板子和写固件之前,先把这个项目拆透。标题里其实藏着三层信息:一是传感器信号的接入和量化,靠 ADC 完成;二是数据读取和设备控制逻辑,靠 DSC 完成;三是测温场景本身对精度、抗干扰、通信距离有明确要求,工控现场和暖通机房的情况还不一样。这篇文章就按这个思路展开,从器件选型、信号链设计到固件实现、现场排查,完整过一遍我在实际项目里的做法和踩过的坑。

1. 方案思路拆解:为什么是“UART ADC + 16 位 DSC”

1.1 这个组合到底解决了什么问题

先说结论:这个架构的最大价值,是把高精度模拟采集和强抗干扰数字通信拆开了,各干各的活。

ADS122U04 是 TI 的 24 位 Δ-Σ ADC,自带可编程增益放大器、内部基准、两路激励电流源,还集成了内部温度传感器。最特别的是它的数字接口不是 SPI 也不是 I2C,而是 UART 接口,支持多点地址模式,用一根数据线就能和主控通信。dsPIC30F4013 是 Microchip 的 16 位数字信号控制器,最高 30 MIPS,集成了 UART、SPI、I2C、ADC、PWM 等外设,特点是电机控制和测量反馈通吃,在暖通空调的风机盘管、压缩机控制板上经常见到。

把这两颗芯片放一起,相当于把“采集”和“控制”分成两个模块:ADC 靠近传感器,负责把微小电压信号变成数字量;DSC 靠近应用,负责通过串口把数据读回来,做滤波、换算、报警输出和远程通信。这样传感器的模拟信号不需要拉很长的线到主控板,只需要一根 UART 数据线穿过去,抗干扰能力自然就好很多。

1.2 UART 接口相比 SPI/I2C 的优势

很多工程师第一反应是:ADC 不都用 SPI 吗?ADS122U04 为啥要用 UART?这个疑问我刚开始也有,但真正用在工业现场之后才明白,UART 接口不是落后,是更适合这类场景。

对比项UART(ADS122U04)SPII2C
连接线1 根数据线 + 地至少 4 根(CLK、MISO、MOSI、CS)2 根(SCL、SDA)
抗干扰差分/开漏,低速时表现好高速时钟线容易辐射和吸收干扰总线电容受限,远距离难搞
隔离成本一个数字隔离器就够需要隔离 CLK 和所有数据线隔离器数量少但时序复杂
多从机地址帧天然支持总线组网靠片选,占用 IO有地址,但总线上拉和速率限制多
波特率影响9600~115200 随便选,长线选低速即可时钟高低电平沿需要严格同步速率上不去,线长更受限

实际画过板子的朋友都知道,SPI 在 PCB 上走 10 厘米没问题,但要走 1 米以上的信号线到现场端子,或者加光电隔离,麻烦事就来了:时钟线高电平跳变带来的串扰、片选信号的毛刺、隔离器通道数量不够,每一个都是坑。而 UART 只需要一对线,逻辑电平要求低,隔离器选一个双通道型号或者在数据线上串个电阻,基本就解决了。

1.3 场景需求决定器件定位

再补充一点选型思路。ADS122U04 看起来只是把接口换成了 UART,但它的寄存器结构和功能设计完全是仪表级的:内部 PGA 可编程、激励电流源可以配置、基准可以选择内部或外部、数据速率可以调节。这些能力对应的正是工业现场和暖通系统的需求。

暖通自控里,大量温度点分布在风管、水管、机房、室外,传感器分散、布线长、电磁环境复杂,对成本敏感;工业过程里,温度范围宽,可能用到热电偶、PT100、PT1000 多种传感器,需要调理电路灵活可配。这套方案把传感器接口、放大、转换、通信全包在一颗 ADC 里,DSC 只需要做协议解析和逻辑处理,无论从开发效率还是后期维护角度,都比纯模拟调理方案好太多。

2. 传感器选型与信号链设计

2.1 工业/HVAC 常见的温度传感器

做这一块,首先得搞清楚现场到底要测什么。不同的温度传感器,信号类型、量程、非线性都不一样,直接影响 ADC 的配置和换算算法。

PT100 和 PT1000 是铂电阻,0°C 时阻值分别是 100Ω 和 1000Ω,灵敏度约为 0.385Ω/°C 和 3.85Ω/°C。线性度好,工业现场用得最多。PT100 适合测 -50~500°C 的过程管道温度,PT1000 因为自身阻值大,导线电阻影响小,在 HVAC 的送风、回风温度上更常见。

热电偶(最常用 K 型)温差电动势只有约 40µV/°C,量程宽,能测到 1200°C 以上,但必须做冷端补偿,而且信号电压极小,对 ADC 的 PGA 低噪声要求高。

NTC 热敏电阻成本最低,灵敏度高,但非线性极强,适合 -40~150°C 这种量程窄、精度要求不高的场合,比如空调室内机、冰箱、一些低成本温控器。

我把常用选型整理成一张表,方便直接参考:

传感器典型量程灵敏度线性度成本典型场景
PT100-200~600°C0.385Ω/°C好中工业过程、冷却水、油温
PT1000-50~300°C3.85Ω/°C好中HVAC 风管、水管、机房
K 型热电偶-200~1200°C40µV/°C一般低锅炉、烟气、压缩机排气
NTC 10kΩ-40~150°C高(非线性)差很低室内空调、消费类温控

2.2 ADS122U04 的关键资源怎么用

ADS122U04 的输入是多路复用的,可以配置成两个差分输入或四个单端输入,这在实际项目里很关键。比如做 HVAC 控制器,一块板子可能要同时采集一路 PT1000 风管温度和一路 NTC 回风温度,差分、单端混用,靠 MUX 配置就能省很多外部切换电路。

内部有两路可编程 IDAC 激励电流源,这是专门给 RTD 和 NTC 设计的。铂电阻测温离不开恒流源激励,外部搭恒流源电路要用好几个运放和精密电阻,面积大还容易漂。ADS122U04 内部直接提供了,电流从 50µA 到 1.5mA 左右可调,直接省掉一整套模拟电路。

内部基准电压是 2.048V,温度系数大概在十几 ppm/°C 级别,对于 0.5°C 以内精度的暖通应用足够;如果做工业过程测温,对长期稳定性要求高,就要用外部精密基准电阻做比例测量,那个方案还能顺带抵消激励电流漂移。

PGA 可编程增益是这套系统的灵魂。热电偶信号只有几十毫伏,必须放大才能把 24 位 ADC 的精度发挥出来;RTD 信号有几百毫伏,增益反而不能太大,否则输入范围不够。PGA 就是那个放大镜,但放大信号的同时也放大噪声,所以不是增益越大越好,得按传感器信号幅度算好了再选。

2.3 关键参数计算实例

以 PT100 测 0~500°C 为例,实际算一遍就清楚怎么配了。

PT100 在 0°C 时电阻是 100Ω,500°C 时按 IEC 60751 标准大约是 280.9Ω。如果用 1mA 恒流源激励,0°C 时差分电压是 100mV,500°C 时是 280.9mV。

选 PGA=8,内部基准 2.048V,那么满量程差分输入范围是 2.048V / 8 ≈ 256mV。500°C 时 280.9mV 已经超了,所以这个配置最多测到约 480°C。如果想把量程压到 600°C,PGA 要降到 4,满量程 512mV,但小信号分辨率也会跟着降。

再用 ADC 码算一下精度:24 位 ADC,正满量程码值 8388607,对应 256mV。1 个 LSB 对应约 0.0305µV。PT100 灵敏度大约 0.385Ω/°C,乘上 1mA 激励就是 0.385mV/°C。也就是说,每 1°C 的变化对应大约 12600 个码,0.1°C 就是 1260 个码,分辨能力完全够。实际系统受噪声限制,有效分辨率达不到全 24 位,但即使在 20SPS 数据率下取无噪声位数 18 位,也够把温度分辨率做到 0.01°C 级别。

热电偶这边,K 型热电偶 40µV/°C,测满量程 50mV 的话,PGA 可以选 16 甚至 32,把信号放大后再交由内部数字滤波器处理。这里要提醒一句:PGA 增益大了,输入等效噪声也会变大,100°C 范围以内的低精度测量甚至可以让 Δ-Σ ADC 直接无 PGA 采样,不要盲目追求增益。

3. 硬件电路设计与抗干扰细节

3.1 三线制 RTD 的比例测量接法

RTD 测温最经典的坑就是导线电阻。两根 1 米长的铜线,电阻可能有 0.1~0.5Ω,折算成温度误差就是 0.3~1.3°C,这在工业现场完全不能接受。两线制测温省线但误差大,四线制最准但要接四根线,三线制是精度和成本之间的平衡点。

ADS122U04 的两路 IDAC 正好够做三线制抵消。思路是让两路电流源输出相同的电流,一路流过 RTD,一路流过补偿线,测量端测到的电压里,导线压降在差分输入里相互抵消。这样即使导线长、电阻随温度变化,也不会明显影响测量结果。

具体接线原则说说清楚:RTD 的三个端子中,一根线接激励电流和测量高端,另外两根线接在 RTD 的低端。IDAC1 经过 RTD 到低端形成主采样回路,IDAC2 走另一根补偿线,流过的电流在低端汇合。ADC 差分输入端测的是 RTD 两端电压,因为两路电流相等、导线电阻近似相等,低端两根线上的压降基本一致,差分后抵消。如果现场只有两线,可以用寄存器把其中一路 IDAC 关掉,剩下的误差通过软件校准或者干脆选用 PT1000 来减小。

引脚级的具体接法,建议以 ADS122U04 datasheet 里 RTD 测量一节为准,不同增益、不同输入 MUX 配置下的推荐电路有区别。我这里给的是整个设计必须满足的约束:激励电流路径要短、测量端要差分、低端补偿电流必须存在。

3.2 输入滤波和保护电路

ADC 的前端保护是很多人容易忽略的环节。工业现场传感器线缆动辄几十米,经过电柜、桥架,容易耦合变频器、接触器、电机启停带来的尖峰干扰。如果这些干扰直接进 ADC 输入端,轻则读数跳变,重则打坏芯片。

我的习惯是在每个模拟输入引脚到地之间加一个 47nF 的电容,在输入引脚前面串一个 1kΩ 电阻,组成简单的 RC 低通滤波。这个滤波器截止频率大约 3.4kHz,可以把绝大多数高频开关噪声滤掉。别把截止频率算太高,滤波效果不够,也别太小,否则信号建立时间会拖长。

对于长线缆的浪涌防护,在端子处加 TVS 管是常规做法,但要注意 TVS 的漏电流。很多 TVS 在常温下漏电几微安,看起来不大,进到高阻抗的 ADC 前端就会被放大,造成温度偏差。我一般把 TVS 放在端子处,经过串联电阻之后再到 ADC 输入,这样漏电流被电阻限制,影响小一些。ESD 防护也是同样的思路,宁可让 TVS 先扛,也别让高压直接怼到 ADC 引脚上。

3.3 电源、地线布局和隔离经验

精密 ADC 最怕电源脏。ADS122U04 的 AVDD 和 DVDD 要求分开供电,就算芯片上已经做了内部隔离,电源走线也要当心。我在项目里的做法是:模拟电源用一颗低噪声 LDO 单独供,数字电源走另一路,两者在 PCB 上尽量分开布,中间留地铜皮隔离。如果有开关电源模块,LDO 的输入前再加一颗磁珠和电容,效果会更好。

UART 接口做隔离是这个方案里最值得一提的地方。因为数据线只有一根,隔离方案特别简单:在 ADC 的 DOUT/DRDY 和 DSC 的 UART RX/TX 之间插入一颗数字隔离器,比如 ISO7721 这种双通道的,电源分别接两端的隔离电源,地分开。这样传感器侧和控制器侧的电气完全隔离,共模干扰、地环路、电位差问题全部被挡在外面。用 SPI 的话至少要隔离三根线,成本高不说,时序余量也紧张,UART 天生就是为这种低速长线隔离准备的。

4. dsPIC30F4013 固件实现

4.1 9 位 UART 初始化和底层收发

ADS122U04 的 UART 通信使用“8 位数据 + 地址/数据位”的 9 位数据帧格式。主机发地址字节时,第 9 位是 1,表示这是地址帧;发命令或者数据字节时,第 9 位是 0。从机接收到地址帧后会做地址匹配,匹配成功后接收后续的命令数据。

dsPIC30F4013 的 UART 模块可以配置成 9 位数据模式。我初始化时的寄存器设置大概长这样:

#define FCY 30000000UL void UART1_Init(unsigned int baud) { // 9-bit data, no parity U1MODEbits.PDSEL = 0b10; U1MODEbits.STSEL = 0; U1MODEbits.BRGH = 1; U1BRG = (unsigned int)((FCY / baud / 4) - 1); U1MODEbits.UARTEN = 1; U1STAbits.UTXEN = 1; IFS0bits.U1RXIF = 0; IEC0bits.U1RXIE = 1; }

发送数据的时候,关键是地址位的处理。我把地址位放在第 9 位,写入 UART 发送寄存器时一并填好:

void uart_send_frame(unsigned char data, unsigned char is_addr) { while (U1STAbits.UTXBF); if (is_addr) U1TXREG = (unsigned int)(0x0100 | data); else U1TXREG = (unsigned int)(data & 0x00FF); }

接收中断里,同样要检查 U1RXREG 的第 9 位,判断收到的是地址帧还是数据帧。现场调试时,如果发现设备完全不响应,先检查是不是地址位没置位,这是我在第一版固件里栽过的跟头。

要注意,ADS122U04 的从机地址由 ADDR0 和 ADDR1 引脚决定,硬件上接地或接高,软件配置的地址必须和硬件一致。默认地址一般可以设成 0x00 或 0x01,具体看 datasheet 的编码表。

4.2 ADC 寄存器配置和连续转换流程

ADS122U04 上电后不会自动开始转换,必须由主机通过 UART 总线配置寄存器和发送启动命令。我用到的配置项有这几组:

// 配置寄存器示例:AIN0/AIN1 差分输入,PGA=8,内部基准,20SPS ads122u04_write_reg(0x00, 0x12); // CONFIG0:差分输入 AIN0-AIN1,PGA=8 ads122u04_write_reg(0x01, 0x00); // CONFIG1:内部基准 2.048V,正常模式 ads122u04_write_reg(0x02, 0x30); // CONFIG2:20SPS,连续转换

寄存器值我只是随手写的示意,具体位定义请对照手册确认。实际的写入函数要严格按照 9 位帧格式拼发:

void ads122u04_write_reg(unsigned char reg, unsigned char val) { uart_send_frame(ADDR_AD, 1); // 地址帧,第 9 位为 1 uart_send_frame(0x40 | (reg << 1), 0); // WREG 命令 uart_send_frame(val, 0); // 写入的数据 }

读取温度值走的是 RDATA 命令,一次拿到 4 个字节:前 3 字节是 24 位有符号转换结果,第 4 字节是状态字节,其中包含了 DRDY 位,标志数据是否更新完毕。连续转换模式下,等状态字节的 DRDY 置位后再读数据,可以避免读到新旧混合的数据。

void ads122u04_read_data(void) { uart_send_frame(ADDR_AD, 1); uart_send_frame(0x10, 0); // RDATA // 切换 UART 从发送到接收 U1STAbits.UTXEN = 0; // 等待接收中断,依次读取 4 字节 }

很多人问我为什么要用连续转换而不是单次转换。我的经验是:连续转换模式下,ADC 的 Δ-Σ 滤波器能保持稳定状态,读取的数据更加平滑;单次转换每次启动都有建立时间,数据率和功耗都要重新算,对大多数工业测温场景没有必要。

4.3 温度换算和 RTD 线性化

拿到裸的 ADC 码之后,第一步是根据差分输入范围把它还原成电压。假设 PGA=8,内部基准 2.048V,正满量程电压是 0.256V,24 位有符号码值范围是 -8388608 到 8388607,换算关系:

float adc_code_to_voltage(int32_t code) { return (float)code / 8388607.0f * 0.256f; }

算出来电压之后,除以激励电流就得到 RTD 电阻值。但如果用的是内部 IDAC,激励电流本身有温漂,这步会有一定误差。追求更高精度的话,把基准接成比例模式,让 ADC 的参考电压也由同一路激励电流产生,代码直接输出 RTD 电阻和参考电阻的比值,激励电流的温漂就被抵消掉了,这是工业仪表的标准做法。

RTD 电阻到温度的换算是整个固件里最容易出 bug 的地方。PT100 的阻温关系不是一根直线,0°C 以上接近二次曲线,0°C 以下还要加上一个三次修正项。我一般不在 MCU 上直接解高阶方程,而是维护一张 1°C 间隔的查表,用线性插值补中间值。表可以预先生成好烧到 Flash 里,查询一次只需要 O(log n) 时间,插值误差远小于 0.1°C。

float rtd_lookup_table_linear(float resistance) { // 二分查找表格区间,然后线性插值 // 代码略,避免占篇幅 }

如果强制要用公式计算,0°C 以上可以用简化式反推,但低温和高温段误差会明显变大,还是查表最稳。

4.4 数字滤波和工程状态判断

ADC 信号进到 MCU 之后,我习惯先做一轮软滤波再对外输出温度值。硬件滤波对付不了所有事,尤其是暖通现场的低频气流扰动、变频器周期性的 EMI,都需要软件再兜一道。

我常用的有三类滤波:滑动平均适合平滑缓慢变化的温度,窗口一般取 5~10 点;中值滤波能干掉偶发的尖峰干扰,适合采集变频器附近的信号;一阶 IIR 滤波则是轻量、低延迟,适合做实时控制环的输入。实际项目中我经常把中值滤波和 IIR 合用:

#define ALPHA 0.2f float temp_raw; float temp_filtered; temp_filtered = temp_filtered + ALPHA * (temp_raw - temp_filtered);

α 的取值有讲究。做风机盘管控制时,温度本身变化不快,α 取 0.1~0.2 就够了,太大会把噪声全放进控制环,太小会让控制响应迟钝,现场调试时手动摸一下感觉最准。

除了滤波,还要在固件里做好断线和超量程判断。RTD 断线时,ADC 读到的电压要么接近满量程,要么接近 0,两种情况都该报故障而不是输出一个离谱的温度值。ADS122U04 的状态字节里有输入超量程的指示位,我一般在解析数据的函数里先检查它,再检查数值是否落在传感器量程内,两层校验都通过才更新输出。

5. 现场常见问题排查与校准实录

5.1 读数跳变和通信失败排查

现场跑起来之后,最让人头疼的问题往往是通信失败和读数不稳定,而不是算法复杂。我整理了一份自己的工作笔记,按优先级排列:

先查共地。两边设备如果供电没有共地,UART 数据线上就会出现明显的电位差,轻则误码,重则烧隔离器。用了数字隔离器还好说,没用的必须把地线可靠连接。

再查波特率误差。dsPIC30F4013 的 UART 波特率由 FCY 和 BRG 寄存器决定,如果用外部晶振经过 PLL,实际系统时钟和理论值有偏差。串口分析仪测一下 hmm 帧,差的多了就要重新算 BRG。

然后查总线状态。UART 空闲时数据线应该是高电平,如果从机侧是开漏输出或者没有上拉,空闲时电平不确定,会导致接收端不断收到 0xFF 之类的假数据。我习惯在数据线上加一个 4.7kΩ 上拉到 ADC 供电电源,稳妥。

读数跳变的话,用排除法:把传感器接一个精密电阻箱,如果读数还是跳,说明问题在信号链或者软件;读数稳了,再查传感器本身。模拟输入端的小电容有没有焊好、基准去耦电容是不是离引脚太远,这些硬件细节往往就是跳变的根源。

5.2 校准方法和精度验证

ADS122U04 的增益误差和偏移误差,虽然出厂有标定,但实际电路中还有外部电阻、导线、基准电压的误差。要想达到 0.1°C 级别的精度,必须做两点校准。

我的校准流程是这样:先用精密电阻箱模拟传感器,接成和实际一样的三线制线路。校准点取 0°C 和 100°C 对应的电阻值,比如 PT100 就是 100Ω 和 138.51Ω。记录 ADC 码和实际电阻值,算出偏移和增益两个修正系数,存到 DSC 的 Flash 里。

校准完成之后,在 50°C 附近验证一下误差。如果中点误差还是超过 0.2°C,说明线性化代码有问题,而不是校准的问题,老老实实回查查表区间。实际现场校准还有个土办法:把探头插到冰水混合物里做零点,再拿一个已经送检过的标准温度计做端点,两个人把探头绑一起,稍微等稳定了,读数差异直接记录成修正值。这个方法虽然土,但对 HVAC 现场足够用。

5.3 常见问题速查表

现象可能原因解决措施
UART 完全无响应地址位未置位/地址不匹配示波器抓数据帧,查第 9 位和 ADDR 引脚配置
读到 0xFFFFFF传感器断线或者输入开路检查端子接线,确认 IDAC 是否开启
温度读数整体偏高/偏低导线电阻误差或基准电压偏差做两点校准,优先检查参考电阻精度
读数周期性跳动数据率和工频干扰混叠换 50SPS 数据率,或加数字陷波滤波
数据偶发乱码波特率误差或共地不良校正 BRG,加强共地/隔离
高增益下噪声特别大PGA 对前端噪声放大调低增益,输入加 RC 滤波,检查布局

排查的时候养成一个好习惯:把 ADC 原始码、滤波前温度、滤波后温度三个值全部通过调试串口打出来。只看最终温度的话,很难定位问题是出在模拟前端、运算还是滤波环节,把中间量全暴露出来,十次有九次能一眼找到问题在哪。

收尾经验

这个项目做下来,我个人最大的体会是:ADS122U04 和 dsPIC30F4013 的组合,并不是参数最惊艳的方案,却是工程上最“省心”的方案。UART 接口让调试和隔离变得异常简单,ADC 把复杂的模拟调理全部集成化,DSC 则是老老实实做控制和通信,分工明确,各司其职。

如果再给我一次机会重做,我会把温度换算表和校准参数在 Flash 里的存储格式提前定义好,预留现场校验的写接口。因为这个系统真正运行起来之后,环境变了、传感器老化,总归要现场重新校准,到时候发现参数结构不够灵活,改固件可比当初多写几行宏定义麻烦多了。设备稳定运行只是第一步,好维护才是这套方案能不能长久用下去的关键。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询