PT使用100温度读取硬件TB的MAX31865现成模块也可以自己制作。PCB。可以查看美信官方文档作为参考。传送门:https://www.maximintegrated.com/en/products/interface/sensor-interface/MAX31865.html
STM32的SPI功能不多赘述,可以用软件模拟SPI或使用STM32的硬件SPI。个人使用总结相应的优缺点SPI通讯用软硬件都行,多机通讯使用STM32的硬件SPI较好。
下面将展示STM32软硬件SPI读取MAX获得电阻值计算温度的模块代码31865。
百度云链接:https://pan.baidu.com/s/1B8qxTVGqyX6V1TCjKcCfrQ 提取码:fq7g
CSDN连接:max31865软硬件读写.rar-互联网文档资源-CSDN下载
显示效果如下:
软件模拟SPI读取MAX31865,转换为温度输出。
#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; }
#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_PRT,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
硬件SPI读取MAX31865,转换为温度输出。
#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));
}
#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
#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;
}
#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
主函数显示
/***********************************************
调用方式:无
返回值:
函数说明:主函数
************************************************/
int main(void)
{
Bsp_init();//初始化板载程序
while(1)
{
Get_RTCSencod();
//float temp = MAX31865_GetTemp();//软件模拟spi读取max31865合成温度
float temp = Get_Hardware_SPI_Temp();//硬件spi读取max31865合成温度
if(isReadTemp == 1 && isShowShell == 1){
#if 0
if(SysRTC_Secondflag == 1){
SysRTC_Secondflag = 0;
printf("%02d:%02d:%02d",THH, TMM, TSS);
printf("temp=%.2f\r\n",temp);
LED_Light();
#endif
#if 1
if(SysRTC_Secondflag == 1){
SysRTC_Secondflag = 0;
printf("%02d:%02d:%02d",THH, TMM, TSS);
printf("temp=%.2f\r\n",temp);
LED_Light();
//delay_ms(100);
}
#endif
}
}
}
硬件模块连接示意图: