Chapter1 max31865模块RTD测温注意事项

注意事项1 参考电阻

The PT100 version of the breakout uses 430Ω
The PT1000 version uses 4300Ω
一般PT100选400欧姆参考电阻,但是板子上给的是4300,也就是430Ω。程序里需要设置参考电阻为430,PT1000选择4300Ω。
#define REF_RES 430
在这里插入图片描述

注意事项2 接线

板子上有三个位置用于设置线的。
在这里插入图片描述

在这里插入图片描述

注意事项3 电气连接

Power Pins:
Vin - this is the power pin. Since the chip uses 3 VDC, we have included a voltage regulator on board that will take 3-5VDC and safely convert it down. To power the board, give it the same power as the logic level of your microcontroller - e.g. for a 5V micro like Arduino, use 5V
3Vo - this is the 3.3V output from the voltage regulator, you can grab up to 100mA from this if you like
GND - common ground for power and logic

SPI Logic pins:
All pins going into the breakout have level shifting circuitry to make them 3-5V logic level safe. Use whatever logic level is on Vin!

SCK - This is the SPI Clock pin, its an input to the chip
SDO - this is the Serial Data Out / Microcontroller In Sensor Out pin, for data sent from the MAX31865 to your processor
SDI - this is the Serial Data In / Microcontroller Out Sensor In pin, for data sent from your processor to the MAX31865
CS - this is the Chip Select pin, drop it low to start an SPI transaction. Its an input to the chip
If you want to connect multiple MAX31865’s to one microcontroller, have them share the SDI, SDO and SCK pins. Then assign each one a unique CS pin.

RDY (Ready) - is a data-ready indicator pin, you can use this pin to speed up your reads if you are writing your own driver. Our Arduino driver doesn’t use it to save a pin.

注意事项4 max31865模块重要细节

SPI对其寄存器进行读写,寄存器如下图。
配置寄存器,想读就读0x00,想写就写0x80。
转化后的RTD数值存放于0x01和0x02这2个8位寄存器。
可以设置错误报警门限上限和下限,通俗来说,比如一个PT100能测温范围是-200℃到420℃,用户想设置下限报警值为-180℃,上限报警值为400℃,那么当max31865转换RTD后,会将0x01和0x02寄存器结果与上限值和下限值比较,如果不在设置的范围,就会产生错误标志。
错误标志存在0x07寄存器中。
读取温度过程:
(1)读取0x07寄存器,看是不是等于0x00,即是说无错误标志。有错误标志时,0x07寄存器里面某个值就是1。

错误标志可以手动清除,但如果没实际解决问题,下次检测这个标志还是会被模块拉起。

(2)如果能过错误检测,就开始下面的过程。向0x80写入配置,这里写入的是说进行一次转换(One_Shot_Conversion ),然后等待DRDY 引脚变成低电平(意味转换结束)。然后读取0x01和0x02这2个8位寄存器,0x02的最低位装的是错没错的标志,没错的话就可以利用0x01和0x02这2个8位寄存器合成电阻数值。

4)PT100电阻变成温度
这个就各显神通了,有各种各样的转换公式。

注意事项5 SPI时序间隔

在这里插入图片描述
在这里插入图片描述

注意事项6 max31865读取不到寄存器数据的原因

从机发数据也是需要主机提供时钟信号的
在这里插入图片描述

在这里插入图片描述

参考代码

//使用RT1052 LPSPI3
//LPSPI3:读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
uint8_t LPSPI3_ReadWriteByte(uint8_t TxData)
{
    uint8_t spirxdata=0;
    uint8_t spitxdata=TxData;
    lpspi_transfer_t spi_tranxfer;
    lpspi_master_handle_t master_handle;

    spi_tranxfer.configFlags=kLPSPI_MasterPcs1|kLPSPI_MasterPcsContinuous;     //PCS1
    spi_tranxfer.txData=&spitxdata;                 //要发送的数据
    spi_tranxfer.rxData=&spirxdata;                 //要接收到的数据
    spi_tranxfer.dataSize=1;                        //数据长度
    LPSPI_MasterTransferBlocking(LPSPI3,&spi_tranxfer);     //SPI阻塞发送
//      LPSPI_MasterTransferNonBlocking(LPSPI3, &master_handle, &spi_tranxfer);
    return spirxdata;
}
uint8_t max31685_ReadRegister8(uint8_t addr)
{
    uint8_t ret;
    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 1U);
    SysTick_DelayTicks(1U);
    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 0U);
    SysTick_DelayTicks(1U);
    ret = LPSPI3_ReadWriteByte(addr);
    SysTick_DelayTicks(1U);
    ret = LPSPI3_ReadWriteByte(0xff);
    SysTick_DelayTicks(1U);
    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 1U);
    return ret;

}
uint8_t max31685_WriteRegister8(uint8_t addr, uint8_t data)
{
    uint8_t ret;
    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 1U);
    SysTick_DelayTicks(1U);
    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 0U);
    SysTick_DelayTicks(1U);
    ret = LPSPI3_ReadWriteByte(addr | 0x80);
    SysTick_DelayTicks(1U);
    ret = LPSPI3_ReadWriteByte(data);
    SysTick_DelayTicks(1U);
    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 1U);
    return ret;
}
void max31865_Init(void)
{
    uint8_t ret; //for test

    GPIO_PinWrite(BOARD_USER_SPI_CS0, BOARD_USER_SPI_CS0_PIN, 1U);
    SysTick_DelayTicks(10U);
    //BIAS ON,自动,三线,50Hz
    max31685_WriteRegister8(MAX31856_CONFIG_REG, MAX31856_CONFIG_BIAS | MAX31856_CONFIG_MODEAUTO | MAX31856_CONFIG_3WIRE | MAX31856_CONFIG_FILT50HZ);
    ret = max31685_ReadRegister8(MAX31856_CONFIG_REG);
}
uint8_t max31865_ReadFault(void)
{


}


void max31865_ClearFault(void)
{

}

void max31865_Config(uint8_t reg, uint8_t cfgValue)
{



}


uint16_t max31865_ReadRTD(void)
{
    uint16_t rtd = 0;
    rtd = max31685_ReadRegister8(MAX31856_RTDMSB_REG) << 8;
    rtd |= max31685_ReadRegister8(MAX31856_RTDLSB_REG);
    rtd = rtd >> 1;
    return rtd;
}

在这里插入图片描述

参考链接1:
https://learn.adafruit.com/adafruit-max31865-rtd-pt100-amplifier?view=all
参考链接2:
https://blog.csdn.net/x1131230123/article/details/105446353?spm=1001.2014.3001.5506

Chapter2 STM32软硬件SPI读取MAX31865 PT100温度支持shell功能

原文链接

Chapter3 STM32CubeMX-配置SPI驱动MAX31865读取铂电阻温度

原文链接

我们在项目文件夹目录下创建 Hardware 文件夹,文件夹下创建 MAX31865 文件夹,下面创建 max31865 文件
在这里插入图片描述
max31865.c 编写如下代码:

#include "max31865.h"

void MAX31865_Init()
{
	//MAX31865_SB_Write(0x80,0xC1);//二线、四线配置
  MAX31865_SB_Write(0x80,0xD1);//三线配置

  HAL_Delay(10);
}


float Get_tempture(void)//PT100
{
  float temps;
  uint16_t data_r;
  data_r = MAX31865_SB_Read(0x01) << 8;
	data_r |= MAX31865_SB_Read(0x02);
	data_r >>= 1;
  temps=data_r;
  temps=(temps*402.0f)/32768.0f;//获得转换的电阻值
	
	
  temps=(temps-100.0f)/0.385055f;
	//电阻转化为温度,此处直接使用网上的线性拟合,误差很大!
	//想要提高精度需要标定电阻和温度关系
  return temps;
}

uint8_t MAX31865_SB_Read(uint8_t addr)//SPI Single-Byte Read
{
  uint8_t read;
	MAX31685_CS_LOW();
	HAL_SPI_Transmit(&hspi1, &addr, 1, 60);
	HAL_SPI_Receive(&hspi1, &read, 1, 60);
	MAX31685_CS_HIGH();
  return read;
}

void MAX31865_SB_Write(uint8_t addr,uint8_t wdata)//SPI Single-Byte Write
{
	uint8_t dat[2];
	dat[0] = addr;
	dat[1] = wdata;
	MAX31685_CS_LOW();
	HAL_SPI_Transmit(&hspi1,dat,2,60);
	MAX31685_CS_HIGH();
}

max31865.h 编写如下代码:

#ifndef __MAX31865_H
#define __MAX31865_H


#include "spi.h"
#include "gpio.h"
#include "stm32f4xx_hal.h"

#define MAX31685_RDY() HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)	//iso module is not connect
#define MAX31685_CS_HIGH() HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET)
#define MAX31685_CS_LOW() HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET)

void MAX31865_Init(void);
uint8_t MAX31865_SB_Read(uint8_t addr);
void MAX31865_SB_Write(uint8_t addr,uint8_t wdata);
float Get_tempture(void);

#endif

然后我们在工程里面添加文件,导入路径,在主函数调用该函数:
在这里插入图片描述
主函数代码:

  /* USER CODE BEGIN 2 */
	MAX31865_Init();
	printf("System Init! \r\n");
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(MAX31685_RDY() == 0)
		{
			tempture=Get_tempture();
			Fault_Status=MAX31865_SB_Read(0x07);//Get Fault_Status
			printf("tempture: %f C\r\n Fault_Status: %d\r\n",tempture,Fault_Status);
		}
		HAL_Delay(1000);
  }
  /* USER CODE END 3 */

MAX31865_SB_Read(0x07) 是获取错误标志位,对应位如下,返回 1 是表示该位错误:
在这里插入图片描述
0x01 和 0x02 用于存储转换后的电阻值,我们读取那个值就能获得电阻值,经过自己的算法转化就能获得温度值:

在这里插入图片描述

实验现象

获取温度数据,打印到串口上:
在这里插入图片描述

Chapter4 STM32F1标准库封装代码

在这里插入图片描述

stm32_spi.h

#ifndef __STM32_SPI_H
#define __STM32_SPI_H

#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
   
#define FLAG_TIMEOUT         ((uint32_t)0x1000)
#define LONG_TIMEOUT         ((uint32_t)(10 *FLAG_TIMEOUT))

#define MAX31865_SPI_PORT 				GPIOA
#define MAX31865_IO_PORT  				GPIOB
				
// define SPI pins				
#define SPI_SCK           				GPIO_Pin_5    /* GPIOA.5*/
#define SPI_MISO          				GPIO_Pin_6    /*GPIOA.6*/
#define SPI_MOSI          				GPIO_Pin_7    /*GPIOA.7*/
#define SPI_CS            				GPIO_Pin_6    /*GPIOB.6*/
#define DRDY_PIN          				GPIO_Pin_5    /*GPIOB.5*/

#define SPI_GPIO_CLK             	RCC_APB2Periph_GPIOA
#define SPI_CS_GPIO_CLK          	RCC_APB2Periph_GPIOB
#define DRDY_GPIO_CLK            	RCC_APB2Periph_GPIOB


#define SPI_CS_HIGH              	GPIO_SetBits(MAX31865_IO_PORT, SPI_CS)
#define SPI_CS_LOW               	GPIO_ResetBits(MAX31865_IO_PORT, SPI_CS)

void  SPI_Inital(void);//MAX31865 硬件spi初始化
uint8_t SPI_Write(uint8_t *buffer, uint8_t nBytes);//SPI写数据
uint8_t SPI_Read(uint8_t *buffer, uint8_t nBytes); //SPI读数据 
uint8_t SPI_WriteByte(uint8_t data);//SPI字节写数据
uint8_t SPI_ReadByte(void);         //SPI字节读数据
void Set_DRDY_Pin_INPUT(void);//MAX31865 DRDY输入IO配置
uint8_t DRDY_Pin_Value(void);//读MAX31865  DRDY_Pin_Value高低电平

#ifdef __cplusplus
}
#endif

#endif

stm32_spi.c

#include "stm32_spi.h"

__IO uint32_t TIMEOUT=LONG_TIMEOUT;
/***********************************************
调用方式: SPI_Inital()
SDO   --->   PA5
CS    --->   PB6
SCLK  --->   PA5
SDI   --->   PA7
DRDY  --->   PB6
返回值:  
函数说明:MAX31865 硬件spi初始化
************************************************/
void  SPI_Inital(void)
{
 SPI_InitTypeDef  SPI_InitStructure;
 GPIO_InitTypeDef  GPIO_InitStructure; 
// GPIO
 RCC_APB2PeriphClockCmd(SPI_GPIO_CLK, ENABLE);
 RCC_APB2PeriphClockCmd(SPI_CS_GPIO_CLK, ENABLE);

 /*!< SPI Periph clock enable */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
 
 /*!< GPIO configuration */  
 /*!< Configure SPI pins */
 GPIO_InitStructure.GPIO_Pin = SPI_SCK|SPI_MOSI|SPI_MISO;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(MAX31865_SPI_PORT, &GPIO_InitStructure);
 
 /*!< Configure SPI pin: CS */
 GPIO_InitStructure.GPIO_Pin = SPI_CS;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_Init(MAX31865_IO_PORT, &GPIO_InitStructure);  
 //set CS high
	GPIO_SetBits(MAX31865_IO_PORT, SPI_CS); 
 /*!< SPI configuration */
 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
 SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b;
 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_8;
 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
 SPI_InitStructure.SPI_CRCPolynomial = 7;
 /* SPI Peripheral Enable */
 SPI_Cmd(SPI1, ENABLE);
 /* Apply SPI configuration after enabling it */
 SPI_Init(SPI1, &SPI_InitStructure);
}
/***********************************************
调用方式: SPI_Write()
返回值:  
函数说明:SPI写数据
************************************************/
uint8_t SPI_Write(uint8_t *buffer, uint8_t nBytes)
{
  uint8_t i;
  for(i=0;i<nBytes;i++){
       TIMEOUT = LONG_TIMEOUT;
       while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){  //not empty
                if((TIMEOUT--) == 0) return (1);
             }
       SPI_I2S_SendData(SPI1,buffer[i]);
       TIMEOUT = LONG_TIMEOUT;
       while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){     
               if((TIMEOUT--) == 0) return (1);
            }
       SPI_I2S_ReceiveData(SPI1);  
     }
  return(0);
}
/***********************************************
调用方式: SPI_Read()
返回值:  
函数说明:SPI读数据
************************************************/
uint8_t SPI_Read(uint8_t *buffer, uint8_t nBytes)
{
  uint8_t i;
  SPI_I2S_ReceiveData(SPI1);
  for(i=0;i<nBytes;i++)
     {
       TIMEOUT = LONG_TIMEOUT;
       while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){  //not empty
               if((TIMEOUT--) == 0) return (1);
             }
       SPI_I2S_SendData(SPI1,0x00);
       TIMEOUT = LONG_TIMEOUT;
       while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){
               if((TIMEOUT--) == 0) return (1);
            }
       buffer[i]= SPI_I2S_ReceiveData(SPI1);
     }
  return(0);
}
/***********************************************
调用方式: SPI_WriteByte()
返回值:  
函数说明:SPI字节写数据
************************************************/
uint8_t SPI_WriteByte(uint8_t data)
{
	 TIMEOUT = LONG_TIMEOUT;
	 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){  //not empty
						if((TIMEOUT--) == 0) return (1);
				 }
	 SPI_I2S_SendData(SPI1,data);
	 TIMEOUT = LONG_TIMEOUT;
	 while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){
					 if((TIMEOUT--) == 0) return (1);
				}
	 SPI_I2S_ReceiveData(SPI1);
	 SPI_I2S_ReceiveData(SPI1);
	 return(0);
}
/***********************************************
调用方式: SPI_WriteByte()
返回值:  
函数说明:SPI字节读数据
************************************************/
uint8_t SPI_ReadByte(void)
{
	SPI_I2S_ReceiveData(SPI1);
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);  //not empty	
	SPI_I2S_SendData(SPI1,0xff);
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); 
	return (SPI_I2S_ReceiveData(SPI1));
}
/***********************************************
调用方式: Set_DRDY_Pin_INPUT()
返回值:  
函数说明:MAX31865 DRDY输入IO配置
************************************************/
void Set_DRDY_Pin_INPUT(void)
{
   GPIO_InitTypeDef  GPIO_InitStructure;
   
   RCC_APB2PeriphClockCmd(DRDY_GPIO_CLK, ENABLE); 
   GPIO_InitStructure.GPIO_Pin = DRDY_PIN;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
   GPIO_Init(MAX31865_IO_PORT, &GPIO_InitStructure);      
}
/***********************************************
调用方式: DRDY_Pin_Value()
返回值:  
函数说明: 读MAX31865  DRDY_Pin_Value高低电平
************************************************/
uint8_t DRDY_Pin_Value(void)
{
   return(GPIO_ReadOutputDataBit(MAX31865_IO_PORT, DRDY_PIN));      
}

MAX31865drv.h

#ifndef __MAX31865drv_H
#define __MAX31865drv_H

#ifdef __cplusplus
 extern "C" {
#endif

#include "stm32_spi.h"
#include "math.h"
#include "usart_arb.h"

typedef struct
{
 uint8_t   Vbias;
 uint8_t   Conversion_mode;
 uint8_t   Rtd_wire;
 uint8_t   Filter; 
}max31865_configuration;

//如果RTD为PT100

#define         REF_RES                         (430)
#define         R0                              (100)

/*
 //如果RTD为PT1K
#define         REF_RES                         4000
#define         R0                              1000
*/

#define         ON                              (0x80)
#define         OFF                             (0x00)

#define         Auto_Conversion                 (0x40)
#define         One_Shot_Conversion             (0x20)

#define         RTD_3wire                       (0x10)
#define         RTD_2wire                       (0x00)
#define         RTD_4wire                       (0x00)

#define         Filter_50Hz                     (0x01)
#define         Filter_60Hz                     (0x00)

/* 定义温度修正系数*/

//#define         A                               0.00390830
//#define         B                               -0.0000005775
//#define         C                               -0.00000000000418301

void maxim_31865_write_register(uint8_t uch_register_address, uint8_t uch_register_value);
void maxim_31865_write_nregisters(uint8_t uch_register_address,uint8_t *uch_buff,uint8_t uch_nBytes);
uint8_t maxim_31865_read_register(uint8_t uch_register_address);
void maxim_31865_read_nregisters(uint8_t uch_register_address, uint8_t *uch_buff,uint8_t uch_nBytes);
void maxim_31865_init(max31865_configuration* configuration);
void maxim_set_fault_threshold(float high_threshold, float low_threshold);
uint8_t maxim_auto_fault_detection(void) ;
uint8_t maxim_manual_fault_detection(void);
void maxim_clear_fault_status(void);
void maxim_get_rtd_value(uint8_t *uch_buff);
void delay_us(uint32_t us);

void Get_Hardware_SPI_Temp_Init(void);//配置PT100参数
float Get_Hardware_SPI_Temp(void);//输出温度结果
  
 #ifdef __cplusplus
}
#endif

#endif

MAX31865drv.c

#include "MAX31865drv.h"
/***********************************************
调用方式: maxim_31865_write_register()
返回值:  
函数说明: 寄存器写入
************************************************/
void maxim_31865_write_register(uint8_t uch_register_address, uint8_t uch_register_value)
{
  SPI_CS_LOW;
  SPI_WriteByte(uch_register_address);
  SPI_WriteByte(uch_register_value);
  SPI_CS_HIGH; 
}
/***********************************************
调用方式: maxim_31865_write_nregisters()
返回值:  
函数说明: 寄存器写入指定字节
************************************************/
void maxim_31865_write_nregisters(uint8_t uch_register_address,uint8_t *uch_buff,uint8_t uch_nBytes)
{
  SPI_CS_LOW;
  SPI_WriteByte(uch_register_address);
  SPI_Write(uch_buff,uch_nBytes);
  SPI_CS_HIGH; 
}
/***********************************************
调用方式: maxim_31865_read_register()
返回值:   uch_register_data
函数说明: 寄存器读出字节
************************************************/
uint8_t maxim_31865_read_register(uint8_t uch_register_address)
{
  uint8_t uch_register_data; 
  SPI_CS_LOW;
  SPI_WriteByte(uch_register_address);
  uch_register_data=SPI_ReadByte();
  SPI_CS_HIGH;
  return (uch_register_data);
}
/***********************************************
调用方式: maxim_31865_read_nregisters()
返回值:   
函数说明: 寄存器读出多字节
************************************************/
void maxim_31865_read_nregisters(uint8_t uch_register_address, uint8_t *uch_buff,uint8_t uch_nBytes)
{
 SPI_CS_LOW;
 SPI_WriteByte(uch_register_address);
 SPI_Read(uch_buff,uch_nBytes);
 SPI_CS_HIGH;
}
/***********************************************
调用方式: maxim_31865_init()
返回值:   
函数说明: 初始化max31865配置
************************************************/
void maxim_31865_init(max31865_configuration* configuration)
{ 
	uint8_t temp=0;
	temp|=configuration->Vbias|configuration->Conversion_mode|configuration->Rtd_wire|configuration->Filter;
	maxim_31865_write_register(0x80,temp);  
}
/***********************************************
调用方式: maxim_set_fault_threshold()
返回值:   
函数说明: 设置故障门限,输入为电阻值
************************************************/
void maxim_set_fault_threshold(float high_threshold, float low_threshold)
{
  uint8_t au_threshold[4];
  uint16_t u_threshold;
  
  u_threshold= ((int)((high_threshold/REF_RES)*16383))<<1;
  au_threshold[0]=(u_threshold>>8);
  au_threshold[1]=u_threshold&0xff;
  u_threshold=((int)((low_threshold/REF_RES)*16383))<<1;
  au_threshold[2]=(u_threshold>>8);
  au_threshold[3]=u_threshold&0xff;
  
  maxim_31865_write_nregisters(0x83,au_threshold,4);
 
}
/***********************************************
调用方式: maxim_auto_fault_detection()
返回值:   
函数说明: 自动故障检测
************************************************/
uint8_t maxim_auto_fault_detection(void)  
{
 uint8_t uch_status;
 uint8_t uch_config;
 uch_config=maxim_31865_read_register(0x00);
 uch_config|=0x84;
 maxim_31865_write_register(0x80, uch_config);
 while((maxim_31865_read_register(0x00)&0xC0)!=0x00);
 uch_status=maxim_31865_read_register(0x07);
 return(uch_status); 
}
/***********************************************
调用方式: maxim_manual_fault_detection()
返回值:   
函数说明: 手动故障检测
************************************************/
uint8_t maxim_manual_fault_detection(void)
{
 uint8_t uch_status;
 uint8_t uch_config;
 uch_config=maxim_31865_read_register(0x00);
 uch_config|=0x80;
 uch_config&=0xf3;
 maxim_31865_write_register(0x80, uch_config);
 delay_us(200);
 uch_config|=0x88;
 maxim_31865_write_register(0x80, uch_config);
 delay_us(200);
 uch_config|=0x8C;
 maxim_31865_write_register(0x80, uch_config);
 while((maxim_31865_read_register(0x00)&0x0C)!=0x00);
 uch_status=maxim_31865_read_register(0x07);
 return(uch_status); 
}
/***********************************************
调用方式: maxim_clear_fault_status()
返回值:   
函数说明: 清除故障寄存器
************************************************/
void maxim_clear_fault_status(void)
{
 uint8_t uch_config;
 
  uch_config=maxim_31865_read_register(0x00);
  uch_config&=0xd3;
  uch_config|=0x02;
  maxim_31865_write_register(0x80, uch_config);  
}
/***********************************************
调用方式: maxim_get_rtd_value()
返回值:   
函数说明: 读取测量结果
************************************************/
void maxim_get_rtd_value(uint8_t *uch_buff)
{
 maxim_31865_read_nregisters(0x01,uch_buff,2);
}
/***********************************************
调用方式: MAX31865_GetTemp1()
返回值:  temp 
函数说明: 获取温度
************************************************/
static float MAX31865_GetTemp1(uint8_t value[2])
{ 
	unsigned int data;
	float Rt;
	float Rt0 = 100;  //PT100	
	float Z1,Z2,Z3,Z4,temp;
	float a = 3.9083e-3;
	float b = -5.775e-7;
	float rpoly;
	data= value[0]<<8;
	data|= value[1];
	data>>=1;  //去掉Fault位
	Rt=(float)data/32768.0*REF_RES;	
	Z1 = -a;
  Z2 = a*a-4*b;
  Z3 = 4*b/Rt0;
  Z4 = 2*b;
  temp = Z2+Z3*Rt;
  temp = (sqrt(temp)+Z1)/Z4;
  if(temp>=0){
		return temp;
	}
  rpoly = Rt;
  temp = -242.02;
  temp += 2.2228 * rpoly;
  rpoly *= Rt;  // square
  temp += 2.5859e-3 * rpoly;
  rpoly *= Rt;  // ^3
  temp -= 4.8260e-6 * rpoly;
  rpoly *= Rt;  // ^4
  temp -= 2.8183e-8 * rpoly;
  rpoly *= Rt;  // ^5
  temp += 1.5243e-10 * rpoly;

  return temp;
}
/***********************************************
调用方式: Get_Hardware_SPI_Temp_Init()
返回值:   
函数说明: 配置PT100参数
************************************************/
void Get_Hardware_SPI_Temp_Init(void)
{
	max31865_configuration  configuration;
	/*配置MAX31865工作模式*/
	configuration.Vbias = ON;
	configuration.Rtd_wire = RTD_3wire;
	configuration.Filter = Filter_50Hz;
	maxim_31865_init(&configuration);
	/*设置故障门限,输入为电阻值*/
	maxim_set_fault_threshold(430, 0);
}
/***********************************************
调用方式: Get_Hardware_SPI_Temp()
返回值:   
函数说明: 输出温度结果
************************************************/
float Get_Hardware_SPI_Temp(void)
{
	max31865_configuration  configuration;
	
	uint8_t uch_fault_status;//故障代码
	uint8_t auch_rtd[2];//数据缓存
	float   f_temperature;//温度转换
	uch_fault_status = maxim_manual_fault_detection();
 /*
	*如果检测到RTD故障,则输入故障代码,停止程序运行,否则,将进入循环程序
	*在循环程序中,采用单次测量方式,每秒测量一次,将测量结果转换成温度输出。
	*如果在循环程序中检测到RTD故障,同样输入故障代码,但是,会循环检测,一旦
	*故障消除,将会继续进行温度采集
	*/
	if((uch_fault_status & 0xFC) == 0){
			configuration.Conversion_mode = One_Shot_Conversion;
			maxim_31865_init(&configuration);                              //启动一次测量

			while(DRDY_Pin_Value() == SET);                                //等待测量结束

			maxim_get_rtd_value( auch_rtd);                                 //读取测量结果

			if((auch_rtd[1] & 0x01) == 0x01){                               //如果故障标识置位,运行故障检测,输入故障代码
					uch_fault_status = maxim_manual_fault_detection();         //运行手动故障检测,也可以运行自动故障检测
					maxim_clear_fault_status();                                //清除故障寄存器
					printf("%d",uch_fault_status);
			}
			else{
					//如果没有故障,则进行温度转换,输出温度转换结果
					f_temperature = MAX31865_GetTemp1(auch_rtd);
			}

	}
	else{
		 maxim_clear_fault_status();//清除故障寄存器
		 printf("%d",uch_fault_status);
	}
	return f_temperature;
	
}

max31865.h

#ifndef __MAX31865_H
#define __MAX31865_H

#include "stm32f10x.h"
#include "math.h"
#include "usart_arb.h"
#include "delay.h"

/* MAX31865参考电阻 */
#define RREF            (430)  //400Ω


/* MAX31865控制口 */
#define MAX31865_CONTROL_PORT     GPIOC
#define MAX31865_SDO              GPIO_Pin_10
#define MAX31865_CS               GPIO_Pin_12
#define MAX31865_SCLK             GPIO_Pin_9
#define MAX31865_SDI              GPIO_Pin_11
#define MAX31865_DRDY 	          GPIO_Pin_13 

#define MAX31865_CS_SET           GPIO_WriteBit(MAX31865_CONTROL_PORT,MAX31865_CS,Bit_SET)
#define MAX31865_CS_CLR      		  GPIO_WriteBit(MAX31865_CONTROL_PORT,MAX31865_CS,Bit_RESET)
#define MAX31865_SCLK_SET    			GPIO_WriteBit(MAX31865_CONTROL_PORT,MAX31865_SCLK,Bit_SET)
#define MAX31865_SCLK_CLR    			GPIO_WriteBit(MAX31865_CONTROL_PORT,MAX31865_SCLK,Bit_RESET)
#define MAX31865_SDI_SET    			GPIO_WriteBit(MAX31865_CONTROL_PORT,MAX31865_SDI,Bit_SET)
#define MAX31865_SDI_CLR     			GPIO_WriteBit(MAX31865_CONTROL_PORT,MAX31865_SDI,Bit_RESET)

#define MAX31865_SDO_READ    			GPIO_ReadInputDataBit(MAX31865_CONTROL_PORT,MAX31865_SDO)
#define MAX31865_DRDY_READ   			GPIO_ReadInputDataBit(MAX31865_CONTROL_PORT,MAX31865_DRDY)

void MAX31865_Init(void); //MAX31865 初始化,软件模拟
void MAX31865_Cfg(void);  //MAX31865 配置
float MAX31865_GetTemp(void);//MAX31865 获取温度


#endif

max31865.c

#include "max31865.h"

/***********************************************
调用方式:MAX31865_Init()
返回值:
SDO   --->   PC10
CS    --->   PC12
SCLK  --->   PC9
SDI   --->   PC11
DRDY  --->   PC13
函数说明:MAX31865 初始化,软件模拟
************************************************/
void MAX31865_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure ;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA,ENABLE);

	GPIO_InitStructure.GPIO_Pin = MAX31865_CS|MAX31865_SCLK|MAX31865_SDI;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(MAX31865_CONTROL_PORT,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = MAX31865_SDO|MAX31865_DRDY;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(MAX31865_CONTROL_PORT,&GPIO_InitStructure);
	
	MAX31865_CS_SET;
	MAX31865_SCLK_SET;
}

/***********************************************
调用方式:MAX31865_Write()
返回值:
函数说明:MAX31865 写寄存器,addr:寄存器地址,data:数据
************************************************/
void MAX31865_Write(unsigned char addr, unsigned char data)
{
		unsigned char i;
	
	MAX31865_CS_CLR;
	for(i=0;i<8;i++)  //写地址
	{
		MAX31865_SCLK_CLR;
		if(addr&0x80) MAX31865_SDI_SET;
		else MAX31865_SDI_CLR;
		MAX31865_SCLK_SET;
		addr<<=1;
	}
	for(i=0;i<8;i++)  //写数据
	{
		MAX31865_SCLK_CLR;
		if(data&0x80) MAX31865_SDI_SET;
		else MAX31865_SDI_CLR;
		MAX31865_SCLK_SET;
		data<<=1;
	}
	MAX31865_CS_SET;
}
/***********************************************
调用方式:MAX31865_Read()
返回值:  data
函数说明:MAX31865 读寄存器 ,addr:寄存器地址
************************************************/
unsigned char MAX31865_Read(unsigned char addr)
{
	unsigned char i;
	unsigned char data=0;
	
	MAX31865_CS_CLR;
	for(i=0;i<8;i++)  //写地址
	{
		MAX31865_SCLK_CLR;
		if(addr&0x80) MAX31865_SDI_SET;
		else MAX31865_SDI_CLR;
		MAX31865_SCLK_SET;
		addr<<=1;
	}
	for(i=0;i<8;i++)  //读数据
	{
		MAX31865_SCLK_CLR;
		data<<=1;		
		MAX31865_SCLK_SET;		
		if(MAX31865_SDO_READ) data|=0x01;
		else data|=0x00;
	}
	MAX31865_CS_SET;
	return data;
}
/***********************************************
调用方式:MAX31865_Cfg()
返回值:  
函数说明:MAX31865 配置
************************************************/
void MAX31865_Cfg(void)
{
	//BIAS ON,自动,4线,50HZ  根据文件修改四线还是三线
	MAX31865_Write(0x80, 0xC3); 
}
/***********************************************
调用方式:MAX31865_GetTemp()
返回值:  
函数说明:MAX31865 获取温度
************************************************/
float MAX31865_GetTemp(void)
{ 
	unsigned int data;
	float Rt;
	float Rt0 = 100;  //PT100	
	float Z1,Z2,Z3,Z4,temp;
	float a = 3.9083e-3;
	float b = -5.775e-7;
	float rpoly;
//	MAX31865_Write(0x80, 0xD3);
	data=MAX31865_Read(0x01)<<8;
	data|=MAX31865_Read(0x02);
	data>>=1;  //去掉Fault位
	Rt=(float)data/32768.0*RREF;
	Z1 = -a;
  Z2 = a*a-4*b;
  Z3 = 4*b/Rt0;
  Z4 = 2*b;
  temp = Z2+Z3*Rt;
  temp = (sqrt(temp)+Z1)/Z4;
  if(temp>=0){
		return temp;
	}
  rpoly = Rt;
  temp = -242.02;
  temp += 2.2228 * rpoly;
  rpoly *= Rt;  // square
  temp += 2.5859e-3 * rpoly;
  rpoly *= Rt;  // ^3
  temp -= 4.8260e-6 * rpoly;
  rpoly *= Rt;  // ^4
  temp -= 2.8183e-8 * rpoly;
  rpoly *= Rt;  // ^5
  temp += 1.5243e-10 * rpoly;

  return temp;
}
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐