当前位置: 首页 > news >正文

基于STM32、HAL库的MAX31865模数转换器ADC驱动程序设计

一、简介:

MAX31865是一款高精度的电阻温度检测器(RTD)至数字转换器,适用于铂电阻温度传感器(如PT100、PT1000等)。它具有以下特点:

  • 支持2线、3线或4线RTD连接

  • 15位ADC分辨率

  • 可编程数字滤波器

  • 内置RTD开路、短路检测

  • SPI接口通信

  • 工作电压:3.0V至3.6V

二、硬件接口:

MAX31865       STM32L4xx
-----------------------------
VDD    →       3.3V
GND    →       GND
CS     →       GPIO (任意GPIO引脚)
SCK    →       SPI_SCK
SDI    →       SPI_MOSI
SDO    →       SPI_MISO

三、头文件:

#ifndef __MAX31865_H
#define __MAX31865_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32l4xx_hal.h"

// MAX31865寄存器地址
#define MAX31865_CONFIG_REG      0x00
#define MAX31865_RTD_MSB_REG     0x01
#define MAX31865_RTD_LSB_REG     0x02
#define MAX31865_HIGH_FAULT_MSB  0x03
#define MAX31865_HIGH_FAULT_LSB  0x04
#define MAX31865_LOW_FAULT_MSB   0x05
#define MAX31865_LOW_FAULT_LSB   0x06
#define MAX31865_FAULT_STATUS    0x07

// 配置寄存器位定义
#define MAX31865_CONFIG_BIAS     (1 << 7)
#define MAX31865_CONFIG_MODE_AUTO (1 << 6)
#define MAX31865_CONFIG_1SHOT    (1 << 5)
#define MAX31865_CONFIG_3WIRE    (1 << 4)
#define MAX31865_CONFIG_FAULT_DETECT_NONE  (0 << 2)
#define MAX31865_CONFIG_FAULT_DETECT_AUTO  (1 << 2)
#define MAX31865_CONFIG_FAULT_DETECT_MANUAL_CYCLE (2 << 2)
#define MAX31865_CONFIG_FAULT_DETECT_MANUAL_OFFSET (3 << 2)
#define MAX31865_CONFIG_FILTER_50HZ (1 << 0)
#define MAX31865_CONFIG_FILTER_60HZ (0 << 0)

// 故障状态寄存器位定义
#define MAX31865_FAULT_HIGH_THRESH (1 << 7)
#define MAX31865_FAULT_LOW_THRESH  (1 << 6)
#define MAX31865_FAULT_REFIN       (1 << 5)
#define MAX31865_FAULT_REFIN_FORCE (1 << 4)
#define MAX31865_FAULT_RTDIN_FORCE (1 << 3)
#define MAX31865_FAULT_VOLTAGE    (1 << 2)

typedef enum {
    MAX31865_2WIRE = 0,
    MAX31865_3WIRE = 1,
    MAX31865_4WIRE = 0
} MAX31865_Wire_t;

typedef struct {
    SPI_HandleTypeDef *hspi;
    GPIO_TypeDef *cs_port;
    uint16_t cs_pin;
    MAX31865_Wire_t wire_mode;
    float rtd_nominal;
    float ref_resistor;
} MAX31865_HandleTypeDef;

// 函数声明
void MAX31865_Init(MAX31865_HandleTypeDef *hmax, SPI_HandleTypeDef *hspi, GPIO_TypeDef *cs_port, uint16_t cs_pin, MAX31865_Wire_t wire_mode, float rtd_nominal, float ref_resistor);
uint8_t MAX31865_ReadRegister(MAX31865_HandleTypeDef *hmax, uint8_t reg);
void MAX31865_WriteRegister(MAX31865_HandleTypeDef *hmax, uint8_t reg, uint8_t value);
void MAX31865_EnableBias(MAX31865_HandleTypeDef *hmax, uint8_t enable);
void MAX31865_AutoConvert(MAX31865_HandleTypeDef *hmax, uint8_t enable);
void MAX31865_ClearFault(MAX31865_HandleTypeDef *hmax);
void MAX31865_SetWires(MAX31865_HandleTypeDef *hmax, MAX31865_Wire_t wires);
uint8_t MAX31865_ReadFault(MAX31865_HandleTypeDef *hmax);
float MAX31865_ReadTemperature(MAX31865_HandleTypeDef *hmax);
float MAX31865_ReadResistance(MAX31865_HandleTypeDef *hmax);

#ifdef __cplusplus
}
#endif

#endif /* __MAX31865_H */

四、源文件:

#include "max31865.h"
#include <math.h>

// 私有函数声明
static void MAX31865_CS_Enable(MAX31865_HandleTypeDef *hmax);
static void MAX31865_CS_Disable(MAX31865_HandleTypeDef *hmax);

void MAX31865_Init(MAX31865_HandleTypeDef *hmax, SPI_HandleTypeDef *hspi, GPIO_TypeDef *cs_port, uint16_t cs_pin, MAX31865_Wire_t wire_mode, float rtd_nominal, float ref_resistor) {
    hmax->hspi = hspi;
    hmax->cs_port = cs_port;
    hmax->cs_pin = cs_pin;
    hmax->wire_mode = wire_mode;
    hmax->rtd_nominal = rtd_nominal;
    hmax->ref_resistor = ref_resistor;
    
    // 初始化CS引脚
    HAL_GPIO_WritePin(hmax->cs_port, hmax->cs_pin, GPIO_PIN_SET);
    
    // 配置MAX31865
    uint8_t config = MAX31865_CONFIG_BIAS | MAX31865_CONFIG_MODE_AUTO | MAX31865_CONFIG_FILTER_60HZ;
    
    if (hmax->wire_mode == MAX31865_3WIRE) {
        config |= MAX31865_CONFIG_3WIRE;
    }
    
    MAX31865_WriteRegister(hmax, MAX31865_CONFIG_REG, config);
}

uint8_t MAX31865_ReadRegister(MAX31865_HandleTypeDef *hmax, uint8_t reg) {
    uint8_t tx_data = reg & 0x7F; // 清除最高位表示读操作
    uint8_t rx_data = 0;
    
    MAX31865_CS_Enable(hmax);
    HAL_SPI_Transmit(hmax->hspi, &tx_data, 1, HAL_MAX_DELAY);
    HAL_SPI_Receive(hmax->hspi, &rx_data, 1, HAL_MAX_DELAY);
    MAX31865_CS_Disable(hmax);
    
    return rx_data;
}

void MAX31865_WriteRegister(MAX31865_HandleTypeDef *hmax, uint8_t reg, uint8_t value) {
    uint8_t tx_data[2];
    tx_data[0] = reg | 0x80; // 设置最高位表示写操作
    tx_data[1] = value;
    
    MAX31865_CS_Enable(hmax);
    HAL_SPI_Transmit(hmax->hspi, tx_data, 2, HAL_MAX_DELAY);
    MAX31865_CS_Disable(hmax);
}

void MAX31865_EnableBias(MAX31865_HandleTypeDef *hmax, uint8_t enable) {
    uint8_t config = MAX31865_ReadRegister(hmax, MAX31865_CONFIG_REG);
    
    if (enable) {
        config |= MAX31865_CONFIG_BIAS;
    } else {
        config &= ~MAX31865_CONFIG_BIAS;
    }
    
    MAX31865_WriteRegister(hmax, MAX31865_CONFIG_REG, config);
}

void MAX31865_AutoConvert(MAX31865_HandleTypeDef *hmax, uint8_t enable) {
    uint8_t config = MAX31865_ReadRegister(hmax, MAX31865_CONFIG_REG);
    
    if (enable) {
        config |= MAX31865_CONFIG_MODE_AUTO;
    } else {
        config &= ~MAX31865_CONFIG_MODE_AUTO;
    }
    
    MAX31865_WriteRegister(hmax, MAX31865_CONFIG_REG, config);
}

void MAX31865_ClearFault(MAX31865_HandleTypeDef *hmax) {
    uint8_t config = MAX31865_ReadRegister(hmax, MAX31865_CONFIG_REG);
    config &= ~0x0C;
    config |= MAX31865_CONFIG_FAULT_DETECT_NONE;
    MAX31865_WriteRegister(hmax, MAX31865_CONFIG_REG, config);
}

void MAX31865_SetWires(MAX31865_HandleTypeDef *hmax, MAX31865_Wire_t wires) {
    uint8_t config = MAX31865_ReadRegister(hmax, MAX31865_CONFIG_REG);
    
    if (wires == MAX31865_3WIRE) {
        config |= MAX31865_CONFIG_3WIRE;
    } else {
        config &= ~MAX31865_CONFIG_3WIRE;
    }
    
    MAX31865_WriteRegister(hmax, MAX31865_CONFIG_REG, config);
    hmax->wire_mode = wires;
}

uint8_t MAX31865_ReadFault(MAX31865_HandleTypeDef *hmax) {
    return MAX31865_ReadRegister(hmax, MAX31865_FAULT_STATUS);
}

float MAX31865_ReadResistance(MAX31865_HandleTypeDef *hmax) {
    MAX31865_ClearFault(hmax);
    MAX31865_EnableBias(hmax, 1);
    HAL_Delay(10);
    
    uint8_t config = MAX31865_ReadRegister(hmax, MAX31865_CONFIG_REG);
    config |= MAX31865_CONFIG_1SHOT;
    MAX31865_WriteRegister(hmax, MAX31865_CONFIG_REG, config);
    
    HAL_Delay(65);
    
    uint8_t msb = MAX31865_ReadRegister(hmax, MAX31865_RTD_MSB_REG);
    uint8_t lsb = MAX31865_ReadRegister(hmax, MAX31865_RTD_LSB_REG);
    
    uint16_t rtd = ((msb << 8) | lsb) >> 1;
    float resistance = ((float)rtd * hmax->ref_resistor) / 32768.0f;
    
    return resistance;
}

float MAX31865_ReadTemperature(MAX31865_HandleTypeDef *hmax) {
    float resistance = MAX31865_ReadResistance(hmax);
    
    // 使用Callendar-Van Dusen方程计算温度
    float temp;
    float z1, z2, z3, z4;
    float r = resistance / hmax->rtd_nominal;
    
    if (r < 1.0) { // 低于0°C
        temp = -242.02 + (2.2228 * r);
        temp += 2.5859 * pow(r, 2);
        temp -= 0.6393 * pow(r, 3);
        temp -= 0.1299 * pow(r, 4);
    } else { // 高于0°C
        z1 = -3.9083e-3;
        z2 = 1.758480889e-5;
        z3 = -2.31e-8;
        z4 = -1.155e-6;
        
        temp = (z1 + sqrt(z2 + (z3 * r))) / z4;
    }
    
    return temp;
}

static void MAX31865_CS_Enable(MAX31865_HandleTypeDef *hmax) {
    HAL_GPIO_WritePin(hmax->cs_port, hmax->cs_pin, GPIO_PIN_RESET);
}

static void MAX31865_CS_Disable(MAX31865_HandleTypeDef *hmax) {
    HAL_GPIO_WritePin(hmax->cs_port, hmax->cs_pin, GPIO_PIN_SET);
}

五、应用:

#include "main.h"
#include "max31865.h"

SPI_HandleTypeDef hspi1;
MAX31865_HandleTypeDef hmax31865;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI1_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SPI1_Init();
    
    // 初始化MAX31865
    // 参数: PT100传感器, 3线制, 参考电阻430Ω
    MAX31865_Init(&hmax31865, &hspi1, GPIOA, GPIO_PIN_4, MAX31865_3WIRE, 100.0f, 430.0f);
    
    while (1) {
        float temperature = MAX31865_ReadTemperature(&hmax31865);
        float resistance = MAX31865_ReadResistance(&hmax31865);
        
        printf("Temperature: %.2f °C, Resistance: %.2f Ω\n", temperature, resistance);
        
        HAL_Delay(1000);
    }
}

// SPI1初始化函数
static void MX_SPI1_Init(void) {
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi1.Init.NSS = SPI_NSS_SOFT;
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 10;
    if (HAL_SPI_Init(&hspi1) != HAL_OK) {
        Error_Handler();
    }
}

// GPIO初始化函数
static void MX_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    // SPI1 CS引脚配置
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    
    // SPI1引脚配置
    GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

相关文章:

  • 嵌入式 C 语言面试核心知识点全面解析:基础语法、运算符与实战技巧
  • c++之网络编程
  • 立创商城、云汉芯城、亿配芯城均启用DeepSeek AI 大模型赋能电子元器件采购平台
  • 第十四届蓝桥杯刷题——day20
  • [官方IP] AXI Memory Init IP
  • 【音视频】AVIO输入模式
  • UnityEditor - 调用编辑器菜单功能
  • 汽车零配件供应商如何通过EDI与主机厂生产采购流程结合
  • Spark读取Apollo配置
  • 在html中如何创建vue自定义组件(以自定义文件上传组件为例,vue2+elementUI)
  • el-upload 上传逻辑和ui解耦,上传七牛
  • Vue里面elementUi-aside 和el-main不垂直排列
  • ClickHouse 中`MergeTree` 和 `ReplicatedMergeTree`表引擎区别
  • 深入理解机器学习:人工智能的核心驱动力
  • OSPF网络协议
  • 【XR手柄交互】Unity 中使用 InputActions 实现手柄控制详解(基于 OpenXR + Unity新输入系统(Input Actions))
  • Windows环境下常用网络命令使用
  • SIEMENS PLC程序解读 ST 语言 车型识别
  • C++面试复习日记(8)2025.4.25,malloc,free和new,delete的区别
  • HDRnet——双边滤波和仿射变换的摇身一变
  • 从“高阶智驾”到“辅助驾驶”,上海车展上的“智驾”宣发变调
  • 文庙印象:一周城市生活
  • 航天科技集团质量技术部部长严泽想升任集团副总经理
  • 我国首次实现地月距离尺度的卫星激光测距
  • 上海:全面建设重复使用火箭创新高地、低成本商业卫星规模制造高地
  • 我国民营经济首季运行向新向好,对国民经济发展形成有力支撑