MAX31855热电偶读取详解:硬件SPI与软件模拟SPI实现与调试

发布时间:2026/10/6 16:32:31
MAX31855热电偶读取详解:硬件SPI与软件模拟SPI实现与调试 做温度采集项目时K型热电偶配合MAX31855是一套非常经典、稳定、性价比也高的方案。MAX31855这颗芯片自带冷端补偿、信号放大和模数转换MCU只需要通过SPI把转换结果读回来就行省掉了大量模拟前端设计。整个项目真正花时间的反而是读取方式你是直接用MCU自带的硬件SPI外设还是用GPIO去软件模拟SPI时序这篇文章就围绕这个核心把MAX31855的电路设计、数据格式、两种读取方式的原理和代码实现全部拆开讲一遍顺带记录我实际调试过程中踩过的坑。适合正在做热电偶测温、温控器、3D打印机热床监测、工业设备温度采集的朋友参考不管你是用STM32、ESP32还是51原理都一样。1. 认识MAX31855为什么热电偶都配这颗芯片1.1 这颗芯片到底帮你省了什么热电偶本身输出的是非常微弱的电压信号K型热电偶大约只有41uV/℃而且是非线性的。要是直接用ADC去采样信号太小、噪声太大冷端温漂也没法处理基本没法用。以前的做法是用仪表放大器放大、再做冷端补偿、再接ADC一套下来电路复杂调试也费劲。MAX31855把这些全集成在一起了内部有高精度放大器、冷端补偿传感器、ADC和SPI接口逻辑MCU只需要按SPI时序读取转换结果就能直接拿到热电偶温度和芯片冷端温度。用起来有点像“温度传感器数字化”的黑盒子你只要关心数据怎么读出来不用再处理模拟信号。这也是它在控温项目里被大量使用的原因成熟方案、资料多、外围电路简单核心工作量就在驱动和时序上。1.2 引脚定义与最小电路照着接就不会错MAX31855是8个引脚的小芯片SOIC-8封装引脚不多核心功能引脚就这几个引脚名称方向说明1T-输入热电偶负极2T输入热电偶正极3VCC电源供电3.0~3.6V典型3.3V4GND电源地5SO输出SPI数据输出6SCK输入SPI时钟7CS输入SPI片选低有效8NC-悬空最小外围电路非常简单但有几个点必须注意。供电必须用3.3V绝对不能接5V。MAX31855的工作电压范围是3.0~3.6V很多人第一次用顺手接到5V上芯片直接就废了。电源引脚旁边加一个0.1uF的陶瓷退耦电容靠近芯片放置有条件的再加一个1uF~10uF的电容兜底。VCC的纹波会直接影响ADC精度这个钱不能省。热电偶T和T-直接接K型热电偶注意极性。K型热电偶两根线有颜色区分一般红色为正极、蓝色或白色为负极接反了读出来的温度是反的。热电偶走线尽量短特别是靠近芯片的引脚部分避免引入噪声。SO、CS、SCK这三个信号线直接接MCU的GPIOSO是输入、CS和SCK是输出。SPI引脚不用额外加上拉电阻但如果线比较长、环境有干扰加10k上拉会更稳。1.3 输出数据格式32位输出里到底藏着什么MAX31855的数据输出格式是很多新手第一道坎。芯片每次片选拉低后输出数据可以只读16位也可以读32位。16位读法只能得到热电偶温度加故障标志32位读法额外包含冷端温度。实际项目里我基本都用32位读法一次拿全解析逻辑统一。32位数据各位含义如下表位含义bit31 ~ bit18热电偶温度14位有符号数分辨率0.25℃bit17保留位固定0bit16故障标志1表示测温故障bit15保留位固定0bit14 ~ bit4冷端温度有符号数分辨率0.0625℃bit3保留位固定0bit2SCV热电偶对VCC短路bit1SCG热电偶对GND短路bit0OC热电偶开路热电偶温度解析时要特别注意符号扩展。温度数据是14位带符号数最高位bit31是符号位但C语言里uint32_t读到后直接右移是不行的最简单的写法是先取出低14位再手动做符号扩展int16_t temp14 (int16_t)((raw 18) 0x3FFF); if (temp14 0x2000) { temp14 | 0xC000; // 如果bit13为1扩展符号到16位 } float tempC temp14 * 0.25f;如果只读16位格式解析原理一样bit15是符号位bit14~bit2是13位温度数据bit1保留bit0是故障标志。16位读取的温度分辨率同样0.25℃。故障标志位一定要查。MAX31855在热电偶开路、短路时会输出异常温度值不查错误位的话读到的数据可能是乱跳的。判错逻辑很简单if (raw 0x00010000) { if (raw 0x01) // 开路 if (raw 0x02) // 对GND短路 if (raw 0x04) // 对VCC短路 }2. 先选路硬件SPI还是软件模拟SPI2.1 硬件SPI效率高但条件苛刻硬件SPI就是直接用MCU芯片内部的SPI外设由硬件自动产生时钟、接收数据CPU只需要配置寄存器或者调用库函数。最大的优势是省CPU时间数据搬运可以用中断或者DMAMCU还能同时处理其他任务。但硬件SPI有几个问题需要预先确认。第一引脚是固定的比如STM32F103的SPI1一般是PA5、PA6、PA7这几个引脚不能随便改如果这些引脚已经被其他外设占用就冲突了。第二SPI模式必须配置正确MAX31855要求主机在SCK上升沿采样数据常用的是SPI Mode 0CPOL0CPHA0。配置错极性相位读出来的数据全是乱的。第三时钟频率不能太高MAX31855的SCK是有上限的大约4.3MHz实际使用留余量1MHz附近最保险。用硬件SPI的时候片选信号CS可以给硬件管理也可以自己用GPIO拉。MAX31855没有硬件片选自动管理那种复杂机制纯靠拉低CS启动一次读取所以我个人习惯直接用GPIO控制CS简单、可控也方便以后软件模拟SPI时复用同一套逻辑。2.2 软件模拟SPI灵活但占用CPU软件模拟SPI的原理就是手动控制GPIO电平用延时模拟出SPI时序。CS拉低SCK按节奏翻转在SCK上升沿读SO引脚电平循环32次凑满一个完整的数据帧。这种方式最大的优势是引脚随便选只要是支持输入输出的GPIO都能当SO、SCK、CS用极大提高了硬件设计的灵活性。比如SPI外设已经被Flash或者显示屏占用了或者MCU根本没有硬件SPI外设那就只能用软件模拟。缺点是会占CPU时间读取一次32位数据至少要翻转32次SCK每次还要延时几个微秒算下来一次读取可能占用几百微秒。但MAX31855转换周期是100ms级别所以几百微秒对整体性能影响微乎其微完全够用。2.3 我的选择建议不要纠结两个都要会实际项目里我的习惯是优先用硬件SPI因为简单可靠代码量少。但如果硬件SPI引脚被占用了或者后面要换MCU平台软件模拟能够快速迁移毕竟它只依赖GPIO读写函数。两种方式的代码我都在工程里保留了用一个宏切换想用哪种就编译哪种。这里顺便说一个我踩过的坑不要把软件模拟SPI的延时做得太小尤其不要为了追求速度而忽略信号稳定。MAX31855本身对时序不苛刻但MCU的GPIO翻转需要时间信号线上也有寄生电容太快的翻转会导致SO数据还没稳定就去读读回来的比萨就错了。我在STM32上做软件模拟时SCK高电平和低电平各延时1us读出来的数据已经非常稳定。如果换用ESP32或者其他主频高的MCU延时要根据实际情况调整。3. 实操用硬件SPI读取MAX31855以STM32为例3.1 接线与硬件准备我这里以STM32F103和STM32CubeIDE为例不过换其他MCU也就改一下引脚和库函数原理完全一样。接线表如下MAX31855STM32说明VCC3.3V供电GNDGND共地SOPA6SPI1_MISO输入SCKPA5SPI1_SCK输出CSPA4GPIO输出软件控制CS我用GPIO控制没有用硬件NSS这样后面切换软件模拟时引脚逻辑几乎不需要改。SO要复用为SPI的MISO功能SCK复用为SPI的SCK功能CS就用普通推挽输出。3.2 SPI参数配置模式01MHz用STM32CubeMX配置SPI1时几个关键参数如下ModeFull-Duplex Master数据传输大小8 bit时钟极性CPOLLow时钟相位CPHA1 Edge波特率分频预分频后时钟约1MHzNSSDisable片选用GPIO控制CPOLLow对应空闲时SCK为低电平CPHA1 Edge对应第一个边沿采样组合起来就是SPI Mode 0。前面说过MAX31855在SCK下降沿更新输出数据上升沿时数据稳定所以主机在上升沿采样正好是Mode 0的行为。Max31855的SCK频率最好别超过4.3MHzSTM32系统时钟72MHzSPI1挂在APB2总线上预分频64得到1.125MHz这个值就挺合适。SPI速率太高时信号质量会下降在杜邦线连接的情况下尤其明显。3.3 读取与温度换算代码CS用GPIO控制的方式一次完整读取32位数据的代码大概是这样的uint32_t MAX31855_ReadRaw(void) { uint8_t txData[4] {0, 0, 0, 0}; uint8_t rxData[4] {0, 0, 0, 0}; HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET); // CS拉低开始传输 HAL_SPI_TransmitReceive(hspi1, txData, rxData, 4, 100); // 读4个字节 32位 HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET); // CS拉高结束传输 uint32_t raw ((uint32_t)rxData[0] 24) | ((uint32_t)rxData[1] 16) | ((uint32_t)rxData[2] 8) | ((uint32_t)rxData[3]); return raw; }发送的数据全是0因为主机发送字节只是为了产生SCK时钟真正的数据是从机在SO引脚上输出的。HAL_SPI_TransmitReceive这个函数同时收发比较适合这种场景。拿到raw之后温度换算函数如下float MAX31855_GetTempC(uint32_t raw) { int16_t temp14 (int16_t)((raw 18) 0x3FFF); if (temp14 0x2000) { temp14 | 0xC000; } return temp14 * 0.25f; }注意一点只要CS拉低MAX31855就开始输出上一次转换结果的数据位数据在SCK驱动下从SO引脚一位一位送出来。所以CS拉低和SPI读取动作之间不需要做特殊延时但CS拉高后要等待足够时间让芯片开始一次新的转换。3.4 读取间隔与转换时间别读太勤MAX31855的转换速度并不快典型转换时间是100ms。也就是说每次CS拉高之后芯片需要大约100ms才能更新内部数据寄存器。如果读取间隔太小读到的仍旧是上一次转换的数据这不是芯片坏了纯粹是数据还没刷新。实际使用中我会把温度查询周期设在200ms左右留出余量。如果项目对温度变化响应要求高可以压缩到100ms但不要低于这个值。读取太频繁不仅拿不到新数据还会白白消耗CPU和总线资源。4. 实操用软件模拟SPI读取MAX31855的数据4.1 模拟SPI的核心逻辑抓住“下降沿更新上升沿读”硬件SPI之所以能工作本质上靠的是时序。软件模拟做的事情就是把时序用GPIO操作复现出来。MAX31855的SO引脚是在SCK下降沿之后输出新一位数据的数据稳定后会一直保持到下个下降沿。所以主机的读取逻辑应该是先把SCK拉低延时再把SCK拉高延时这时SO上的数据已经稳定了读取SO电平保存到变量里。重复32次就拼出了一个完整的32位数据帧。这里最关键的认知是数据是在SCK从高变低的那一刻更新的而SCK从低变高之后SO上的数据已经稳定可读。所以不要搞反采样点不要在下降沿去读不然读到的总是上一位数据。有一点容易被忽略CS拉低后必须保证SCK一开始是低电平然后再开始翻转。因为如果SCK初始为高第一个边沿就是下降沿就少了一位数据的采样机会最终读到的位数或者对齐关系会错乱。4.2 GPIO模拟代码实现引脚定义我沿用之前的PA4、PA5、PA6用宏定义封装一下方便换平台。#define MAX31855_CS_LOW() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET) #define MAX31855_CS_HIGH() HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET) #define MAX31855_SCK_LOW() HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_RESET) #define MAX31855_SCK_HIGH() HAL_GPIO_WritePin(SCK_GPIO_Port, SCK_Pin, GPIO_PIN_SET) #define MAX31855_SO_READ() HAL_GPIO_ReadPin(SO_GPIO_Port, SO_Pin) void MAX31855_SoftDelay(void) { for (volatile int i 0; i 10; i); } uint32_t MAX31855_ReadSoft(void) { uint32_t data 0; MAX31855_SCK_LOW(); MAX31855_CS_LOW(); MAX31855_SoftDelay(); for (int i 0; i 32; i) { MAX31855_SCK_LOW(); MAX31855_SoftDelay(); MAX31855_SCK_HIGH(); MAX31855_SoftDelay(); data 1; if (MAX31855_SO_READ()) { data | 1; } } MAX31855_CS_HIGH(); MAX31855_SCK_LOW(); return data; }这段代码的逻辑就是标准的SPI Mode 0空闲时SCK为低上升沿采样。每次先把SCK拉低产生下降沿触发MAX31855更新下一位数据然后拉高产生上升沿等数据稳定后读取。最后CS拉高结束传输顺便把SCK恢复成低电平。软件延时不能省具体延时多久取决于MCU主频和GPIO翻转速度。STM32F103跑72MHz的时候上面那个空循环10次大概在微秒级别实验下来没问题。如果是ESP32这种高频芯片可以把循环次数适当增大保证SCK高电平时间足够让SO稳定。4.3 软件模拟的实战细节中断和引脚复用软件模拟SPI有个容易忽略的问题读取过程中如果发生中断中断处理程序占用的时间会导致SCK波形出现毛刺或展宽。对于MAX31855这种低速芯片来说偶尔展宽SCK问题不大但如果你在读取过程中被一个很长的中断打断可能CS一直被拉低而SCK停止了整整一个周期容易造成数据错位。解决办法有两个在读取函数里临时关中断或者读取操作放在高优先级任务里执行。临时关中断最简单__disable_irq(); uint32_t raw MAX31855_ReadSoft(); __enable_irq();但关中断会影响实时性所以如果系统里还有别的中断任务我建议把读取操作安排在不影响系统稳定性的位置或者直接在状态机里周期性执行避免和关键中断冲突。另外一个细节是SO引脚要配置为输入模式。STM32的GPIO输入模式有浮空输入和上拉输入两种SO接MAX31855的推挽输出浮空输入就行。如果信号线较长可以开启内部上拉防止SO悬空时读到随机电平。5. 实战中的常见问题与排查技巧实录5.1 读回数据全是0xFFFFFFFF或者0x00000000这是所有SPI调试里最经典的问题。读回全1大概率是SO引脚一直是高电平说明MAX31855根本没有把数据驱动到SO上或者MCU和芯片之间的连接有问题。常见原因SO引脚没接对、SO没有复用成SPI功能硬件SPI模式、芯片供电不正常。读回全0一般是SO引脚一直为低可能原因包括MAX31855没工作电源没通或者芯片损坏、SO引脚被短路到地、SPI的MISO和MOSI接反。特别注意MAX31855只有SO数据输出没有数据输入引脚千万别把模块的SO接到MCU的MOSI引脚上很多人第一次在这里翻车。排查方法很简单先把CS和SCK用万用表量一下电平CS空闲是高、SCK空闲是低再用示波器看CS拉低后SO上有没有波形。没有示波器的话写一个简单的循环读SO引脚电平的代码用手碰一碰MAX31855的温度看电平有没有变化也能做一个粗判。5.2 温度值跳变明显或者显示异常大/异常负温度大幅跳变首先检查错误标志位。MAX31855的OC开路标志一旦置1温度数据会输出一个固定值看起来就是异常温度。热电偶没接好、线断了、接插件接触不良都会导致OC位置1。另一个常见原因是电源问题。MAX31855的ADC对电源噪声敏感如果VCC上纹波大转换结果就会乱跳。解决办法是加强退耦电容以及在芯片附近加一个LC滤波。我曾经在一个电机驱动板上调试只要电机一转温度数据就跳最后定位到是电源串扰加了滤波电容才解决。还有一个容易被忽略的点热电偶线本身是双绞线如果和电源线、PWM线挨得太近会感应噪声。测试的时候把热电偶线远离这些干扰源或者用屏蔽线试试。5.3 硬件SPI读不出来软件模拟却正常这个现象很常见原因基本都出在硬件SPI的配置上。首先确认SPI模式是Mode 0CPOL为低、CPHA为1 Edge。我在调试时就遇到过CPHA配错读出的数据看似有规律但温度解析出来完全不对。其次是引脚复用。STM32使用硬件SPI时要配置GPIO复用功能不是简单设成输出或输入就行。复用配错了SPI外设信号根本到不了引脚上。第三个检查点是时钟频率。把SPI预分频调大时钟降到500kHz试试。用杜邦线连接时信号质量差高速下容易读错位1MHz以下是比较稳妥的选择。如果你的项目里SO引脚被配置成了输出模式硬件SPI读回来也会是错误数据。用软件模拟时输入输出由代码控制比较容易发现用硬件SPI时MISO引脚必须由外设控制方向很多人在GPIO配置时顺手设成了推挽输出结果怎么调都不对。5.4 排查速查表按顺序来少走弯路现象优先检查项处理方法读回全0接线、供电、SO是否短路量VCC电压确认SO接线检查芯片是否发烫读回全1SO是否接对、GPIO复用是否配置确认SO连接到MISO而不是MOSI确认复用功能温度跳动大错误标志位、电源纹波读raw的bit16错误位加强退耦检查热电偶接头温度始终为固定值热电偶开路、接反查OC位更换热电偶调换T/T-硬件SPI读不了SPI模式、引脚复用、时钟频率确认Mode 0降速到1MHz以下查复用配置软件模拟读不了GPIO方向、采样点、SCK初始电平SO设输入SCK空闲设低上升沿读数据排查时我一般有个固定流程先读raw原值看最高位和错误位确认接线没问题再判断故障标志位最后才怀疑时序。很多新手上来就怀疑时序折腾半天发现是热电偶没接好这是最常见的时间浪费点。我个人在实际操作中的体会是MAX31855本身是非常稳定的一颗芯片只要供电干净、时序正确、热电偶接好读出来的数据几乎不需要滤波。真正的问题基本都出在电路细节上VCC纹波、接线过长、热电偶接触不良。另外建议工程里把硬件SPI和软件模拟SPI的代码都留着用宏切换产品阶段用硬件方式跑正式逻辑调试阶段用软件方式定位问题双保险。这个内容的后续扩展方向也很多比如多路热电偶采集、把温度数据发到上位机或者云平台、加入PID温控算法都是在这个驱动基础上叠加的核心就是先把MAX31855的读取做扎实。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询