大家好,又见面了,我是你们的朋友全栈君。
前言
网络上关于ZigBee和MAX31865的相关资料较少,对于如何在CC2530上实现对PT100温度数据的读取的资料更是几乎没有。因此本文对MAX31865芯片和模块的使用进行简要介绍,并提供使用源码,同时提供自制模块的相关原理图。
文章目录
- 前言
-
- 一、相关资料
- 二、MAX31865芯片介绍
-
- 2.1简介:
- 2.2:读写时序
- 2.3:配置寄存器
- 2.4错误标志
- 2.5温度读取
- 三、MAX31865模块介绍
-
- 3.1引脚介绍
- 3.2线制选择与接线
- 四、代码
-
- 4.1 配置I/O寄存器
- 4.2 SPI写寄存器
- 4.3 SPI读寄存器
- 4.4 SPI读MSB ADC值
- 4.5 SPI读LSB ADC值 均值滤波
- 4.6 头文件相关定义
- 4.7 主函数
- 五、PCB
- 参考文献
一、相关资料
- MAX31865芯片中文资料
关于MAX31865芯片中文资料可以参考百度文库: 点击或复制链接打开: https://wenku.baidu.com/view/d32856ee940590c69ec3d5bbfd0a79563c1ed408?qq-pf-to=pcqq.group&bfetype=new
- MAX31865芯片英文资料
⑴可以在美信官网查找到芯片手册。
图1.1 美信官网查找MAX31865
大学生还可以用学校邮箱申请样片。
图1.2 美信官网申请样片
⑵当然也可以直接在电子元器件查找网站上进行下载。 例如: https://www.alldatasheetcn.com/ https://www.datasheet5.com/
- MAX31865模块资料
可以参考国外基于Adafruit的MAX31865的使用这篇文章,看不懂的朋友也可以看我后面的简略介绍。
二、MAX31865芯片介绍
2.1简介:
该芯片主要用于测量PT100/PT1000热电阻的阻值,通过SPI对内置存放温度的ADC码进行读取,进而通过公式获得热电阻值并换算成温度值。内片内置15位ADC,满量程时精度0.5℃,可以满足绝大部分需求。
2.2:读写时序
如图2.1所示读时序,首先拉低CS使能脚,时钟SCLK由高变低,写入一个电平,通过SDI写入八位地址,由高到低,而后拉低时钟,往复8次。 写入地址后,通过拉低拉高SCKL,从SDO读取电平。 需要注意的是: 1.读写时必须满足最小上升/下降时间 2.写地址时SDO为高阻态 3.单片机对应的SDO需要设置为输入模式
图2.1 SPI读时序
写时序相对来说比较简单,不再赘述。
图2.2 SPI写时序
2.3:配置寄存器
 根据芯片手册我们可以看到,如图2.3所示配置寄存器的读地址为0x00,写地址为0x80。读配置寄存器可以验证写入的配置是否生效,同时可以通过读出地址与写入地址是否对应来判断模块是否正常工作。 D4是选择PT100的接线(2 4/3线制),其余各个位的功能及作用具体看芯片手册。 □ 不考虑功耗的情况下,四线制可以写入0xC2; □ 考虑功耗,采用1-shot,则可以写入0x01;值得注意的时,在1-shot模式下,在读取阻值之前首先需要打开Vbias给RC网络充电,60Hz下需要52ms,50Hz下需要62.5ms;而后再对D5位写高,完成一次电阻转换。读取完温度数据后,重新关闭Vbias即可。
图2.3 MAX31865配置寄存器
2.4错误标志
如图2.3中的第4567寄存器,通过对其配置,可以设置温度报警门限上限和下限。 简单来说,比如一个PT100能测温范围是-200℃到500℃,用户想设置下限报警值为-180℃,上限报警值为480℃,那么当max31865转换RTD后,会将0x01和0x02寄存器结果与上限值和下限值比较,如果不在设置的范围,就会产生错误标志。错误标志存在0x07寄存器中。
2.5温度读取
如图2.4所示,D0是用于指示是否有图3.3中设定的错误出现。 ○读取温度时,可以先读取0x07寄存器,看是不是等于0x00,即是说无错误标志。有错误标志时,0x07寄存器里面某个值就是1。 ○而后依次读取0x01和0x02地址的数据,并移除掉D0标志位。 ○由ADC码转换为热电阻阻值公式如下: R r t d = ( A D C C o d e × R R E F / 2 15 ) R_{rtd} = (ADC Code ×R_{REF} /2^{15}) Rrtd=(ADC Code ×RREF/215) 其中 R R E F R_{REF} RREF由实际接入电阻决定,一般PT100为400Ω,实际一般使用430Ω。 ○热电阻值可由Callendar-Van Dusen 方程得出: R ( T ) = R 0 ( 1 a T b T 2 c ( T − 100 ) T 3 ) R(T) = R_0(1 aT bT^2 c(T-100)T^3) R(T)=R0(1 aT bT2 c(T−100)T3) 其中 a = 3.90830 × 1 0 − 3 a=3.90830×10^{-3} a=3.90830×10−3 b = − 5.77500 × 1 0 − 7 b=-5.77500×10^{-7} b=−5.77500×10−7 − 200 ℃ ≤ T ≤ 0 ℃ -200℃≤T≤0℃ −200℃≤T≤0℃时 c = − 4.18301 × 1 0 − 12 c=-4.18301×10^{-12} c=−4.18301×10−12 0 ℃ ≤ T ≤ 850 ℃ 0℃≤T≤ 850℃ 0℃≤T≤ 850℃时 c = 0 c=0 c=0
图2.4 MAX31865读取温度
三、MAX31865模块介绍
3.1引脚介绍
总共有8个引脚: ●VIN——电源正极输入引脚,MAX31865供电电压为3.3V,模块内置电压转换,可接入3.3V-5V。 ●GND——地,接电源负极。 ●3V3——3.3V输出引脚,VIN接5V时,该引脚可以作为3.3V输出。 ●SDO——SPI时钟引脚,接单片机I/O口输出。 ●SDO——Serial Data Out / Microcontroller In Sensor Out SPI MISO引脚,接单片机I/O口输出。 ●SDI——Serial Data In / Microcontroller Out Sensor In SPI MOSI引脚,接单片机I/O口,相应I/O口设置为输入。 ●CS——SPI片选引脚,接单片机I/O口输出。 ●RDY—— data-ready indicator 数据允许读取指示,可不接。
图3.1 MAX31865模块引脚
3.2线制选择与接线
图3.2 MAX31865模块线制焊盘
●4线制——需要将图3.2的右下三个焊盘中的左边两个焊接(即24)在一起,即FORCE2引脚接地,图中已经连接在一起 ,因此不需要短接。实际淘宝买的模块应该是没有焊接的,所以需要自己焊接,如图3.3所示,其余焊盘均不焊接。 接线时红色(PT100正)的两根接F 和RTD ,白色/蓝色(PT100负)的两根接F-和RTD-
图3.3 MAX31865模块4线制未自动焊接
●3线制——需要将图3.2的右下三个焊盘中的右边边两个焊接(即3)在一起,左上的两个焊盘焊(即2/3wire)接在一起。其余焊盘均不焊接,若24已经默认焊接,则需要断开,否则读数会始终为固定值。 接线如图。
图3.4 MAX31865模块3线制焊接与接线
●2线制——需要将图3.2的右下三个焊盘中的左边两个焊接(即24)在一起,即FORCE2引脚接地,同时将图3.2的右边两个个焊盘焊接(即 2wire ),其余焊盘均不焊接。 接线直接红色(PT100正)接RTD ,白色/蓝色(PT100负)接RTD-。
四、代码
代码已经有足够的注释,因此不再详细介绍。
4.1 配置I/O寄存器
I/O口设置
//-----------------RTD端口定义----------------
#define RTD_CLK P0_4 //SCLK
#define RTD_SDO P0_5 //serial data output 即单片机输入 MOSI
#define RTD_SDI P0_6 //serial data input 即单片机输出 MISO
#define RTD_CS P0_7 //片选脚
I/O初始化和MAX31865配置寄存器配置
P0DIR是CC2530配置P0口输入输出寄存器。
P0INP是CC2530配置上拉/下拉寄存器。
其他芯片例如51、STM32可以进行类似配置,除SDO设置为输入外,其余可设置为推挽输出。
/************************************************ *函数名:RTD_Init(void) *函数功能:Max18650寄存器配置,单片机I/O配置 *返回值:无 *注:为减小转换功耗,VIAS设为常闭,采用1-shot模式 *************************************************/
void RTD_Init(void)
{
P0DIR |= 0xDF;//SDO设置为输入 SKI CS SDI设置为输出
P0INP &= 0xDF;//上拉/下拉
P2INP |= 0x20;//下拉输入
//RTD_WR_REG(0x80,0xC2);//写配置寄存器 BIAS ON,自动,4线,60HZ 0xC2
RTD_WR_REG(0x80,0x01);//配置寄存器 BIAS OFF,1-shot,4线,50HZ 抑制工频噪声
//RTD_RD_Data(0x00);
}
4.2 SPI写寄存器
代码语言:javascript复制/************************************ *函数名:RTD_WR_REG(uint8 adr,uint8 cmd) *函数功能:对RTD寄存器配置 *adr:寄存器写地址 *cmd:要写入的命令 *返回值:无 ***********************************/
void RTD_WR_REG(uint8 adr,uint8 cmd)
{
uint8 i;
RTD_CS_Clr();//拉低片选,选中芯片
for(i=0;i<8;i )//写寄存器地址
{
RTD_SCLK_Clr();
if(adr&0x80)
RTD_SDI_Set();//若地址数据最高位为高,则SDI拉高
else
RTD_SDI_Clr();//若地址数据最高位为低,则SDI拉低
RTD_SCLK_Set();
adr<<=1; //地址数据左移,次高位变为最高位
}
RTD_SCLK_Set();
//Delayms(1);
for(i=0;i<8;i )//写寄存器数据
{
RTD_SCLK_Clr();
if(cmd&0x80)
RTD_SDI_Set();//数据最高位为高,则SDI拉高
else
RTD_SDI_Clr();//数据最高位为低,则SDI拉低
RTD_SCLK_Set();
cmd<<=1; //数据左移,次高位变为最高位
}
RTD_SCLK_Set();
RTD_CS_Set();
}
4.3 SPI读寄存器
代码语言:javascript复制/************************************ *函数名:RTD_RD_Data(uint8 adr) *函数功能:从RTD寄存器中读数据 *adr:读取寄存器所在地址 *返回值:data 读取到的值 ***********************************/
uint8 RTD_RD_Data(uint8 adr)
{
uint8 i;
uint8 data = 0x00;
if(adr==0x01||adr==0x02)//读取温度寄存器时
RTD_WR_REG(0x80,0xA1);//启动一次电阻测试转换
RTD_CS_Clr();//拉低片选,选中芯片
for(i=0;i<8;i )
{
RTD_SCLK_Clr();
if(adr&0x80)
RTD_SDI_Set();//数据最高位为高,则SDI拉高
else
RTD_SDI_Clr();//数据最高位为低,则SDI拉低
RTD_SCLK_Set();
adr<<=1; //数据左移,次高位变为最高位
}
for(i=0;i<8;i )
{
RTD_SCLK_Clr();
if(RTD_SDO)
data|= 0x01;//该位置1
// else
// data|= 0x00;//该位置0
if(i<7)
data<<=1; //数据左移,次高位变为最高位
RTD_SCLK_Set();
}
RTD_CS_Set();
return data;//返回读取到的数据
}
4.4 SPI读MSB ADC值
代码语言:javascript复制/********************************************* *函数名:RTD_READ_MSB() *函数功能:读取MSB寄存器ADC值 *返回值:Rt寄存器高八位 *********************************************/
uint8 RTD_READ_MSB(void)
{
unsigned char MSB = 0;
//uint8 i;
//float Rt;
//float Rt,temperature;
//float c,temp;
RTD_WR_REG(0x80,0x81);//打开VBAIS
Delayms(50);//滤波电容充电
//for(i=0;i<60;i )
//MicroWait(1000);//滤波电容充电
while(MSB < 38) //温度大于-40摄氏度
MSB = RTD_RD_Data(0x01);
//data = data<<8;
//data|= RTD_LSB_Ave_Fliter(5);
//RTD_WR_REG(0x80,0x01);//配置寄存器 关闭VBIAS 减小功耗
//data>>=1; //去掉Fault位
//Rt = (float)data/32768.0*Rref;
// c = Rt/R0 - 1;
// temp = Sqrt(b*b - 4*a*c);
// temperature = (-b temp)/(2*a);
//return Rt;
return MSB;
}
4.5 SPI读LSB ADC值 均值滤波
代码语言:javascript复制/********************************************* *函数名:RTD_LSB_Ave_Fliter(uint8 num) *函数功能:对LSB寄存器读到的数值进行均值滤波 *NUM:读取0x02寄存器次数,即对多少次采样取均值 *返回值:sum/num LSB寄存器均值 *********************************************/
uint8 RTD_LSB_Ave_Fliter(uint8 num)
{
//uint8 data[num];
uint8 i;
unsigned int sum = 0;
for(i=0;i<num;i )
sum = RTD_RD_Data(0x02);
return(sum/num);
}
4.6 头文件相关定义
代码语言:javascript复制#define st(x) do { x } while (__LINE__ == -1)
#define RTD_CS_Clr() st(RTD_CS = 0;)
#define RTD_CS_Set() st(RTD_CS = 1;)
#define RTD_SDI_Clr() st(RTD_SDI = 0;)
#define RTD_SDI_Set() st(RTD_SDI = 1;)
#define RTD_SCLK_Clr() st(RTD_CLK = 0;)
#define RTD_SCLK_Set() st(RTD_CLK = 1;)
void Delayms(uint8 xms);//延时函数
uint8 RTD_LSB_Ave_Fliter(uint8 num);//滤波函数
//RTD控制用函数
void RTD_WR_REG(uint8 adr,uint8 cmd);
uint8 RTD_RD_Data(uint8 adr);
void RTD_Init(void);
uint8 RTD_READ_MSB(void);
4.7 主函数
代码语言:javascript复制/*************************** //主函数 ***************************/
void main(void)
{
RTD_Init();
RTD_READ_MSB();
RTD_LSB_Ave_Fliter(5);
}
五、PCB
图4.1 MAX31865模块4线制电路图
图4.2 MAX31865模块3线制电路图
图4.3 MAX31865模块2线制电路图
根据芯片手册接线原理图(图4.1-4.3)可以绘制出如图4.4所示的原理图,BJ1 2 3 用于选择线制。
图4.4 MAX31865 3.3MCU电路图
需要注意的是,如图4.5所示,MAX31865模块为了能够实现5V电压输入和5V供电单片机的适配会在接单片机的引脚处上拉3.3V,并增加二极管,防止5V电平直接加在MAX31865上,损坏芯片。
图4.5 MAX31865 5VMCU电路图
参考文献
https://learn.adafruit.com/adafruit-max31865-rtd-pt100-amplifier?view=all https://blog.csdn.net/x1131230123/article/details/105446353 https://wenku.baidu.com/view/d32856ee940590c69ec3d5bbfd0a79563c1ed408?qq-pf-to=pcqq.group&bfetype=new https://blog.csdn.net/worf__/article/details/99686799
相关代码和资料已上传至CSDN下载中心。
感谢阅读到最后,转载请注明出处,原创不易,点个赞再走呗。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/148183.html原文链接:https://javaforall.cn