
做温度采集项目时在“用什么传感器”这个问题上纠结了很久。热电偶量程大但冷端补偿麻烦NTC便宜但线性度差DS18B20省事可精度和长期稳定性又差点意思。最后选了PT100铂电阻加MAX31865前端芯片的方案——PT100在工业领域十分常见、互换性好而MAX31865这颗芯片把RTD测量的关键环节都集成好了外部只需一个精密参考电阻配合STM32的硬件SPI和外部中断就能稳定拿到高精度温度数据。这篇文章把我从CubeMX配置到驱动代码、再到温度换算和现场调试的完整过程都整理出来适合正在做高精度温度采集、或者刚接触MAX31865与PT100的嵌入式开发者照着这套思路走能少踩不少坑。1. 方案设计为什么是“硬件SPI 外部中断”1.1 MAX31865相比其他测温方案的取舍先说结论如果你需要测量-200℃到850℃范围内的温度且精度要求达到±0.5℃甚至更高PT100配合MAX31865几乎是性价比最高的组合。PT100在0℃时电阻为100Ω灵敏度约为0.385Ω/℃也就是说要分辨0.1℃的变化需要能测出0.0385Ω的电阻差异。这对普通ADC来说很难但MAX31865内部有15位ADC配合430Ω参考电阻理论上能分辨约0.013Ω折合成温度大约是0.03℃完全够用。MAX31865真正省心的地方在于它把恒流源激励、可编程增益放大、ADC转换、故障检测全部集成了。你不需要像用AD7124或ADS1120那样自己搭前置放大电路也不用操心RTD的激励电流该设多少。对于量产项目来说BOM精简校准成本也低。当然它也有局限性MAX31865只能测电阻不能直接测热电偶或NTC。如果你的项目既要PT100又要热电偶可以考虑AD7124这类多通道ADC但驱动复杂度和调试成本会翻好几倍。我这边的经验是单一测温场景用专用前端芯片比用通用ADC省心得多。1.2 硬件SPI与软件SPI的取舍很多刚入门的朋友喜欢用IO口模拟SPI时序也就是俗称的“软件SPI”觉得这样引脚分配灵活、不用研究外设寄存器。对于低频、低速的通信软件SPI确实能用但在这类连续测温场景下不推荐。主要原因是软件SPI靠延时翻转时钟线MCU被占得死死的。假设你以500kHz频率翻时钟每bit耗时2微秒读一次RTD数据要发命令字节和接收两个数据字节共24个时钟周期光这一趟就要花近50微秒。听起来不多但如果系统里还要跑屏幕刷新、通信协议、控制算法软件SPI抢占CPU的时间会非常可观。硬件SPI就不同了STM32的SPI外设自动产生时钟、移入移出数据CPU只需把数据寄存器写进去然后等传输完成标志位就行。配合DMA的话连等待都省了。另外硬件SPI的时序是芯片内部电路保证的不会因为中断优先级被人为打断而出错。软件SPI如果中途来了个高优先级中断时序就崩了。MAX31865的SPI速率上限约为5MHzSTM32的硬件SPI很容易满足。我的做法是预分频设到1MHz左右兼顾稳定性和抗干扰能力。SPI速率并不是越快越好尤其连接线较长时速率过高容易产生信号反射。1.3 硬件片选与软件片选怎么选SPI片选有两种实现方式一是用SPI外设的硬件NSS引脚二是在普通GPIO上用软件拉低拉高。硬件NSS的好处是CPU不用管开始传输时硬件自动拉低传输结束自动拉高。但实际用起来有两个隐患。第一HAL库在有些情况下对硬件NSS的处理并不完美比如TransmitReceive与Transmit混用时NSS拉高的时机可能不符合从设备的预期。第二如果SPI总线上挂了多个从设备每个从设备的命令长度不同硬件NSS只管理一个引脚其他从设备仍要用GPIO那不如全部用GPIO管理和排查都方便。MAX31865在空闲状态下CS必须保持高电平否则会误判为一次传输。用普通GPIO控制CS时序完全由自己把控多读一个字节少读一个字节都清楚出问题也好查。所以这个项目我推荐软件片选。1.4 外部中断监听DRDY省心又高效MAX31865有一个DRDY引脚转换完成后会拉低通知主控可以读取数据了。这个引脚如果不用就得自己估算转换时间然后延时去读费时费力还不准。而用STM32的外部中断功能监听DRDY下降沿是最理想的配合方式。读到DRDY拉低后说明RTD寄存器里已经是最新的转换结果。外部中断服务函数里只做一件事置一个全局标志位。主循环检测到标志位后再通过SPI读取数据。这样既可以避免中断服务函数里执行SPI通信这种耗时操作又能保证每次读取的都是有效的新数据。2. 硬件连接PT100接法与MAX31865模块接线2.1 PT100的2线、3线、4线制接线PT100是一种铂电阻温度传感器阻值随温度变化。它有几种接线方式直接影响测量精度。二线制最简单就是两根线直接接在RTD两端。问题是这两根导线本身有电阻这个导线电阻会和PT100串联混进测量结果。以铜导线为例1米长的细线电阻大约在0.1Ω到0.5Ω之间一算就知道能产生几摄氏度的误差。所以二线制只适合短距离、对精度要求不高的场景。三线制是工业现场最常用的方式。原理是用一根额外导线测量导线电阻然后在计算中抵消掉能消除大部分导线电阻误差适用于几十米以内的传输距离。四线制精度最高。两根线流过激励电流另两根线负责测量电压。测电压的线上几乎没有电流所以电压降为零测到的就是PT100两端的真实电压。实验室标准计量大多用四线制。我这次使用的是四线制PT100接线顺序是一根接RTD一根接RTD-另外两根接FORCE和FORCE-。如果用MAX31865成品模块接三线制PT100需要把RTD-和FORCE-短接具体看模块丝印说明。二线制则是把RTD-和FORCE-用跳线帽连在一起。2.2 MAX31865与STM32的引脚连接以STM32F103系列为例我选用了SPI1外设对应引脚为PA5SCK、PA6MISO、PA7MOSI片选CS用PA4DRDY外部中断接PB0。接线表如下MAX31865模块引脚STM32引脚说明VIN3.3V注意模块是否带稳压不带稳压只能接3.3VGNDGND共地SCLKPA5SPI1_SCKMOSIPA7SPI1_MOSIMISOPA6SPI1_MISOCSPA4软件片选任意GPIODRDYPB0外部中断输入下降沿触发SPI的MISO和MOSI很容易接反接反的典型现象是读回来的数据全是0xFF或0x00而且怎么调配置都不对。接好线后先用万用表量一遍通路再上电能省不少排查时间。需要注意DRDY引脚是开漏输出模块上一般已经带了上拉电阻。如果自己画板子DRDY一定要接一个10k电阻上拉到VCC不然电平拉不起来外部中断永远触发不了。2.3 参考电阻的选择与精度影响MAX31865的测量原理是比率式测量外部参考电阻Rref和PT100串联同一路激励电流分别流过这两个电阻。芯片通过ADC测量两个电阻上的电压之比就能推算出PT100的电阻值。计算公式是RTD阻值 ADC读数 ÷ 32768 × Rref。对于PT100Rref的推荐值是430Ω。这是因为PT100在850℃时阻值约为390.5Ω430Ω留出一点余量确保整个量程都在ADC的满量程范围内。这里有一个特别需要注意的点参考电阻的精度直接决定了测温精度它的误差会毫无衰减地反映到最终的电阻计算结果中。比如Rref是1%精度的430Ω那温度误差也会在1%左右换算成温度值可能有好几度偏差。所以选参考电阻要选0.1%精度、温漂系数低的低温漂电阻。成品MAX31865模块上一般已经焊好了430Ω 0.1%电阻但如果是自己画板子元件选型时要格外上心。3. STM32CubeMX详细配置过程3.1 时钟树设置打开STM32CubeMX新建工程后先把系统时钟配好。f103可以直接用外部晶振经过PLL倍频到72MHz如果没有外部晶振用内部HSI也可以只是精度稍差。MAX31865对SPI时钟源要求并不苛刻APB2外设时钟跑72MHz还是64MHz都不影响。在Clock Configuration页面把HCLK设置为72MHzAPB1分频器设2APB2分频器设1。SPI1挂在APB2上所以SPI外设时钟就是72MHz。后面配置SPI波特率时要用到这个数值。3.2 SPI外设配置进入Connectivity - SPI1配置页面Mode选择Full-Duplex MasterHardware NSS Signal选择Disable因为我们用软件片选Clock Polarity选择LowClock Phase选择2 EdgePrescaler选择64分频Data Size选择8 bitFirst Bit选择MSB First分频64之后SPI波特率就是72MHz ÷ 64 1.125MHz低于MAX31865的5MHz上限安全稳妥。之前我试过更大分频让速率跑更高结果用15厘米杜邦线连接时出现了偶发读取出错降速后问题消失。对于转换速率每秒只有几次的MAX31865来说SPI速率不是瓶颈稳定比速度重要。模式选择这里再说得细一点。MAX31865数据手册支持SPI Mode 1和Mode 3这两种模式时钟极性不同但相位都是第二个边沿采样。我习惯用Mode 1也就是Clock Polarity是Low、Clock Phase是2 Edge。如果配置成模式0或者模式2数据采样的边沿就不对了读回来的字节会错位。3.3 片选GPIO与DRDY外部中断配置CS片选我们配置为普通推挽输出GPIO初始电平设为High因为SPI从设备在CS高电平时处于未选中状态。在CubeMX中选中PA4引脚在GPIO配置里设置为GPIO_OutputOutput level选High。引脚标签我一般命名为CS_MAX31865代码里看起来清晰。DRDY引脚配置为外部中断模式。选中PB0引脚GPIO mode选择External Interrupt Mode with Falling edge trigger detection也就是下降沿触发。上下拉选择Pull-up保险起见多一道保障。标签命名为DRDY_MAX31865。然后在NVIC配置页面使能EXTI line0中断优先级根据项目实际需求设置。如果项目里还有其他中断建议把EXTI优先级设高一些因为DRDY触发后我们只是置标志位执行时间极短优先级高也不会影响其他任务。3.4 生成代码前检查配置完成后在Project Manager页面选择工具链为MDK-ARM或者STM32CubeIDE版本选择对应工具链。代码生成器里勾选“Generate peripheral initialization as a pair of .c/.h files per peripheral”这样每个外设生成独立的文件维护方便。还要勾选“Copy only the necessary library files”避免生成一堆用不到的模板代码。生成代码后不要手动修改HAL库生成的外设初始化代码区域比如MX_SPI1_Init函数内部。用户自己的代码要写在USER CODE BEGIN和USER CODE END注释块之间这样重新生成代码时不会丢失。这一点在反复调整CubeMX配置时特别重要不然辛辛苦苦改的代码一次重新生成就没了。4. MAX31865核心原理与寄存器配置4.1 MAX31865的比率式测量原理理解MAX31865的测量原理对写驱动非常有帮助。芯片内部有一个精密的ADC但测量的不是绝对电压而是RTD上的电压与参考电阻上电压的比值。工作过程大致是这样内部偏置电压源使电流流过串联的Rref和RTD芯片测量RTD上的电压V_rtd和Rref上的电压V_ref然后计算出比值。因为流过两个电阻的电流相同所以电压比就等于电阻比V_rtd : V_ref R_rtd : R_ref。这种设计的巧妙之处在于激励电流源的绝对大小和稳定性不影响最终结果。就算电流源随温度变化漂移了5%两个电阻上的电压会同步变化比值保持不变。所以真正决定测量精度的只有Rref的精度、ADC的分辨率以及PT100自身的精度。ADC结果和电阻的换算关系是R_rtd (ADC_CODE / 32768) × R_ref。ADC_CODE是15位数据满量程32768对应RTD电阻等于Rref。4.2 寄存器地址与读写机制MAX31865的寄存器不多关键就这几个寄存器地址名称说明0x00Configuration配置寄存器控制偏置电流、转换模式、滤波频率、故障检测0x01RTD Data MSBsRTD电阻数据高字节0x02RTD Data LSBsRTD电阻数据低字节0x03High Fault Threshold MSB高故障阈值高字节0x04High Fault Threshold LSB高故障阈值低字节0x05Low Fault Threshold MSB低故障阈值高字节0x06Low Fault Threshold LSB低故障阈值低字节0x07Fault Status故障状态寄存器读写操作都是通过SPI传输命令字节实现的。命令字节的最高位是读/写标志1表示读0表示写。后面7位是寄存器地址。比如读取RTD数据寄存器命令字节就是0x80 | 0x01 0x81。向配置寄存器写值命令字节就是0x00。注意RTD数据寄存器的高字节是0x01低字节是0x02但它们是同一个15位ADC结果的高8位和低7位。读取时需要发送读命令后连续接收两个字节然后把两个字节拼成一个16位数据再右移一位去掉最低的无用位得到真正的15位ADC值。因为MAX31865的15位ADC结果存储在16位寄存器的bit15到bit1bit0固定为0。4.3 配置寄存器0x00的关键位默认上电后配置寄存器值为0x00这意味着偏置电流是关闭的。如果不写配置寄存器就马上读RTD数据读回来的ADC值会是0温度计算出来肯定不对。这是很多新手犯的第一个错误。常用的配置值是0xC0二进制为1100 0000含义是bit7为1打开偏置电流VBIAS enablebit6为0连续自动转换模式bit5和bit4为00故障检测使用自动延迟模式bit3为1选择50Hz滤波抑制工频干扰bit2为0不触发故障清除bit1和bit0为0保留位这里我特别说一下滤波频率的选择。如果所在地区电网频率是50Hz选50Hz滤波能明显抑制工频干扰。实测中如果选了60Hz滤波但环境里有50Hz干扰源读数的波动会明显增大。MAX31865的转换时间和滤波设置有关50Hz模式下转换周期会稍长一些但换来的是更稳定的读数值得。4.4 从配置到读数的完整时序MAX31865的操作时序其实很简单但有几个时间点要留意。第一刚上电时不要立即读数据。配置寄存器写入0xC0后偏置电流建立和第一次故障检测都需要时间。我的处理方法是写入配置后延时100ms再开始正常读取流程。这个延时是为了让电源和偏置稳定等第一个转换周期完成DRDY引脚自然会产生下降沿。第二DRDY引脚拉低代表一次转换完成数据已更新到RTD寄存器。读取RTD寄存器后DRDY会自动复位为高电平。所以主循环里的逻辑是等待DRDY下降沿标志然后读数据读完后等下一次下降沿。第三故障检测如果配置为自动延迟模式只在启动时进行一次检测检测结果输出到故障状态寄存器。之后正常转换过程中不会再自动进行故障检测这样避免故障检测周期干扰正常测量。如果需要在运行中持续监控RTD的断线和短路可以改用自动周期性检测模式代价是转换时间会变长。5. 驱动代码实现与温度换算5.1 SPI底层读写封装首先封装两个最基础的函数读寄存器和写寄存器。// 片选控制宏 #define MAX31865_CS_LOW() HAL_GPIO_WritePin(CS_MAX31865_GPIO_Port, CS_MAX31865_Pin, GPIO_PIN_RESET) #define MAX31865_CS_HIGH() HAL_GPIO_WritePin(CS_MAX31865_GPIO_Port, CS_MAX31865_Pin, GPIO_PIN_SET) // 写寄存器reg为寄存器地址bit7需为0data为要写入的数据 void MAX31865_WriteReg(uint8_t reg, uint8_t data) { uint8_t tx[2] {reg 0x7F, data}; MAX31865_CS_LOW(); HAL_SPI_Transmit(hspi1, tx, 2, 10); MAX31865_CS_HIGH(); } // 读寄存器reg为寄存器地址函数内部自动加读标志0x80 uint8_t MAX31865_ReadReg(uint8_t reg) { uint8_t tx 0x80 | reg; uint8_t rx 0; MAX31865_CS_LOW(); HAL_SPI_TransmitReceive(hspi1, tx, rx, 1, 10); // 此时rx读到的内容无效需要再发一个字节得到真正的寄存器数据 tx 0; HAL_SPI_TransmitReceive(hspi1, tx, rx, 1, 10); MAX31865_CS_HIGH(); return rx; }有人会问为什么读寄存器要发两个字节因为MAX31865在接收到读命令后还需要一个时钟周期才会把数据移出到MISO上。第一个字节期间移出的内容没有意义要再持续给时钟才能拿到有效数据。有的驱动写法是把命令字节和后续的读字节放在一个TransmitReceive里一起处理也一样。5.2 读取RTD电阻数据读取RTD数据寄存器更高效的做法是连续读两个数据字节// 读取RTD数据返回15位ADC值 uint16_t MAX31865_ReadRTD(void) { uint8_t tx[3] {0x81, 0x00, 0x00}; uint8_t rx[3] {0, 0, 0}; uint16_t adc_value 0; MAX31865_CS_LOW(); HAL_SPI_TransmitReceive(hspi1, tx, rx, 3, 10); MAX31865_CS_HIGH(); // rx[0]是命令字节期间的无效数据实际数据在rx[1]和rx[2] adc_value ((uint16_t)rx[1] 8) | rx[2]; // 右移一位去掉bit0得到15位有效ADC值 adc_value 1; return adc_value; }MAX31865的RTD数据寄存器地址是0x01但一次发送读命令后芯片会自动把连续的下一个寄存器也读出来所以读0x81命令后跟两个字节就能依次拿到0x01和0x02的数据。这个连续读特性在读取状态寄存器多的外设时很方便。5.3 外部中断回调与主循环处理在CubeMX生成的stm32f1xx_it.c里GPIO外部中断的中断服务函数已经调用了HAL_GPIO_EXTI_IRQHandler它会再调用弱定义的HAL_GPIO_EXTI_Callback回调函数。我们只需要在用户代码区域重写这个回调函数// 全局标志声明为volatile防止编译器优化 volatile uint8_t max31865_data_ready 0; void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin DRDY_MAX31865_Pin) { max31865_data_ready 1; } }主循环里这样处理while (1) { if (max31865_data_ready) { max31865_data_ready 0; uint16_t adc MAX31865_ReadRTD(); float resistance Rref * adc / 32768.0f; float temperature RTD_ResistanceToTemp(resistance); printf(ADC:%d R:%.2f T:%.2f\r\n, adc, resistance, temperature); } }在中断里只置标志位、不在中断里做SPI通信是个很重要的习惯。SPI通信有等待延时如果延时稍长会影响其他中断响应。标志位方案把耗时的操作全部放在主循环里执行中断服务短平快这也是外部中断配合慢速外设的常见模式。5.4 PT100电阻换算温度的两种方法拿到PT100的电阻值后需要换算成温度。这里有两种常用方法。第一种是查表法。PT100的分度表是标准化的把对应温度下的电阻值做成数组然后根据测得的电阻值在数组里查找不在整数点就线性插值。这种方法的优点是覆盖面广从-200℃到850℃都能处理缺点是表格数据量大占用Flash空间。第二种是公式法。根据IEC 60751标准PT100在0℃到850℃范围内电阻与温度的关系可以用二次方程近似R 100 × (1 A×T B×T²)其中A 3.9083×10⁻³B -5.775×10⁻⁷。反过来由电阻求温度就是解这个二次方程。公式法代码实现更简洁我推荐在0℃到850℃范围内使用#include math.h #define PT100_R0 100.0f // 0℃时的电阻 #define PT100_A 3.9083e-3f #define PT100_B -5.775e-7f // 由PT100电阻值计算温度单位℃适用于0℃到850℃ float RTD_ResistanceToTemp(float resistance) { float temp 0.0f; float delta 0.0f; // 解方程 R R0 * (1 A*T B*T^2) // 即 B*T^2 A*T (1 - R/R0) 0 delta PT100_A * PT100_A - 4.0f * PT100_B * (1.0f - resistance / PT100_R0); if (delta 0.0f) { temp (-PT100_A sqrtf(delta)) / (2.0f * PT100_B); } return temp; }验证一下当resistance等于100Ω时delta A²temp (-A A) / (2B) 0结果是0℃当resistance等于138.5Ω时算出来的温度约等于100℃符合PT100的典型特性。如果测温范围包含0℃以下这个二次方程就不够了。标准规定负温度区间需要用带三次项C的方程好在工程上低温段的导通电阻和校准曲线问题比较多更稳妥的做法是负温区查表。我的项目只需要0℃以上的温度所以公式法足够。5.5 数据滤波与抗干扰处理MAX31865本身是24位ADC芯片但内部集成的数字滤波器只能抑制工频干扰。在工业现场RS485通信、电机启停、电源纹波都可能引入随机噪声表现为读数小幅抖动。实际测试中如果DRDY引脚走线较长或者SPI线与其他信号线并行走线读数偶尔会跳几个码。我的处理方法是主循环里做简单的滑动平均。每收到5次有效温度值取一次平均然后输出。这样既不增加太多代码复杂度又能明显改善读数的稳定性。#define FILTER_LEN 5 float filter_buf[FILTER_LEN]; uint8_t filter_index 0; float Temperature_Filter(float new_temp) { float sum 0.0f; uint8_t i 0; filter_buf[filter_index] new_temp; if (filter_index FILTER_LEN) { filter_index 0; } for (i 0; i FILTER_LEN; i) { sum filter_buf[i]; } return sum / FILTER_LEN; }更极端的情况如果读数偶尔出现特别离谱的跳变可以做中值滤波或者限幅滤波把超出合理范围的异常值直接丢弃。不过MAX31865的硬件故障检测本身已经能发现很多异常软件滤波只需处理常规噪声。6. 常见问题速查与调试心得6.1 故障状态寄存器逐位解读MAX31865的故障状态寄存器是0x07读出来后每一位代表一种故障情况。调试过程中这寄存器能帮大忙。位含义排查方向D7故障汇总标志置1表示有任一故障继续看低7位是哪个D6RTD超过高阈值检查高阈值寄存器是否被设为合理值D5RTD低于低阈值检查低阈值寄存器或PT100是否短路D4参考电压负端输入大于0.85×偏置电压检查RFORCE-和REFIN-接线D3参考电压负端输入小于0.85×偏置电压参考电阻是否虚焊或开路D2RTD负端输入小于0.85×偏置电压可能是RTD断线D1过压欠压故障检查供电是否稳定接近3.3VD0保留忽略读取故障状态寄存器会锁存当前故障状态处理完故障原因后需要在配置寄存器里把D2位置1来清除故障标志然后再写回正常的0xC0配置。如果不做清除操作故障标志可能会一直保持。6.2 典型现象一ADC读数全是0xFFFF这个现象很直观SPI读回来的RTD寄存器全是1说明MISO线上没有有效数据常见原因有三个。第一是MISO和MOSI接反了。SPI是同步串行接口发送和接收各自独立走线接反的话主设备发给从设备的数据会被接到自己的MISO上读不到任何有效内容。第二是CS引脚没有拉低MAX31865根本不参与通信。第三是SPI的时钟极性和相位配置不对采样边沿采不到有效电平。排查办法是先用示波器或者逻辑分析仪看SCK时钟波形确认时钟有无产生再看MISO线上在SCK边沿时是否有对应电平变化。如果MISO一直高电平大概率是CS没拉低或者从设备没上电。6.3 典型现象二ADC读数全是0x0000读到全0和全FFFF原因不同。全FFFF多数是通信层面问题而全0往往是MAX31865没有产生有效转换。最常见的原因就是配置寄存器没有正确写入偏置电流没有打开。上电后MAX31865默认配置为0x00偏置电流关闭RTD上没电流流过ADC自然是0。按前面说的初始化时写入0xC0就能解决。另一个可能是配置寄存器写入失败了。写操作是单向的主控发完指令后要稍等片刻再启动读取流程。如果芯片还在处理上一帧数据时就强行片选拉低发新命令数据可能没写进去。6.4 典型现象三温度读数偶发抖动MAX31865的硬件分辨率其实很高所以读数稳定时小数点后一位一般不跳。如果发现读数抖动先确认滤波频率选择是否与环境一致。50Hz工频环境下选了60Hz滤波干扰会直接透进来。把配置寄存器改成0xC0可以避开。然后检查DRDY引脚附近有无强干扰源。DRDY信号本身是低频数字信号如果走线又长又经过电机驱动模块附近容易受到磁场耦合干扰。解决办法是缩短走线、加RC滤波或者在软件里增加滑动平均。6.5 调试过程中的几个实用心得有条件的话用逻辑分析仪同时抓CS、SCK、MOSI、MISO四路信号传输是否正常一目了然。我之前遇到过一次数据错位问题排查了很久最后发现是CS拉低和SCK首沿之间没有足够的建立时间在CubeMX配置里增加低速分频后问题才解决。MAX31865的寄存器写入最好加一个读回校验。写配置寄存器0xC0后马上从0x00读回来看看是不是0xC0。如果读回来不对后面所有操作都没意义早发现早处理。另外项目正式量产前建议每块板子做一次温度校准。方法是用精密电阻箱代替PT100在0℃、100℃、300℃三个温度点对应的电阻值处分别记录ADC转换结果再做两点或三点校准。虽然MAX31865内部精度够高但参考电阻的个体误差会带入系统性误差校准之后整体精度更有保证。最后再分享一个小技巧如果DRDY引脚引脚紧张短期内又不方便重新画板也可以用任意一个普通GPIO轮询DRDY电平DRDY为低说明转换完成读到高就一直等。代价是CPU需要在等待期间不断查询电平不能进入低功耗模式。而外部中断方案只需要一个下降沿就能把MCU的等待阻塞降到最低。测温系统如果是由电池供电的遥测终端这个差异就直接关系到整机功耗。我自己在实际项目中把DRDY外部中断、硬件SPI、软件片选这套方案稳定跑了好几个月温度波动控制在±0.1℃以内故障检测还能准确识别出探头脱落和参考电阻异常。这种组合从配置难度、代码量、稳定性几个角度来说都比较均衡。新项目如果也是做PT100测温照着这套搭就对了。