ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

MAX6675/MAX31855驱动代码详解:SPI数据解析与K型热电偶测温避坑指南

MAX6675/MAX31855驱动代码详解:SPI数据解析与K型热电偶测温避坑指南 简介面向嵌入式软硬件开发者和电子工程学习者这份C语言驱动代码围绕MAX6675与MAX31855两款热电偶驱动芯片解决K型及多种热电偶的温度采集与驱动实现问题。压缩包内仅1个C文件整体大小592B集中展示了SPI与单线接口的初始化、通信读写函数、温度数据解析以及错误检测等核心环节。目前已有3228人学习下载。通过研读这份精简源码可以快速掌握MAX6675的SPI读取流程与MAX31855的单线通信配置要点理解芯片内部冷端补偿和A/D转换后输出的14位温度数据格式并可直接移植到自己的项目中减少查阅数据手册和反复调试的时间。资源虽小但覆盖了从接口配置到温度获取的完整通路对需要快速上手热电偶测温方案的开发者是一份小巧实用的参考范例。 去年接了个小项目要给一台小机器加装温度监测选型时图省事直接上了MAX6675加K型热电偶的组合——毕竟网上例程铺天盖地模块几块钱一个拿来就能用。结果板子打样回来一测温度读数在正常值和明显偏差值之间来回跳排查了整整一个下午最后发现根子出在SPI读取时序和杜邦线的干扰上。后来把方案换成MAX31855顺手把两个芯片的驱动整合成了一份通用代码。这篇就把MAX6675和MAX31855的驱动代码、数据位解析思路以及数据手册里不会写的实际坑都讲透。适用对象是正在做K型热电偶测温的嵌入式开发者不管你是刚接触SPI还是已经调过几块板子都能从里面拿点东西走。1. 选型决定驱动写法MAX6675与MAX31855的核心差异很多人看到这两颗芯片长得差不多、接法也差不多就想当然地认为驱动可以完全通用。实际上它们的数据格式和功能边界有明显区别驱动代码的解析逻辑也必须跟着变。1.1 数据格式和测量范围先看最关键的温度数据位宽。MAX6675输出12位无符号温度数据分辨率为0.25°C/LSB测量范围只有0°C到1023.75°C。注意这个“无符号”很关键它天生不支持负温度环境温度低于0°C时内部冷端补偿会失效读数直接不准。MAX31855则是14位带符号温度数据同样0.25°C/LSB理论上讲可以覆盖-2048°C到2047.75°C实际范围受限于热电偶类型以K型为例大约是-200°C到1350°C。如果你要测零下温度或者需要更宽的量程MAX31855是必须的选择。另一个直接影响驱动代码的点是输出数据的宽度。MAX6675每次通过SPI读回16位高12位是有效温度低4位里有状态位MAX31855每次读回32位高位是温度中间是冷端温度低位是故障标志。这就意味着驱动里读数据的字节数、拼接方式、移位处理全都不一样。所以写驱动之前先确认自己用的是哪颗芯片别拿着MAX6675的例程去读MAX31855读回来的数据用肉眼根本看不出规律。1.2 热电偶类型、故障检测与硬件兼容性MAX6675只支持K型热电偶MAX31855则有多个子型号分别对应K、J、N、T、S、R、E、B型热电偶买料的时候要根据后缀选对型号比如MAX31855K就是K型专用版。这种设计上的差异也解释了为什么MAX31855的驱动要多做一层热电偶类型判断而MAX6675完全不需要。故障检测方面两者差距更明显。MAX6675只有一路热电偶开路检测位短路、反接都检测不出来MAX31855把低3位做成了故障标志分别对应开路、短路到VCC、短路到GND。实际生产中这个差别很重要——热电偶的偶丝很细弯折几次就可能内部断开MAX6675虽然能报开路但遇到短路故障时会给出一个看起来正常的错误温度容易把设备带跑偏。硬件引脚上SO-8封装的两颗芯片在SO、CS、SCK这三个信号脚上是兼容的这也是很多产品能直接替换的原因。但驱动不能直接换因为数据位定义和读取长度都变了。对比项MAX6675MAX31855适用热电偶仅K型K、J、N、T、S、R、E、B型温度分辨率12位0.25°C/LSB14位0.25°C/LSB测量范围0~1023.75°C视型号K型约-200~1350°C冷端补偿内部补偿值不可读内部补偿冷端温度可读出故障检测仅开路开路、短路到VCC、短路到GNDSPI读取长度16位32位2. SPI读取链路拆解时序、字节序和位定义驱动代码的核心是SPI读取和位解析。这部分搞清楚了代码本身其实就是简单的移位运算。2.1 时钟模式与片选时序MAX6675和MAX31855都支持SPI Mode 0即CPOL0、CPHA0。实测下来这个模式最稳我也见过有人用Mode 1也能读但既然数据手册推荐Mode 0就没有必要在时序上冒险。片选的控制比SPI模式更容易被忽略。读数据前把CS拉低然后开始发时钟读完立刻拉高。CS拉低到第一个SCK上升沿之间要留一点余量MAX6675规格是至少100ns用STM32的GPIO翻转速度一般没问题但如果用的是软件SPIGPIO翻转加上指令周期通常也够。需要注意的是两次读取之间必须间隔大于内部转换周期MAX6675和MAX31855的典型转换时间都是100ms左右。如果你读的频率太快读到的实际上是上一次转换的结果表现就是温度值好几个周期不变然后忽然跳一下。字节序方面两颗芯片都是MSB先出。配置SPI时务必确认是MSB First如果配置成了LSB First读回来的字节顺序会反过来温度数据会完全乱套。这个坑我踩过一次排查了很久才发现是CubeMX默认设置被改掉了。2.2 MAX6675的16位数据解析MAX6675读回来的是16位数据按bit排列如下bit15恒为0因为是单极性测量不支持负温bit14~bit312位温度值0.25°C/LSBbit2热电偶开路标志1表示开路bit1恒为0bit0恒为0解析逻辑就是先检查bit2如果为1直接报故障不需要解析温度。如果正常把原始数据右移3位再取低12位然后乘0.25就得到实际温度。由于bit15恒为0右移之后不会污染温度数据所以代码里直接(raw 3) 0x0FFF就行。2.3 MAX31855的32位数据解析与冷端温度MAX31855读回来的是32位数据位定义如下bit31符号位bit30~bit1814位温度值二进制补码0.25°C/LSBbit17~bit412位冷端温度二进制补码0.25°C/LSBbit3保留位恒为0bit2热电偶短路到VCCbit1热电偶短路到GNDbit0热电偶开路温度解析时先把(raw 18) 0x3FFF取到低14位然后做符号扩展。二进制补码的第13位就是符号位判断0x2000是否置位如果置位就把它扩展成16位有符号数。冷端温度同理取(raw 4) 0x0FFF再检查第11位做符号扩展。最后都乘0.25。这里特别提醒一句当低3位故障标志的任意一位为1时整个32位数据里的温度字段和冷端字段都无效不能拿来计算。很多人没注意这一点在开路状态下读到一个看似正常的温度值还以为设备是好的。3. 一套驱动吃两代芯片可复用的HAL库实现既然两颗芯片的物理连接兼容、读取时序一致只是数据格式不同那驱动就可以设计成一套代码、两个解析分支。这样做的好处是换料时不用改上层调用逻辑只需要改一个枚举值。3.1 抽象设备句柄与API设计我用一个结构体把SPI句柄、片选引脚和芯片类型包起来上层调用只跟这个结构体打交道。这样项目里即使是多路测温也可以定义多个设备实例互不干扰。typedef enum { TC_CHIP_MAX6675 0, TC_CHIP_MAX31855 } tc_chip_t; typedef struct { SPI_HandleTypeDef *hspi; GPIO_TypeDef *cs_port; uint16_t cs_pin; tc_chip_t chip; } tc_dev_t; typedef enum { TC_OK 0, TC_ERR_OPEN, TC_ERR_SHORT_VCC, TC_ERR_SHORT_GND } tc_fault_t; typedef struct { float temperature; // 热电偶测量端温度摄氏度 float cold_junction; // 冷端温度仅MAX31855有效 tc_fault_t fault; // 故障码 uint8_t raw_valid; // 数据有效性1有效0故障 } tc_sample_t; tc_sample_t tc_read_sample(tc_dev_t *dev);API只有一个tc_read_sample返回一个结构体里面包含温度值、冷端值和故障码。这样调用方拿到结果后不用关心底层是哪颗芯片统一判断raw_valid和fault就行。3.2 底层SPI读取与数据拼接底层的SPI读取MAX6675读2字节MAX31855读4字节。这里统一用8位模式收发收到后手动拼成16位或32位。不推荐直接配置成16位或32位数据长度因为有些MCU对非对齐访问和DMA有额外限制8位模式最稳。static uint16_t tc_spi_read16(tc_dev_t *dev) { uint8_t tx[2] {0x00, 0x00}; uint8_t rx[2] {0x00, 0x00}; HAL_GPIO_WritePin(dev-cs_port, dev-cs_pin, GPIO_PIN_RESET); HAL_SPI_TransmitReceive(dev-hspi, tx, rx, 2, HAL_MAX_DELAY); HAL_GPIO_WritePin(dev-cs_port, dev-cs_pin, GPIO_PIN_SET); return ((uint16_t)rx[0] 8) | rx[1]; } static uint32_t tc_spi_read32(tc_dev_t *dev) { uint8_t tx[4] {0x00, 0x00, 0x00, 0x00}; uint8_t rx[4] {0x00, 0x00, 0x00, p a hrefhttps://download.csdn.net/download/u010210711/12484642 stylecolor:#ec7500;font-size:14px; 本文还有配套的精品资源点击获取 /a img altmenu-r.4af5f7ec.gif srchttps://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif stylewidth:16px;margin-left:4px;vertical-align:text-bottom;cursor:text; /p
返回列表