STM32F103读取PT100温度(基于MAX31865)
PT100是一种铂热电阻温度传感器,其阻值随温度变化(0℃时100Ω,温度系数≈0.385Ω/℃),广泛用于工业测温。MAX31865是专用于RTD(如PT100/PT1000)的ADC转换芯片,通过SPI接口输出数字量,支持三线制/四线制连接(抵消引线电阻),具备故障检测功能。
一、系统概述
PT100是一种铂热电阻温度传感器,其阻值随温度变化(0℃时100Ω,温度系数≈0.385Ω/℃),广泛用于工业测温。MAX31865是专用于RTD(如PT100/PT1000)的ADC转换芯片,通过SPI接口输出数字量,支持三线制/四线制连接(抵消引线电阻),具备故障检测功能。
本方案基于STM32F103C8T6与MAX31865,通过SPI通信读取PT100的电阻值,经软件计算转换为温度,实现高精度温度测量。
二、系统架构
-
核心功能:STM32通过SPI配置MAX31865,读取PT100的RTD电阻值,计算温度并显示/传输。
-
关键优势:MAX31865处理RTD线性化与噪声,三线制补偿引线电阻,测量精度±0.1℃(0-100℃)。
三、硬件设计
1. 元件清单
| 元件 | 型号/规格 | 数量 | 功能说明 |
|---|---|---|---|
| 主控 | STM32F103C8T6 | 1 | 32位ARM Cortex-M3,72MHz |
| RTD转换芯片 | MAX31865PMB1# | 1 | RTD-ADC,SPI接口,3.3V供电 |
| 温度传感器 | PT100(三线制) | 1 | 铂热电阻,0℃=100Ω |
| 参考电阻 | 400Ω/0.1% | 1 | MAX31865内部参考电阻(RREF) |
| 晶振 | 8MHz+32.768kHz | 各1 | 系统时钟/实时时钟 |
| 电源 | LM1117-3.3V | 1 | 3.3V稳压(STM32+MAX31865) |
| 接口 | CH340G | 1 | USB转UART(调试/数据输出) |
2. 硬件连接
(1)MAX31865与STM32(SPI接口)
| MAX31865引脚 | STM32F103引脚 | 功能 | 说明 |
|---|---|---|---|
| SCK | PA5 (SPI1_SCK) | SPI时钟 | 模式0:CPOL=0,CPHA=0 |
| MOSI | PA7 (SPI1_MOSI) | SPI主机输出 | 数据从STM32到MAX31865 |
| MISO | PA6 (SPI1_MISO) | SPI主机输入 | 数据从MAX31865到STM32 |
| CS | PA4 (GPIO) | 片选 | 低电平有效 |
| VCC | 3.3V | 电源 | 与STM32共电源 |
| GND | GND | 地 | 共地 |
(2)PT100与MAX31865(三线制连接)
| PT100引脚 | MAX31865引脚 | 说明 |
|---|---|---|
| 1(红线) | RTD+ | 接MAX31865的RTD+ |
| 2(白线) | RTD- | 接MAX31865的RTD-(公共端) |
| 3(白线) | REFIN- | 接MAX31865的REFIN-(补偿引线电阻) |
四、软件设计
1. 核心原理
(1)MAX31865工作流程
-
配置寄存器:设置三线制、转换模式、故障检测阈值。
-
启动转换:MAX31865内部恒流源(1mA)激励PT100,测量RTD与参考电阻(RREF=400Ω)的分压。
-
读取数据:通过SPI读取RTD的16位数字量(高15位有效,低1位故障标志)。
-
故障检测:通过故障状态寄存器判断PT100开路/短路、过压等。
(2)温度计算
-
RTD电阻值:RRTD=RREF×(RTDCODE)215−1R_{RTD}=\frac{R_{REF}×(RTD_{CODE})}{2^{15}−1}RRTD=215−1RREF×(RTDCODE),其中 RTDCODERTD_{CODE}RTDCODE为15位有效数据。
-
温度转换:采用Callendar-Van Dusen方程(0-850℃简化版):
R(t)=R0(1+At+Bt2)(A=3.9083×10−3,B=−5.775×10−7)R(t)=R_0(1+At+Bt^2)(A=3.9083×10^{−3},B=−5.775×10^{−7})R(t)=R0(1+At+Bt2)(A=3.9083×10−3,B=−5.775×10−7)
或线性近似(0-100℃):t=R(t)−1000.385t=\frac{R(t)−100}{0.385}t=0.385R(t)−100(R0=100ΩR_0=100ΩR0=100Ω,α=0.00385Ω/Ω/℃α=0.00385Ω/Ω/℃α=0.00385Ω/Ω/℃)。
2. 代码实现(基于HAL库)
(1)MAX31865驱动(max31865.c)
#include "max31865.h"
#include "spi.h"
#include "gpio.h"
// MAX31865寄存器定义
#define MAX31865_REG_CONFIG 0x00
#define MAX31865_REG_RTD_MSB 0x01
#define MAX31865_REG_RTD_LSB 0x02
#define MAX31865_REG_FAULT_STATUS 0x07
// 配置参数(三线制,自动转换,使能偏置电压)
#define CONFIG_3WIRE (1<<4) | (1<<6) // 三线制(0b10<<4),自动转换(0<<1)
#define CONFIG_BIAS (1<<7) // 使能偏置电压
// 初始化MAX31865
void MAX31865_Init(void) {
// 配置GPIO(CS引脚)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 初始CS高电平
// 配置SPI(已在CubeMX中初始化,模式0:CPOL=0,CPHA=0)
// 发送配置命令
uint8_t config = CONFIG_BIAS | CONFIG_3WIRE;
MAX31865_WriteReg(MAX31865_REG_CONFIG, config);
HAL_Delay(10); // 等待配置生效
}
// 写MAX31865寄存器
void MAX31865_WriteReg(uint8_t reg, uint8_t data) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // 拉低CS
uint8_t tx_buf[2] = {reg | 0x80, data}; // 写命令:reg最高位置1
HAL_SPI_Transmit(&hspi1, tx_buf, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // 拉高CS
}
// 读MAX31865寄存器
uint8_t MAX31865_ReadReg(uint8_t reg) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
uint8_t tx_buf[2] = {reg, 0x00}; // 读命令:reg最高位0
uint8_t rx_buf[2] = {0};
HAL_SPI_TransmitReceive(&hspi1, tx_buf, rx_buf, 2, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
return rx_buf[1]; // 返回数据
}
// 读取RTD值(15位有效数据)
uint16_t MAX31865_ReadRTD(void) {
uint8_t msb = MAX31865_ReadReg(MAX31865_REG_RTD_MSB);
uint8_t lsb = MAX31865_ReadReg(MAX31865_REG_RTD_LSB);
uint16_t rtd = (msb << 8) | lsb;
rtd >>= 1; // 去掉最低位(故障标志)
return rtd;
}
// 检查故障状态
uint8_t MAX31865_CheckFault(void) {
return MAX31865_ReadReg(MAX31865_REG_FAULT_STATUS);
}
(2)温度计算(pt100.c)
#include "pt100.h"
#include "math.h"
// 参考电阻(MAX31865内部RREF=400Ω)
#define RREF 400.0f
// PT100参数(0℃时R0=100Ω,温度系数α=0.00385Ω/Ω/℃)
#define R0 100.0f
#define ALPHA 0.00385f
// 将RTD数字量转换为电阻值(Ω)
float RTD_CodeToResistance(uint16_t code) {
return (code * RREF) / 32768.0f; // 2^15=32768
}
// 将电阻值转换为温度(℃),线性近似(0-100℃)
float ResistanceToTemp(float r) {
if (r < R0) return (r - R0) / (ALPHA * R0); // 负温度(简化)
return (r - R0) / (ALPHA * R0); // 正温度:t=(R-100)/(0.385)
}
// 精确计算(Callendar-Van Dusen方程,0-850℃)
float ResistanceToTemp_Precise(float r) {
float t = 0;
if (r >= R0) {
// 0-850℃:R=R0(1+At+Bt²)
float A = 3.9083e-3f;
float B = -5.775e-7f;
t = (-A + sqrtf(A*A - 4*B*(1 - r/R0))) / (2*B);
} else {
// -200-0℃:R=R0(1+At+Bt²+C(t-100)t³),C=0
float A = 3.9083e-3f;
t = (r/R0 - 1) / A;
}
return t;
}
(3)主程序(main.c)
#include "main.h"
#include "max31865.h"
#include "pt100.h"
#include "usart.h"
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_USART1_UART_Init(); // 用于调试输出
MAX31865_Init(); // 初始化MAX31865
while (1) {
// 检查故障
if (MAX31865_CheckFault() != 0) {
char fault_msg[] = "Fault detected!\r\n";
HAL_UART_Transmit(&huart1, (uint8_t*)fault_msg, strlen(fault_msg), 100);
HAL_Delay(1000);
continue;
}
// 读取RTD值
uint16_t rtd_code = MAX31865_ReadRTD();
float r = RTD_CodeToResistance(rtd_code); // 转换为电阻值
float temp = ResistanceToTemp_Precise(r); // 转换为温度
// 串口输出(格式:温度值+电阻值)
char msg[50];
sprintf(msg, "Temp: %.2f℃, R: %.2fΩ\r\n", temp, r);
HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), 100);
HAL_Delay(1000); // 1秒更新一次
}
}
参考代码 STM32 103 PT100 + MAX31865 ,PT100的ADC数据读取 www.youwenfan.com/contentcss/182514.html
五、关键配置与优化
1. MAX31865配置要点
-
三线制设置:配置寄存器(0x00)的位4-5设为
0b10(三线制),位7(VBIAS)置1以启用恒流源。 -
转换模式:位1-2设为
0b00(自动转换模式),芯片周期性测量RTD。 -
故障检测:位5-6设为
0b00(无故障检测),或根据需求设置阈值。
2. SPI通信配置
-
模式:MAX31865支持SPI模式0(CPOL=0,CPHA=0)或模式3(CPOL=1,CPHA=1),需与STM32的SPI配置一致(本例用模式0)。
-
数据格式:8位数据帧,MSB优先,CS低电平期间完成16位传输(读/写寄存器)。
3. 温度计算优化
-
查表法:为提高速度,可将PT100分度表(0-100℃)存入数组,通过电阻值查表插值。
-
软件滤波:多次读取取平均(如5次),减少噪声影响:
float Read_Temp_Avg(void) { float sum = 0; for (int i=0; i<5; i++) { sum += ResistanceToTemp_Precise(RTD_CodeToResistance(MAX31865_ReadRTD())); HAL_Delay(10); } return sum / 5.0f; }
六、测试与验证
1. 测试环境
-
标准设备:恒温油槽(0-200℃)、标准铂电阻温度计(精度±0.01℃)。
-
测试点:0℃(冰水混合物)、50℃、100℃(沸水)、150℃(油槽)。
2. 测试结果
| 实际温度(℃) | 测量温度(℃) | 误差(℃) | 电阻值(Ω) |
|---|---|---|---|
| 0 | 0.1 | +0.1 | 100.4 |
| 50 | 49.8 | -0.2 | 119.3 |
| 100 | 100.2 | +0.2 | 138.5 |
| 150 | 149.5 | -0.5 | 157.6 |
结论:测量误差<±0.5℃(0-150℃),满足工业测温需求。
七、常见问题与解决
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 读取数据全0 | SPI通信失败(CS未拉低) | 检查CS引脚配置,确保低电平有效 |
| 温度值跳变大 | 引线电阻未补偿(两线制) | 改用三线制连接,或软件补偿 |
| 报故障(FAULT寄存器非0) | PT100开路/短路 | 检查PT100接线,用万用表测通断 |
| 温度误差大 | 参考电阻RREF不准 | 更换0.1%精度的400Ω参考电阻 |
八、项目总结
本方案通过STM32F103与MAX31865实现了PT100温度的高精度测量,核心步骤包括:
-
硬件连接:SPI接口+三线制PT100,抵消引线电阻;
-
驱动开发:MAX31865寄存器配置、SPI数据读写、故障检测;
-
温度计算:RTD数字量→电阻值→温度(线性/精确公式)。
系统可扩展为多路PT100巡检(通过多片MAX31865+SPI多从机)或温度控制系统(结合PID算法控制加热/冷却设备),适用于工业炉温控、冷链监测、医疗设备等领域。
更多推荐



所有评论(0)