ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

ADS122U04+STM32F722VE:工业温度采集与RTD热电偶设计实战

ADS122U04+STM32F722VE:工业温度采集与RTD热电偶设计实战

做工业仪表和HVAC控制柜的项目,温度测点是最容易被低估的信号源。ADC芯片选不好、线性化处理不到位,后面PID调得再好都是白搭。ADS122U04IPWR这颗TI出品、自带UART接口的24位Δ-Σ ADC,配合STM32F722VE这个Cortex-M7主控,是我这两年做温度采集板用得比较顺手的组合。这篇文章把完整的选型思路、硬件接线、固件实现和调试踩坑过程都摊开讲,适合正在做多路温度采集、RTD/热电偶前端、或者想把采集模块独立出来的工程师参考。

1. 为什么是ADS122U04 + STM32F722VE:这套组合解决什么问题

1.1 工业与HVAC测温信号先得看清这几点

工业现场和HVAC系统里的温度测量,表面上是“读个温度”,实际信号类型五花八门。PT100/PT1000铂电阻输出的是电阻变化,热电偶输出的是微伏级电压,NTC热敏电阻又是强非线性的阻抗变化。这些信号都有一个共同特点:动态范围大、噪声环境恶劣、但更新速率要求不高。

拿PT100来说,0℃时100Ω,温度系数大约0.385Ω/℃,用250µA激励电流,温度每变化1℃只产生不到100µV的电压变化。这信号不用高增益PGA放大,普通ADC根本看不出变化。热电偶更夸张,K型热电偶灵敏度约41µV/℃,工业现场一个电机启动的电磁干扰都可能轻松超过这个量级。

所以做这类采集设备,第一要求不是采样率,而是分辨率、低噪声和抗工频干扰能力。ADS122U04这类24位Δ-Σ ADC天然适合这种场景:过采样架构把量化噪声摊薄,内置数字滤波器能把50/60Hz工频干扰压下去,配合可编程PGA,微伏级信号也能拉出可用的分辨率。

1.2 ADS122U04比SPI版ADS1220好在哪

ADS122U04和经常见到的ADS1220核心功能几乎一样:24位Δ-Σ ADC、4路模拟输入、两个可编程IDAC恒流源、内部2.048V参考、PGA增益1到128倍、内部温度传感器。最大区别是主机接口从SPI换成了UART。

很多做嵌入式的朋友会问,SPI不是更快吗,为什么非要用UART版?我在实际项目中体会到两个关键优势。

第一,UART在长距离传输上更皮实。SPI通常只能板内连接,超过十几厘米就容易受干扰;UART只要加个RS-485收发器,就能把ADC放在传感器附近,通过双绞线把数据传回几十米甚至几百米外的控制柜。工业现场传感器分散布置的场景,这个优势非常明显。

第二,省引脚、接线简单。SPI至少需要SCLK、MISO、MOSI、CS四根线,UART只要TX、RX两根。STM32F722VE的UART外设资源丰富,一块板子挂好几个ADS122U04,每个模块只需占用一组UART,对IO紧张的仪表板设计很友好。

当然UART也有代价:通信要按帧协议来,相比SPI多了一些字节封装的麻烦。但这个代价在温度采集这种低速场景下完全值得,毕竟温度测点通常每秒更新1到10次就够了。

1.3 STM32F722VE在这个系统里干什么活

STM32F722VE基于Cortex-M7核心,主频跑到216MHz,带单精度FPU,512KB Flash和256KB SRAM。拿来做温度采集主控,算力当面确实有点“大炮打蚊子”,但这恰好是它的优势。

温度换算可不是简单地查个表。PT100在0℃以下的Callendar-Van Dusen方程带三次项,需要用牛顿迭代求解;热电偶冷端补偿需要先查表得到冷端热电势,加回测量值后再反查温度。这堆计算在普通M3上也能跑,但STM32F722VE的FPU让浮点运算几乎不占CPU时间,主循环还能同时处理好几路UART数据、Modbus通信和继电器控制。

如果只做模拟量采集,用STM32F103也够。但做工业仪表往往还要跑通信协议栈、人机界面或简单的滤波算法,M7的高主频给后续功能扩展留了充足余量。我习惯把温度采集和逻辑控制放在同一颗MCU里,省掉一颗控制芯片,成本和故障率都降了。

2. 硬件链路设计:接线、激励与参考电阻至少要抠到这一步

2.1 RTD三线/四线接线与比例测量

RTD测温最核心的技巧不是ADC,而是怎么把几百欧姆的电阻变化可靠地变成可测量的电压。常见接法有两线制、三线制和四线制。两线制最省线,但引线电阻直接串在测量回路里,几十毫欧的线阻变化就会造成零点漂移,工业现场基本不用。

四线制精度最高:一对线给RTD送激励电流,另一对线只负责感知RTD两端的电压,感测线不流过电流,线阻完全不影响测量。如果板上有足够的模拟输入引脚,优先用四线制PT100,特别是在需要长期稳定性的场合。

三线制是工业现场的折中方案。原理是利用ADS122U04的两个IDAC恒流源,给两根引线通相同的电流,RTD两端的差分测量会自动把引线上的压降抵消掉。引出线尽量等长、同材质,效果能接近四线制。

这里有个更讲究的电路细节,强烈建议用比例测量而不是依赖内部参考电压。做法是让IDAC电流先流过一只精密电阻RREF,再流到RTD,把RREF两端的电压引到ADS122U04的REFP/REFN引脚作参考电压:

I_IDAC → RREF → L1 → RTD → L3 → GND REFP/REFN跨接在RREF两端 AINP/AINN差分跨接在RTD两端

这时ADC输出码只跟RREF和RRTD的比值有关:

code ≈ (RRTD / RREF) × 满量程码

激励电流的温漂、长期漂移同时作用在信号和参考上,比例相消。实测下来用这种方法,即使IDAC电流变化几个百分点,温度读数都不受影响。RREF本身的精度和温度系数反而是最需要把关的,我建议用0.1%精度、温漂低于10ppm/℃的金属膜电阻,别用可调电位器——电位器调起来方便,温漂大得吓人,等设备通上电跑起来,漂移能让你怀疑人生。

2.2 热电偶通道与冷端补偿设计

热电偶输出的是热端和冷端的温差电压,冷端补偿(CJC)做得好不好,直接决定绝对温度误差。ADS122U04内置了一个芯片温度传感器,典型精度±0.5℃,可以把冷端温度近似为芯片温度。为了减小误差,热电偶的冷端接插件要尽量靠近ADC芯片布置,让两者温度一致,中间不要有大功率器件或散热片。

热电偶电压只有几十毫伏,PGA增益建议设到64或128。J型、K型、T型热电偶在常规温度范围的输出都在几毫伏到几十毫伏之间,配内部2.048V参考电压,PGA=64时满量程约±32mV,已经能覆盖K型热电偶0到700℃左右的输出范围。

还有一个容易忽略的细节:热电偶测量回路需要给输入引脚提供一个直流通路。有些热电偶探头内阻很小没问题,但某些悬浮接法的探头可能会导致ADC输入悬空,让读数漂移。简单处理是在AINP和AINN之间并一个几百kΩ的电阻,或者利用IDAC给输入加一个微小偏置电流。

2.3 电源去耦和PCB布局要点

24位ADC做温度采集,最后读出多少位有效精度,很大程度取决于板子画得干不干净。AVDD和DVDD建议从同一个低噪声LDO输出,分别用磁珠或小电阻隔离再进芯片。模拟电源引脚边上放1µF和0.1µF电容组合,参考电压引脚REFP/REFN同样要放去耦电容,而且要紧贴引脚放置。

数字信号线和模拟输入线在PCB上尽量分区走线,UART的TX/RX信号不要贴着AIN输入线跑长距离。这方面我交过学费:第一版板子布局紧凑,把UART走线和热电偶差分线并行了大概3厘米,结果读数噪声从个位数LSB直接飙到几十个LSB。后来把模拟输入走线加宽、远离数字线,噪声才降回来。

模拟地和数字地不要分得太碎,我习惯做成完整的底层地平面,只在ADC芯片下方做单点连接。如果系统里有开关电源或继电器,注意让这些干扰源远离模拟输入区域,必要时在输入端加RC低通滤波:常见取100Ω串联电阻加100nF电容,截止频率大约16kHz,对宽带噪声很有帮助。

3. 固件实现:UART通信、寄存器配置与温度换算

3.1 UART初始化与ADS122U04寄存器写入

STM32F722VE的UART初始化用标准CubeMX配置即可,8位数据、无校验、1停止位。ADS122U04的UART帧格式和普通UART透传类似,主控发命令字节,器件回数据。初始化代码我习惯分成“MCU侧UART配置”和“ADC侧寄存器配置”两段。

/* 使用 USART1,波特率按器件手册要求设置 */ UART_HandleTypeDef huart1; static void uart1_init(void) { __HAL_RCC_USART1_CLK_ENABLE(); huart1.Instance = USART1; huart1.Init.BaudRate = 9600; /* 工业现场降速更稳 */ 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; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; HAL_UART_Init(&huart1); }

寄存器配置遵循ADS122U04数据手册中的映射关系,代表性的配置是写寄存器0、1、2:

static void ads122u04_write_reg(uint32_t reg, uint8_t value) { uint8_t cmd[3]; cmd[0] = 0x20 | (reg & 0x07); /* WREG命令,具体编码以数据手册为准 */ cmd[1] = 0x00; /* 写1个寄存器 */ cmd[2] = value; HAL_UART_Transmit(&huart1, cmd, 3, 100); HAL_Delay(1); } static void ads122u04_init(void) { /* 差分输入AIN0-AIN1,PGA增益16,内部参考 */ ads122u04_write_reg(0, 0x00); /* 数据速率20SPS,连续转换模式,正常功耗 */ ads122u04_write_reg(1, 0x00); /* 内部参考2.048V,IDAC电流250uA,路由配置 */ ads122u04_write_reg(2, 0x00); }

注意UART命令要一口气发完,不要在字节之间插入太长延时。TS是嵌入式工程师,不是所有人都有耐心读205页数据手册,需要保证12位有效精度。ADS122U04有独立RDATA命令,需要轮询时用。

3.2 PT100/PT1000的电阻-温度换算算法

ADC拿到的原始码先换算成RTD电阻值。比例测量下:

/* 假设已通过RDATA命令读到24位原始值 code */ float code = (float)raw_code; /* 满量程码按8388607计算,内部参考、PGA=16 */ float v_in = code / 8388607.0f * 2.048f / 16.0f; /* RTD电阻 = 输入电压 / 激励电流 */ float r_rtd = v_in / 0.00025f;

如果用了RREF比例参考,直接用比值算更干净:

float r_rtd = raw_code / 8388607.0f * rref;

这段我把PGA的影响写进公式了。如果配置是PGA=16,外部参考RREF=4.7kΩ,IDAC=250µA,那么满量程输入电压是2.048/16=128mV,PT100在0℃时只有25mV,码值大约是满量程的20%。

拿到电阻值之后,0℃以上用IEC 60751标准方程反解:

/* R0=100对应PT100;PT1000改成1000 */ static float rtd_to_temp(float r_rtd, float r0) { const float a = 3.9083e-3f; const float b = -5.775e-7f; const float c = -4.183e-12f; if (r_rtd >= r0) { /* 0℃以上:一元二次方程闭式解 */ float d = r_rtd / r0 - 1.0f; float disc = a * a + 4.0f * b * d; if (disc < 0.0f) disc = 0.0f; return (-a + sqrtf(disc)) / (2.0f * b); } else { /* 0℃以下:带C项的方程,用牛顿迭代 */ float t = -20.0f; for (int i = 0; i < 8; i++) { float r_model = r0 * (1.0f + a * t + b * t * t + c * (t - 100.0f) * t * t * t); float drdt = r0 * (a + 2.0f * b * t + c * (4.0f * t * t * t - 300.0f * t * t)); t -= (r_model - r_rtd) / drdt; } return t; } }

我用这个函数跑过从-50℃到350℃的仿真数据,迭代8轮收敛后误差在0.01℃以内。STM32F722VE的FPU跑这段几乎是瞬间的事,不用优化。

3.3 热电偶查表与冷端补偿计算流程

热电偶没有简单的解析方程,工程上最稳的路子是查表加线性插值。把NIST ITS-90标准表的整数度热电势存成数组放Flash,查表找相邻两点,线性插值。K型热电偶从-200℃到1300℃,每1℃存一个点,也就1500个16位数,3KB Flash搞定,STM32F722VE随便放。

实现流程分三步:

/* Step 1: 读取ADC原始码,换算成热电偶测量电压 */ float v_tc = read_thermocouple_mv(); /* Step 2: 读取ADS122U04内部温度传感器,得到冷端温度Tcjc */ float tcjc = read_chip_temperature_c(); /* Step 3: 查表,找出冷端温度对应的热电势E_cjc */ float e_cjc = tc_lookup_k_type(tcjc); /* Step 4: 总热电势 = 测量电压 + 冷端热电势 */ float e_total = v_tc + e_cjc; /* Step 5: 用总热电势反查温度 */ float temp = tc_reverse_lookup_k_type(e_total);

原理其实很简单:热电偶本身只输出“热端与冷端的温差电动势”,冷端温度补偿就是把这个温差电压补成“相对于0℃的绝对电压”。整个过程里最容易出错的是符号,冷端低于0℃时补偿查表返回负值,加总之前先确认极性。

芯片内部温度传感器每家出厂都有一点个体差异。如果项目要求整体误差0.5℃以内,我习惯在出厂校准环节把这颗芯片的CJC温度误差测出来,存进Flash做偏移补偿。只校准这一点,就能把冷端补偿的误差消化大半,比调放大增益性价比高得多。

4. 现场调试实录:常见问题与排查速查

4.1 通信时好时坏,先怀疑这几个地方

UART通信不稳定是这类模块最常见的问题。如果数据偶尔丢帧、读回来的值全是0xFF或者命令无响应,我建议按这个顺序排查。

第一是波特率误差。STM32F722VE如果用的外部晶振精度不高,或者波特率配置计算出的分频值有小数误差,误差累计超过2%就会造成偶发错帧。这时候把波特率从115200降到9600能立竿见影,9600波特率下同样的时钟误差所占比例更小,容错窗口更宽。

第二是共地问题。ADS122U04和STM32F722VE之间如果电压范围不同,双方必须可靠共地,否则UART信号电平参考不一致,时好时坏非常隐蔽。用示波器挂TX/RX线看波形,能直接看到毛刺和参考电平漂移。

第三是UART命令字节之间的间隔不稳定。如果代码里在发送命令时中间触发了高优先级中断,字节被拉开,器件端帧超时直接丢弃。解决方法是发命令时关中断或用DMA一次性搬完缓冲区。

4.2 读数满量程或乱跳,多半是输入链路问题

ADC读数固定在接近满量程的位置,最常见的原因是输入超出了可测范围。检查顺序是:先看MUX通道选对没有,再看PGA增益是不是太高,最后确认传感器连接没有断路。

PT100传感器断路时,IDAC电流没有回流路径,AINP引脚被拉向电源方向,读数往往会顶到满量程。这个特性反而可以当断线检测用:上电后先读一次码值,如果接近满量程,直接报故障,不需要额外硬件。当然,热电偶断开也会出现类似情况,用4.7kΩ上拉电阻接在输入引脚能帮助区分。

读数随机乱跳则要考虑是不是采样率设得太高了。ADS122U04在2000SPS下噪声很大,温度控制又不需要这么快的速度。我通常把数据速率设为20SPS,这个档位对50/60Hz工频有专门的陷波,效果比任何外接滤波都明显。

4.3 温漂、自热和引线电阻的三个隐藏误差源

排除通信和断线问题之后,如果整体精度还是提升不上去,基本就是三个“软刀子”在作怪。

自热效应最容易被忽视。恒流源激励电流本身就是热源,电流消耗在传感器上,传感器温度会高于被测介质。PT100用1mA电流时自热功率100µW,在静止空气中可能造成0.1到0.5℃的偏差。所以我做RTD项目时习惯用250µA或500µA激励,宁可把PGA开大一点,也不让自热影响读数。

引线电阻误差在三线制里已经通过IDAC配对抵消了大部分,但如果引线材质不一致或长度差异太大,残余误差依然明显。上电自检时可以做一次“引线电阻学习”:测量IDAC在引线上产生的压降,把测到的引线电阻存起来,正常测量时软件里减去这部分。

温度漂移方面,如果板子上的数字电路发热明显,ADC芯片温度跟着变化,冷端补偿会出现缓慢漂移。机械结构上让传感器接线端子尽量避开电源芯片和MCU,PCB上也能开一些隔热槽,实测能改善冷端温度的一致性。

现象常见原因排查动作
读数为0或极小传感器短路、MUX通道错检查接线和寄存器配置
读数固定满量程传感器开路、输入超限做断线检测、降PGA
读数缓慢漂移自热、参考电阻温漂减小激励电流、换低TCR电阻
读数跳字严重采样率过高、数字干扰设20SPS、调整PCB隔离
UART偶发无响应波特率误差、命令间隔不稳降速、关中断发送

5. 实测收尾:轮询式架构下的一些优化习惯

5.1 轮询节奏与功耗平衡怎么定

温度采集项目的核心指标通常是刷新率和功耗的平衡。我实测下来,ADS122U04在20SPS数据速率下单次转换时间大约50ms,轮询读取时把主循环节奏定在100ms(10Hz),既能平滑显示读数,又不会让MCU因为频繁读UART而满载。如果只有一路温度,甚至可以降到1Hz刷新,功耗和电磁干扰都会小很多。

轮询时用阻塞式HAL_UART_Transmit和Receive也够用,因为10Hz频率下CPU大部分时间都在空闲。只有在一颗MCU挂多个ADS122U04、并且还跑Modbus通信时,我才建议用DMA+空闲中断的方式接收数据,否则代码复杂度反而增加。

5.2 提前留好调试和校准入口

最后分享一个经验:开发这类仪表板时,一定要在固件里预留两个接口。第一个是“原始值透传”,就是能把ADC码值、参考电压、中间计算量直接通过串口打出来。现场出现精度问题,能立刻区分是前端信号不对还是软件换算不对,省去大量排查时间。

第二个是“温度校准入参”,把RTD的R0、冷端补偿偏移、RREF实际阻值做成可配置参数,存在Flash里。每次校准时只需要通过串口命令改这几个数,不用重新烧录固件。我做过的几台设备,出厂校准和售后维护靠这两个接口省下不少事。

ADS122U04和STM32F722VE这套组合,优点就是“测量端交给专业ADC,算力端交给MCU,中间用一根稳定的UART串起来”。顺着这个架构,单纯做温度采集、扩展成多路采集模块、或者接入RS-485总线当智能传感器节点,都在同一个技术框架内。按我上面的接线和代码思路走,第一次跑通读出稳定温度的时间,应该能控制在几天以内。

返回列表