? ? ? ? PT100的温度读取硬件是利用TB的MAX31865现成模块,也可以自己做相应的PCB。原理图可以查看美信官方文档作为参考。传送门:https://www.maximintegrated.com/en/products/interface/sensor-interface/MAX31865.html
????????STM32的SPI功能就不多赘述,可以利用软件模拟SPI或使用STM32的硬件SPI。相应的优缺点个人使用总结单个SPI通讯用软硬件都行,多机通讯使用STM32的硬件SPI较好。
????????下面将展示STM32软硬件SPI读取MAX31865,获得电阻值计算温度的模块代码。
????????百度云链接:https://pan.baidu.com/s/1B8qxTVGqyX6V1TCjKcCfrQ? ????????提取码:fq7g
显示效果如下:
?
软件模拟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_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
硬件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
}
}
}
硬件模块连接示意图:?
?
?
|