ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

24位ADC+UART: ADS122U04与TM4C129的高精度温度采集方案

24位ADC+UART: ADS122U04与TM4C129的高精度温度采集方案

去年做一套工业组合式空调机组的温控改造,现场要求把冷冻水供回水温度、新风温度、回风温度、表冷器盘管温度全部采回来,一共七八个点,而且传感器到控制柜的走线最短也有十几米。原来那套方案是NTC热敏电阻加运放放大,再走0-10V模拟量进PLC,结果夏天一开变频器,显示温度直接跳两三度,根本没法做PID。后来换了ADS122U04IPWR加TM4C129XKCZAD的组合,一条UART线把四路高精度温度全部收进来,再用TM4C129处理换算、滤波和Modbus上报,稳定得让我有点意外。

这篇文章把整套方案从芯片选型、传感器接入、寄存器配置、固件实现到现场校准和踩坑记录完整写出来。内容更适合正在做工业温度采集模块、HVAC楼宇自控或数据采集网关的软硬件工程师,或者准备用高精度ADC替换传统模拟链路的同学参考。

1. 从“运放+万用表”到“串口ADC”:这套组合解决的三个实际问题

1.1 工业现场多点测温的困境

工业暖通场景下的温度测量,难点从来不在“测不准”三个字,而在“一直测不准”和“多个点一起不准”。传统的模拟链路通常是传感器信号经过长线传输到控制柜,再进隔离变送器和模拟量输入模块。只要现场有大功率变频器、接触器或开关电源,这些模拟小信号就会叠加共模干扰和差模噪声。NTC和热电偶本身输出阻抗匹配不好,长线还容易产生天线效应,采集结果跟着负载电流一起波动。

但改用数字输出传感器或ADC之后,最大的变化就是把模拟信号到数字信号的转换尽量往前移,靠近传感器端。ADS122U04IPWR这种带UART接口的24位ADC刚好可以把前端放大、滤波和模数转换都做了,输出的就是数字量,抗干扰能力和传输距离都比传统模拟方案强得多。

1.2 ADS122U04IPWR 的定位:带UART的24位精密ADC

ADS122U04IPWR 是TI推出的一款24位、4通道、Δ-Σ架构ADC,和常见的SPI接口ADC最大的区别是它自带UART接口。这一点在工业现场特别实用,因为UART可以很方便地转成RS-485,长距离传输和多设备组网都很成熟,相比SPI的短距离片选方式,布线灵活性和抗干扰能力都更好。

芯片内部集成了可编程增益放大器PGA,增益从1倍到128倍可选,还带两个可编程激励电流源IDAC,可以直接驱动RTD热电阻。此外还有内部温度传感器、电压基准、系统监视器和CRC校验功能。一组24位ADC配合4通道输入选择器,用模拟多路开关的方式就能在几类温度传感器之间切换,不需要额外布置一片多路复用器。开发板级别的设计里,一片ADS122U04加几个电阻电容,就能搭出完整的多路温度采集前端。

也有朋友问我,既然TM4C129XKCZAD自带ADC,为什么还要外挂一片ADS122U04?答案很简单:普通MCU内置ADC一般只有12位精度,INL、温漂和噪声都达不到工业级温度测量的要求。HVAC要控制温差在正负0.5℃以内,12位ADC配合传感器很难稳定完成。ADS122U04的24位核心让温度分辨率能轻松做到0.001℃级别,虽然实际系统精度受传感器和校准限制,但至少硬件上限不会被ADC卡住。

1.3 TM4C129XKCZAD 管整个系统:更看重协议栈与外设

TM4C129XKCZAD 属于TI Tiva C系列,Cortex-M4F内核,主频120MHz,带浮点单元。对于温度采集这种计算量不大的任务,CPU性能完全够用。真正让我选它的是两点:一个是内置以太网MAC和PHY,可以直接做网络上报,HVAC项目里接到楼宇自控网络非常方便;另一个是多路UART外设,一路接ADS122U04,一路做调试打印,还能再留一路给RS-485走Modbus RTU,接口完全不冲突。

TM4C129XKCZAD的硬件UART带FIFO,还能触发中断,配合DMA可以做到比较高效的数据接收。在ADS122U04连续转换模式下,数据会以固定的时间间隔到达UART,用FIFO加中断驱动,MCU不用一直空转等待,可以腾出CPU时间去跑控制逻辑和通信协议。

这套组合的实际价值是:MCU只负责“管理”和“上报”,前端测量真正的高精度工作全部交给独立ADC完成,数字隔离也更容易做。整个系统的模拟部分集中在一片芯片上,PCB布局和抗干扰设计都简单很多。

2. 温度传感器接入:RTD、热电偶、热敏电阻的电路与配置

ADS122U04IPWR支持多种类型的温度传感器,不同传感器对应不同的输入MUX配置、PGA增益和激励电流源设置。这也是我在HVAC现场最喜欢它的原因:一个板子兼容四种传感器,只要改配置和接线端子就行。

2.1 三线/四线PT100的激励电流与比例测量

工业和HVAC里最常用的是PT100铂电阻,0℃对应100Ω,温度系数大约0.385Ω/℃。测量PT100最标准的方法是用恒流源激励,然后测电阻两端电压,再用比例法消除电流源的误差。

ADS122U04内置IDAC电流源,可以设置10μA到1.5mA等不同档位。对PT100,我习惯把IDAC1设置为1mA,激励电流从IDAC1引脚输出,经过PT100后回到AIN0或AIN1,同时用同一路电流在外部精密基准电阻上产生参考电压,实现比例测量。这样即使电流源有温漂,ADC的码值和参考电压同步变化,计算结果不受影响。

接线方式上,四线制效果最好:两根线给RTD供电,两根线单独测电压,线电阻完全不进入测量回路。但HVAC现场大量已经是三线制PT100,三线制的接法同样支持,关键是让两根引线的电阻分别落在激励回路和检测回路的同一臂上,通过差分测量抵消线电阻影响。ADS122U04的差分输入可以直接接AIN0和AIN1,MUX配置为AIN0-AIN1差分对即可。

PGA增益的设置要结合传感器输出电压和ADC参考电压来算。PT100在0℃时100Ω,1mA激励产生100mV电压;在100℃时约138.5Ω,产生138.5mV。如果把外部参考电压设为2.048V,PGA=16时有效输入范围大约是±2.048V/16=±128mV,0℃到100℃的差分电压刚好落在这个范围内。想留更多裕量可以用PGA=8,分辨率仍然很高。

2.2 热电偶的冷端补偿思路

K型热电偶是测温范围和性价比比较均衡的选择,工业风管温度、高温冷水机组排气温度都会用到。热电偶的输出信号很小,K型大约40μV/℃,所以必须把PGA放到64倍甚至128倍。ADS122U04在PGA=128时,配合2.048V参考电压,理论分辨率非常高,足够分辨0.01℃级别的热电偶电压变化。

热电偶本身测的是测量端和冷端之间的温差,冷端必须做补偿。ADS122U04内部集成温度传感器,可以直接读取芯片附近的结温,作为冷端参考。但更稳妥的做法是在热电偶接线端子附近贴一个PT100或高精度NTC,采集端子的实际温度,再在固件里做冷端补偿。因为ADC内部温度传感器反映的是芯片温度,和接线端子之间会有热阻误差,特别是机箱内有发热元件时,这个误差可能达到1℃以上。

我把热电偶的正极接AIN0,负极接AIN1,同时在AIN0到AIN1之间并联一个100nF滤波电容,再在每一根线上串联一个1kΩ电阻。这个RC滤波能滤掉高频干扰,不会明显影响低频温度信号。配置寄存器时,要打开输入偏置电阻功能,给热电偶提供一个对地或对AVDD的直流偏置路径,否则浮空的热电偶会把共模电压拉到不可控的范围。

2.3 热敏电阻和0-10V/4-20mA变送器输入

HVAC里还有很多NTC 10k热敏电阻,比如壁挂式温控器、风管温度传感器。NTC的阻值随温度变化是非线性的,但测量方法比RTD简单:用固定参考电阻和NTC组成分压电路,再测量分压点的电压。ADS122U04的IDAC电流源同样可以直接激励NTC,但要注意NTC在低温时阻值会很大,如果激励电流太大,电压可能超过ADC输入范围;一般用100μA或250μA比较合适。

对于4-20mA电流环变送器,温度已经被变送器转换成电流信号,ADC只需要测量电流在采样电阻上的压降。常用250Ω精密电阻,20mA时压降5V,超过ADS122U04的输入范围,所以要把采样电阻减小到100Ω,20mA时2V,再用PGA=1配合2.048V参考电压测量。这个方法在工业现场非常实用,因为很多风管温湿度传感器的信号输出都是4-20mA,ADC通道可以统一兼容,硬件上只需要在端子上并一个采样电阻。

3. UART链路与ADS122U04寄存器配置:比特率、CRC和连续转换

ADS122U04和TM4C129XKCZAD之间走的是UART,这要求两边在比特率、帧格式、校验和通信时序上严格按照手册配合。我把这一层的配置和调试过程完整拆开讲。

3.1 硬件连接:TM4C129的UART外设接法

TM4C129XKCZAD的UART模块引脚是CMOS电平,3.3V,和ADS122U04的电源域一致,可以直连。需要特别注意TX和RX是交叉连接的:MCU的TX接ADC的RX,MCU的RX接ADC的TX,两头共地。

板子上的电平和ESD保护也要处理。ADS122U04的UART引脚虽然是数字接口,但引到端子后可能受到外部静电或瞬态干扰。我在UART线靠近接口的地方各串了100Ω电阻,并加TVS管到地。如果应用要求更远的传输距离,我会在TM4C129和ADC之间加一片支持3.3V侧电平的RS-485收发器,把UART信号转成差分信号,实测在100米双绞线上仍然能稳定通信。

ADC的UART波特率支持多档,具体用多少取决于系统时钟和噪声环境。我的经验是9600bps最稳定,适合布线复杂的工业柜;但数据量不能让电路切换频率。11200bps或更高速率需要把时钟源配准,否则长期运行偶尔会出帧错误。TM4C129的UART波特率生成寄存器也要做同样的计算,确保两边误差小于2%。

3.2 寄存器配置流程,从复位到启动

ADS122U04的UART协议核心是读写寄存器和启动转换。上电后我先做一次软件复位,等10ms让内部基准和PGA稳定,然后依次写配置寄存器。

Config0寄存器负责输入MUX和PGA设置。比如测量PT100时,寄存器值包含AIN0-AIN1差分、PGA=16、PGA旁路关闭。Config1寄存器设置转换模式和输出速率,HVAC应用我选择连续转换模式,输出速率20SPS或50SPS,开启50Hz/60Hz工频抑制滤波器。Config2寄存器设置IDAC电流源大小和输出引脚,测量PT100时设为1mA并输出到AIN0。Config3寄存器选择内部温度传感器是否启用、是否需要烧毁检测。

通用的启动流程可以归纳成这几步:

  1. 上电后等待电源稳定,发送复位命令。
  2. 配置UART帧格式、比特率、使能CRC。
  3. 依次写Config0到Config3,建议每写一个寄存器后读回验证。
  4. 启动连续转换,等待数据准备好。
  5. 读取转换结果,检查CRC和溢出标志。
  6. 如果切换传感器类型,先停止转换,重新写Config寄存器,再启动。

读回验证这一步特别重要。我遇到过一次写Config2后ADC完全没有激励电流输出,后来用读回命令发现写入值和读回值不一致,查出来是I2C地址? 准确说是UART命令帧的地址位错了。所以每次写寄存器后都读一遍,能省非常多调试时间。

3.3 数据格式与CRC校验的实际处理

ADS122U04转换结果是24位二进制补码,读取后要放在一个有符号32位变量里,先判断符号位再除以8388608归一化。有的工程师直接把24位数据塞进uint32_t,结果负数全部变成很大的正数,后面算温度就全错了。

数据帧末尾有CRC校验字段,这个不能省。工业现场的UART长线上偶发一位错误很正常,如果没有CRC,偶尔会出现一个远离真实值的跳点。我固件里对每一帧都做CRC8校验,校验不过直接丢弃这一帧,不把它送进滤波队列。这样做之后,大量毛刺都在通信层就被过滤掉,不会污染后面的温度滤波和控制逻辑。

CRC计算可以用查表法,占用大概256字节Flash,非常适合TM4C129XKCZAD这种Flash充足的MCU。不要试图在中断里逐位计算CRC,那样会拖慢中断响应。把UART数据先收进DMA缓冲区,收完一整帧再统一校验,CPU占用率非常低。

4. TM4C129XKCZAD固件设计:状态机、缓冲区和温度换算

硬件链路正常工作之后,固件架构就决定了整个系统的稳定性和可维护性。我没有把ADS122U04的驱动直接写在主循环里,而是拆成三个层次:UART硬件抽象层、ADC协议层、传感器应用层。

4.1 驱动层拆成三块,避免以后改传感器时重写代码

UART硬件抽象层只做一件事:提供字节发送和整帧接收回调。这一层直接操作TM4C129XKCZAD的UART寄存器,把收到的字节放进环形缓冲区,同时做奇偶校验和帧超时判断。应用层完全不用关心UART细节。

ADS122U04协议层负责构造命令帧、解析响应帧、校验CRC、维护当前寄存器配置。对外提供类似ads122u04_read_single()和ads122u04_start_continuous()这样的接口。传感器类型变化时,只需要改协议层里的配置参数,应用层代码一行都不用动。

传感器应用层处理的是“前一个温度是什么、下一个温度是什么、要不要做平滑滤波”。这层可以放自己的平均滤波器或一阶低通滤波,也可以在这里做温度单位换算。我习惯把滤波放在寄存器码值层面,因为此时信号还是线性电压比例关系,滤波更物理;如果先把码值换算成温度再滤波,非线性传感器会引入额外误差。

4.2 原始码值到工程单位的换算

比例测量RTD时,温度换算分两步。第一步把ADC码值换算成电阻值。如果外部参考电阻Rref和RTD共用同一个IDAC激励,那么:

RTD电阻值 = Rref × (code_rtd / code_ref)

这里code_rtd是RTD通道读数,code_ref是参考电阻通道读数。内部参考电压和IDAC温漂都会被约掉,这是最稳定的比例测量方式。

第二步把电阻值换算成温度。PT100在0到100℃范围内可以用线性近似,但要做更高精度,建议用IEC 60751的多项式查表,或者用查表加线性插值。MCU有浮点单元,直接算多项式也不慢。我实测用分段线性插值表,表里每10℃一个点,插值计算出的温度误差小于0.05℃,固件Flash只占1KB左右。

热电偶的换算稍微复杂一点。先把24位码值换算成电压,然后用标准热电偶分度表做温度查找。冷端温度要先换算成对应的毫伏值,加到测量电压上,再查表得到真实温度。这整个过程里最容易出错的是冷端电压和测量电压的单位要一致,否则结果可能差几十度。

4.3 多通道扫描时序与实时性

ADS122U04是单ADC四通道输入,本质上通过输入MUX切换来测量多个传感器。每切换一次通道,内部输入滤波器和PGA都需要建立时间,如果立即读取,会混入上一个通道的残余信号。我的做法是在切换通道后丢掉前两三次转换结果,从第四次开始取数。以20SPS采样率计算,四通道一轮下来大约需要0.8秒,对HVAC这种惯性很大的温度控制场景完全够用。

实时性要求高的场景,我会把“切换通道”和“读取结果”做成两个独立状态。空闲时设置好下一通道并启动转换;收到数据中断后,把结果存入对应通道的环形缓冲区,再设置再下一通道。这样MCU不会在等待ADC转换期间死等,控制周期也不会被通道数拖累。

TM4C129XKCZAD的DMA功能值得利用。连续转换模式下,ADC每隔一段时间输出一帧数据,如果全部靠UART中断接收,CPU会被频繁打断。我配置了UART的DMA接收,每收满一帧触发一次完成中断,在中断里只做CRC校验和内存拷贝,整体CPU占用不到5%。

5. 工业HVAC场景的校准与误差预算:别让软件精度浪费硬件精度

硬件电路和固件都跑通之后,最影响最终测量精度的就是校准和误差分配。很多工程师设计时只算ADC分辨率,忽略了传感器误差和零点偏置,最后整机精度还不如一个水银温度计。

5.1 零点和满量程校准,省去复杂计算公式

ADS122U04虽然有24位精度,但输入前端和PGA难免存在失调电压,外部基准电阻也有容差。所以每台设备出厂前都要做两点校准。我用高精度电阻箱模拟PT100在0℃和100℃时的阻值,分别记录ADC码值,然后计算增益系数和偏移量,存到TM4C129XKCZAD的Flash里。

如果现场没有电阻箱,可以用高精度的100Ω和138.51Ω精密电阻代替,误差也能做到很小。

校准的流程大概是:

  1. 在0℃校准点接入精密电阻,等待读数稳定,记录码值offset。
  2. 在100℃校准点接入精密电阻,记录码值gain。
  3. 用两点式直线方程算出换算系数。
  4. 把系数写入Flash,并在下次上电时加载。

校准之后,系统零点和增益都被修正到一个很理想的状态。不过要注意校准温度和实际工作温度接近效果最好,因为PGA增益随温度的变化不会被两点校准完全消除。误差要求高的场合,可以在不同温度点做三点校准,插值使用。

5.2 冷端温度校准与传感器匹配

热电偶通道的冷端校准要单独处理。如果用ADS122U04内部温度传感器做冷端,要提前标定芯片温度和端子温度之间的偏差。我在恒温箱里设置几个温度点,读取内部温度传感器值和端子附近PT100的实测值,做成一个校正表。这样在0到70℃环境范围内,冷端补偿误差可以控制到0.3℃左右。

如果是RTD通道,传感器本身的精度也不能忽略。普通PT100 B级精度是±0.3℃@0℃,但加上AD转换误差和接线端子接触电阻,整体误差会进一步变大。对高精度HVAC计量,建议选A级PT100,并且在端子上用冷压端子压接,不允许直接拧螺丝,因为长期震动会导致接触电阻漂移。

5.3 误差项的叠加估算

我把一套典型系统的误差预算列出来,方便你做选型参考。假设是A级PT100四线制,外部基准电阻0.1%,ADS122U04内部基准温漂10ppm/℃,校准后残余增益误差0.01%,环境温度变化范围20℃:

误差来源典型误差范围说明
PT100 A级电阻精度±0.15℃传感器自身误差
基准电阻容差±0.05℃比例测量已消除大部分
ADC INL和增益误差±0.03℃校准后剩余
激励电流温漂±0.02℃比例测量后影响很小
量化噪声±0.001℃24位下可以忽略
冷端误差(RTD无此项)-仅热电偶相关
总计典型值±0.25℃满足HVAC控制要求

这个误差估算的意义在于:如果传感器本身误差是±0.3℃,硬件电路做得再好,系统测试精度也不可能优于±0.3℃。所以选传感器时一定要看等级参数,不能只看分辨率。

6. 实测中踩过的坑:EMC、供电噪声和调试技巧

再好的芯片,如果供电和布局不合理,也发挥不出性能。这一部分记录我在调试和现场试运行过程中遇到的几个问题,都是常规文档里不容易注意到的细节。

6.1 开关电源纹波造成的转换跳动

第一次打样时,我用24V开关电源经过DC-DC降到5V,再经LDO降到3.3V给整板供电。ADC单独由LDO供电,但DRDY引脚和UART线上还是能测到100mV级别的小脉冲噪声。表现为温度读数在0.1℃范围内来回跳,不是一直偏,而是随机跳动。

排查过程比较曲折。先怀疑是软件滤波不够,把滤波窗口加长到10秒,现象有所缓解但没根除。后来用示波器对比AVDD引脚和UART数据线,发现每次UART发送命令时AVDD上都会出现一个尖峰。原因是ADC的数字IO和模拟电路共用了一个3.3V电源域,数字开关噪声通过电源耦合进模拟前端。

解决方法是把ADS122U04的AVDD和DVDD分别用两个LDO供电,中间用磁珠隔开,模拟地和数字地单点连接。更进一步,我把UART线换成双绞线,并在ADC侧增加RC滤波。改动后同样位置测下来,转换结果非常平稳,长期运行没有再现跳动。

如果在预算允许的情况下,也可以给ADS122U04配一颗专用基准源,比如REF5025之类,把REF引脚的输入噪声压到个位数微伏级别。对于HVAC这种0.5℃精度的应用,内部基准已经够用,但发烧级追求可以用外部基准。

6.2 地址冲突和多设备总线调度

当系统里同时挂多片ADS122U04时,UART总线调度就会复杂起来。ADS122U04支持通过命令设置设备地址,上电默认地址是某个值。我在一次多板测试中,因为两片ADC都忘了修改地址,导致MCU发一条指令后两片同时响应,接收缓冲区数据全部乱掉。

解决方法是:上电时只让一片ADC的通信线使能,其他片保持高阻或断电,然后逐一对每片写入独立地址;之后才允许共同挂到总线上。这相当于一个“上电分配地址”的流程。我把这个流程做进了生产测试程序,后续现场更换ADC板卡时也用同样的方式分配地址,彻底告别冲突问题。

单片ADC应用的情况下,地址冲突不会出现,但要注意UART帧的应答超时。如果ADC正在忙转换,没有及时应答,MCU要设置超时重试。我一般把UART超时定为50ms,超过就丢弃并重新发送同步命令。

6.3 调试利器:监听UART报文

调试这个系统最有效的方法,不是盯着温度数值看,而是把ADS122U04和TM4C129之间的UART报文全部抓出来。我用TM4C129的另一个UART作为调试口,把ADC收到的每一帧原始数据打印出来,同时打印解析后的码值、CRC状态和温度值。

有了这组日志,可以很清楚地判断温度异常是通信链路问题还是换算问题。比如码值变化正常但温度不对,那大概率是换算公式或查表边界错误;如果码值本身就跳,那就要回头查供电、接地和传感器接线。这个习惯帮我节省了很多瞎猜时间。

另外,ADS122U04的DRDY信号很好用。调试时把它接到TM4C129的一个GPIO上,并在GPIO中断里翻转一个调试引脚,用示波器同时观察DRDY和UART数据帧的时间关系,可以确认数据是否在转换完成后才被读取。如果数据在ADC还没转换完成时就启动读取,读回来的是上一通道旧值,这一个问题能造成很多莫名其妙的现场故障。

最后再分享一个经验:ADS122U04的寄存器配置和CRC校验一旦写好,就不要频繁改动。把配置表固化下来,只开放传感器类型和通道数两个参数。现场调试越简单,量产一致性越好。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进