一、MAX31865
高度集成降低系统成本、简化设计并缩短设计周期
- 简便的RTD铂电阻至数字转换器
- 支持100Ω至1kΩ (0°C时)铂电阻RTD (PT100至PT1000)
- 兼容2线、3线和4线传感器连接
- SPI兼容接口
高精度设计方便满足误差预算
- 15位ADC分辨率;标称温度分辨率为0.03125°C (随RTD的非线性变化)
- 整个工作条件下,总精度保持在最高0.5°C (0.05%满量程)
- 全差分VREF输入
- 转换时间:21ms (最大值)
集成故障检测提高系统可靠性
- ±45V输入保护
- 故障检测(RTD开路、RTD短路到量程范围以外的电压或RTD元件短路)
1.重要寄存器
Configuration Register (读00h,写80h)
BIAS (D7)
当没有执行转换时,可以禁用 VBIAS 以降低功耗。将 1 写入此位以在开始单个 (1-Shot) 转换之前启用 VBIAS。当选择自动(连续)转换模式时,VBIAS 保持连续开启。
Conversion Mode (D6)
将 1 写入该位以选择自动转换模式,在该模式下,转换以 50/60Hz 的速率连续进行。将 0 写入该位以退出自动转换模式并进入 “Normally Off” 模式。可以从此模式启动 1-shot 转换。
1-Shot (D5)
当转换模式设置为 “Normally Off” 时,将 1 写入该位以开始转换。这会导致发生单个电阻转换。当 CS 向该位写入 1 后变为高电平时,将触发转换。请注意,如果执行多字节写入,则当 CS 在事务结束时变为高电平时,将触发转换。如果 VBIAS 导通 (由配置寄存器选择),则当 CS 变为高电平并开始转换时,对 RTD 电压进行采样。注意,如果 VBIAS 关闭(以减少转换之间的电源电流),则 RTDIN 输入端的任何滤波电容都需要充电,然后才能执行精确的转换。因此,请启用 VBIAS 并等待输入 RC 网络的至少 10.5 个时间常数加上额外的 1 毫秒,然后再开始转换。请注意,在 60Hz 滤波器模式下,单次转换大约需要 52 毫秒,在 50Hz 滤波器模式下需要大约 62.5 毫秒才能完成。1-Shot 是一个自清除位。
3-Wire (D4)
当使用 3 线 RTD 连接时,将 1 写入此位。在这种模式下,从 (RTDIN+ - RTDIN-) 中减去 FORCE+ 和 RTDIN+ 之间的电压,以补偿因使用 FORCE 和 RTDIN- 连接使用单线引起的 IR 误差。当使用 2 线或 4 线连接时,将 0 写入此位。
Fault Detection Cycle (D3:D2)
主站启动的故障检测周期有两种操作模式,手动和自动模式定时。如果外部 RTD 接口电路包括一个时间常数大于 100Fs 的输入滤波器,则应在手动模式操作中控制故障检测周期时序。故障检测周期通过进行以下电压比较并在 Fault Status Register 中设置相关位来检查三个故障:
1) REFIN- 处的电压是否大于 85% x VBIAS?(故障状态寄存器位 D5)
2)当 FORCE- 输入开关打开时,REFIN- 处的电压是否小于 85% x VBIAS?(故障状态寄存器位 D4)
3)当 FORCE- 输入开关打开时,RTDIN- 的电压是否小于 85% x VBIAS?(故障状态寄存器位 D3)

Fault Status Clear (D1)
向该位写入 1,同时向位 D5、D3 和 D2 写入 0,以将故障状态寄存器中的所有故障状态位 (D[7:2]) 返回为 0。请注意,如果过压/欠压故障仍然存在,则故障寄存器中的位 D2 和 RTD LSB 寄存器中的位 D0 可以在复位后立即再次设置。故障状态清除位 D1,自清除为 0。
50/60Hz (D0)
此位选择噪声抑制滤波器的陷波频率。将 0 写入该位以拒绝 60Hz 及其谐波;将 1 写入此位以拒绝 50Hz 及其谐波。注意:在自动转换模式下,请勿更改陷波频率。
RTD Resistance Registers (01h-02h)
两个 8 位寄存器 RTD MSB 和 RTD LSB 包含 RTD 电阻数据。数据格式如表 4 所示。数据格式就是 RTD 电阻与基准电阻的 15 位比。RTD LSB寄存器的D0是一个Fault位,指示是否检测到任何RTD故障。
Fault Status Register (07h)
Fault Status 寄存器锁存任何检测到的 fault bit;将 1 写入 Configuration Register 中的 Fault Status Clear 位,将所有 Fault Status 位返回为 0。
2.SPI时序
CS信号低电平有效,CLK信号空闲时为高电平(根据手册18页,空闲时低电平也可),第二个数据沿锁定数据。

3.电气特性
二、驱动
代码
bsp_max31865.h1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| #ifndef __BSP_31865_H #define __BSP_31865_H #include "stm32f10x.h"
#define MAX31865_INITVAL 0xC1 #define PT1000_Resistance_Ref 4020
typedef struct _MAX31865_ { float temp_out; uint8_t status; } MAX31865;
#define M_SPI SPI2 #define M_SPI_APBxClock_FUN RCC_APB1PeriphClockCmd #define M_SPI_CLK RCC_APB1Periph_SPI2
#define M_SPI_IRQ SPI2_IRQn #define M_SPI_IRQHandler SPI2_IRQHandler
#define M_SPI_CS_APBxClock_FUN RCC_APB2PeriphClockCmd #define M_SPI_CS_CLK RCC_APB2Periph_GPIOB #define M_SPI_CS_PORT GPIOB #define M_SPI_CS_PIN GPIO_Pin_12
#define M_SPI_SCK_APBxClock_FUN RCC_APB2PeriphClockCmd #define M_SPI_SCK_CLK RCC_APB2Periph_GPIOB #define M_SPI_SCK_PORT GPIOB #define M_SPI_SCK_PIN GPIO_Pin_13
#define M_SPI_MISO_APBxClock_FUN RCC_APB2PeriphClockCmd #define M_SPI_MISO_CLK RCC_APB2Periph_GPIOB #define M_SPI_MISO_PORT GPIOB #define M_SPI_MISO_PIN GPIO_Pin_14
#define M_SPI_MOSI_APBxClock_FUN RCC_APB2PeriphClockCmd #define M_SPI_MOSI_CLK RCC_APB2Periph_GPIOB #define M_SPI_MOSI_PORT GPIOB #define M_SPI_MOSI_PIN GPIO_Pin_15
#define M_SPI_CS_LOW() GPIO_ResetBits(M_SPI_CS_PORT, M_SPI_CS_PIN) #define M_SPI_CS_HIGH() GPIO_SetBits(M_SPI_CS_PORT, M_SPI_CS_PIN)
#define MAX31865DRDP_PIN GPIO_Pin_5 #define MAX31865DRDP_PORT GPIOB #define MAX31865DRDP_CLK RCC_APB2Periph_GPIOB #define MAX31865DRDP_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ReadPIN_DRDP (MAX31865DRDP_PORT->IDR&MAX31865DRDP_PIN)
void MAX31865Init(void);
u16 SPISendByte(u8 add,u8 byte);
MAX31865 *GetSensorTemp(void);
#endif
|
bsp_max31865.c1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
| #include "bsp_max31865.h"
#define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000)
typedef union _UU16_ { uint16_t U16; int16_t S16; uint8_t vU8[2]; int8_t vS8[2]; } _UU16;
static MAX31865 tmpValue = {0}; static __IO uint32_t SPITimeoutCNT = SPIT_FLAG_TIMEOUT;
static void HardDelay(void) { uint8_t delayTick = 0; while (delayTick < 128) delayTick++; }
void MAX31865Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; M_SPI_APBxClock_FUN(M_SPI_CLK, ENABLE);
M_SPI_CS_APBxClock_FUN(M_SPI_CS_CLK | M_SPI_SCK_CLK | M_SPI_MISO_PIN | M_SPI_MOSI_PIN, ENABLE);
GPIO_InitStructure.GPIO_Pin = M_SPI_CS_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(M_SPI_CS_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = M_SPI_SCK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(M_SPI_SCK_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = M_SPI_MISO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(M_SPI_MISO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = M_SPI_MOSI_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(M_SPI_MOSI_PORT, &GPIO_InitStructure);
M_SPI_CS_HIGH();
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(M_SPI, &SPI_InitStructure);
SPI_Cmd(M_SPI, ENABLE);
MAX31865DRDP_APBxClock_FUN(MAX31865DRDP_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = MAX31865DRDP_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(MAX31865DRDP_PORT, &GPIO_InitStructure);
SPISendByte(0x80, MAX31865_INITVAL); HardDelay(); }
u16 SPISendByte(u8 add, u8 byte) { uint16_t tmp16 = add << 8; tmp16 = tmp16 | byte;
M_SPI_CS_LOW(); SPITimeoutCNT = SPIT_FLAG_TIMEOUT; while (SPI_I2S_GetFlagStatus(M_SPI, SPI_I2S_FLAG_TXE) == RESET) { if ((SPITimeoutCNT--) == 0) { M_SPI_CS_HIGH(); return 255; } }
SPI_I2S_SendData(M_SPI, tmp16);
SPITimeoutCNT = SPIT_FLAG_TIMEOUT; while (SPI_I2S_GetFlagStatus(M_SPI, SPI_I2S_FLAG_RXNE) == RESET) { if ((SPITimeoutCNT--) == 0) { M_SPI_CS_HIGH(); return 255; } } M_SPI_CS_HIGH(); return SPI_I2S_ReceiveData(M_SPI); }
static uint8_t r00 = 0, r01 = 0, r02 = 0, r07 = 0; static int16_t r01_2 = 0; static float R_RTD = 0;
MAX31865 *GetSensorTemp(void) { _UU16 tmpReg; r00 = SPISendByte(0x00, 0xFF); HardDelay(); if (r00 != MAX31865_INITVAL) { SPISendByte(0x80, MAX31865_INITVAL); HardDelay(); tmpValue.status = 0xFF; return &tmpValue; }
if (ReadPIN_DRDP != 0) return &tmpValue;
r01 = SPISendByte(0x01, 0xFF); HardDelay(); r02 = SPISendByte(0x02, 0xFF); HardDelay(); r07 = SPISendByte(0x07, 0xFF); HardDelay();
if (r07 != 0) { SPISendByte(0x80, 0xC7); HardDelay(); } tmpReg.vU8[1] = r01; tmpReg.vU8[0] = r02; r01_2 = tmpReg.U16 >> 1;
R_RTD = (r01_2 / 32768.0f) * PT1000_Resistance_Ref; tmpValue.status = r07; if (tmpValue.status == 0) tmpValue.temp_out = 0.000011185431f * R_RTD * R_RTD + 0.23292227f * R_RTD - 244.17129f; return &tmpValue; }
|
调用方法
main.c1 2 3 4 5 6 7 8 9 10 11 12 13
| #include "bsp_max31865.h" MAX31865 *_Sen_Max31855; int main(void) { HSI_SetSysClock(RCC_PLLMul_16); MAX31865Init(); ... while (1) { _Sen_Max31855 = GetSensorTemp(); delay_ms(1000); } }
|