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

基于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);
}

http://www.xdnf.cn/news/2083.html

相关文章:

  • 消息队列mq在Mlivus Cloud向量数据库中的关键配置与最佳实践
  • C++智能指针概念理解的面试题
  • window.location.href的用法
  • 基于 Netmiko 的网络设备自动化操作
  • 《逐梦九天:中国航天编年史》
  • QT文本框(QTextEdit)设置内容只可复制粘贴
  • C++:继承机制详解
  • Cursor 配置 MCP Tool
  • 写在后面的话
  • yolo常用操作(长话短说)热力图,特征图,结构图,训练,测试,预测
  • 打开Qt应用程序以控制台
  • Linux基础篇、第四章_02磁盘及分区管理fdisk 和 gdisk
  • 厚铜PCB打样全流程解析:从文件审核到可靠性测试的关键步骤
  • Python的库
  • Hbase集群管理与实践
  • C语言——字串处理
  • 什么是快应用
  • STM32 I2C总线通信协议
  • 遥感金融风险监管:技术革新与实践探索
  • Java—— 常见API介绍 第五期
  • cursor 提示词和规则
  • 基于SpringBoot+Vue实现停车场管理系统
  • sync.Cond条件变量:使用场景与范例
  • Centos 7 ssh连接速度慢(耗时秒+)
  • LWIP中两种重要的数据结构pbuf和pcb详细介绍
  • 【大模型学习】Qwen-2.5-VL制作gradio前端demo页面
  • (九)深入了解AVFoundation-采集:拍照 摄像头切换、拍照参数和照片数据EXIF 信息
  • Pandas 数据处理:长格式到宽格式的全面指南
  • 文章记单词 | 第41篇(六级)
  • Vue3文件上传组件实战:打造高效的Element Plus上传解决方案,可以对文件进行删除,查看,下载功能。