一、系统概述

PT100是一种铂热电阻温度传感器,其阻值随温度变化(0℃时100Ω,温度系数≈0.385Ω/℃),广泛用于工业测温。MAX31865是专用于RTD(如PT100/PT1000)的ADC转换芯片,通过SPI接口输出数字量,支持三线制/四线制连接(抵消引线电阻),具备故障检测功能。

本方案基于STM32F103C8T6MAX31865,通过SPI通信读取PT100的电阻值,经软件计算转换为温度,实现高精度温度测量。

二、系统架构

三线制

SPI

UART

GPIO

内部恒流源

PT100传感器

MAX31865

STM32F103

PC/显示终端

故障指示LED

  • 核心功能: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工作流程
  1. 配置寄存器:设置三线制、转换模式、故障检测阈值。

  2. 启动转换:MAX31865内部恒流源(1mA)激励PT100,测量RTD与参考电阻(RREF=400Ω)的分压。

  3. 读取数据:通过SPI读取RTD的16位数字量(高15位有效,低1位故障标志)。

  4. 故障检测:通过故障状态寄存器判断PT100开路/短路、过压等。

(2)温度计算
  • RTD电阻值RRTD=RREF×(RTDCODE)215−1R_{RTD}=\frac{R_{REF}×(RTD_{CODE})}{2^{15}−1}RRTD=2151RREF×(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×103,B=5.775×107)

    或线性近似(0-100℃):t=R(t)−1000.385t=\frac{R(t)−100}{0.385}t=0.385R(t)100R0=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温度的高精度测量,核心步骤包括:

  1. 硬件连接:SPI接口+三线制PT100,抵消引线电阻;

  2. 驱动开发:MAX31865寄存器配置、SPI数据读写、故障检测;

  3. 温度计算:RTD数字量→电阻值→温度(线性/精确公式)。

系统可扩展为多路PT100巡检(通过多片MAX31865+SPI多从机)或温度控制系统(结合PID算法控制加热/冷却设备),适用于工业炉温控、冷链监测、医疗设备等领域。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐