本帖最后由 宜城龙山 于 2023-10-26 11:09 编辑
基于max6675的分布式温度测量系统设计
热电偶作为一种主要的测温元件,具有结构简单、制造容易、使用方便、测温范围宽、测温精度高等特点。但是将热电偶自身存在以下不足:①非线性:热电偶输出热电势与温度之间的关系为非线性关系,故在应用时须进行线性化处理。②冷补偿:热电偶输出的热电势为冷端保持为0℃时与测量端的电势差值,实际应用时冷端的温度会随着环境温度的变化而变化,因此需进行冷端补偿。③输出量值小:热电偶的输出为模拟小信号,通常在mv量级,不能直接与MCU连接,需经线性放大后经AD转换后输入到MCU进行处理。因此,在工业应用中通常做法是:先将热电偶的输出信号经运放对信号放大、A/D转换送入MCU,在使用分段查表线性化、温度补偿等软件处理后,能获得所需的结果,不仅软硬件设计复杂,而且系统误差较大,给一般使用者带来较大的难度。工程开发人员迫切需求一款集信号采集放大、冷端补偿、线性化及数字化输出功能的热电偶温度转换单芯片。
ADI公司推出的MAX6675即是一款集成了热电偶放大器、冷端补偿、A/D转换及SPI串口通信的热电偶温度转换芯片。
1、性能特点
MAX6675的主要特性如下:
- 通信接口:SPI串行口输出温度值
- 测温范围:0℃~+1024℃
- 分辨率:12位,0.25℃
- 冷端补偿:片内
- 输入方式:高阻抗差动
- 电源电压:单一+5V
- 工作温度范围:-20℃~+85℃
- ESD:2000V
- 具有热电偶断线检测功能
该器件采用8引脚SO帖片封装。引脚排列如图1所示,引脚功能如表1所列。
表1 MAX6675 引脚功能
序号
|
名 称
|
功 能
|
1
|
GND
|
接地端
|
2
|
T-
|
K型热电偶负极
|
3
|
T+
|
K型热电偶正极
|
4
|
VCC
|
电源正
|
5
|
SCK
|
时钟信号输入端
|
6
|
|
片选信号,
为低时启动串行口
|
7
|
SO
|
串行数据输出端
|
8
|
N.C.
|
空引脚
|
2、工作原理
MAX6675的内部结构如图2所示。内部主要由信号调节放大器(A1、A2)、12位的模拟/数字转换器(ADC)、冷端补偿传感和校正(COLD_JUNCTION COMPENSATION DIODE)、数字控制器(DIGTAL CONTROLLER)、1个SPI兼容接口及相关的逻辑控制。
2.1 温度变换
MAX6675的T+和T-输入端连接到低噪声放大器A1,以保证检测输入的高精度,同时可起到将热电偶连接导线与干扰源隔离的作用。热电偶输出的热电势经低噪声放大器A1放大,再经过A2电压跟随器缓冲后,被送至ADC的输入端。在将温度电压值转换为对应的温度值之前,需要对热电偶的冷端温度进行补偿,冷端温度即是MAX6675周围温度与0℃实际参考值之间的差值。对于K型热电偶,电压变化率为41μV/℃,输出电压可由下面的线性公式来近似热电偶的输出电压值:
Vout=41×(tR-tAMB)
上式中,Vout为热电偶输出电压(mV),tR是测量点温度;tAMB是周围温度。
2.2 冷端补偿
热电偶是通过检测热、冷两端温度的差值,其节点温度可在0℃~+1023.75℃范围变化。冷端即安装MAX6675的电路板周围温度,其温度变化范围在-20℃~+85℃内。当冷端温度波动时,需要通过补偿来消除检测误差。
MAX6675是通过内部的温度检测二极管将周围温度转换为温度补偿电压,并与电偶电压一起送到ADC中转换,以计算热电偶的热端温度。当热电偶的冷端与芯片温度相等时,MAX6675可获得最佳的测量精度。因此在实际测温应用时,应尽量避免在MAX6675附近放置发热器件或元件,因为这样会造成冷端误差。
2.3 噪声补偿
MAX6675的测量精度对电源耦合噪声较敏感。为降低电源噪声影响,可在MAX6675的电源引脚附近接入1只0.1μF陶瓷旁路电容。
2.4 SPI串行接口
MAX6675采用标准的SPI串行外设总线与MCU接口如图3所示,且MAX6675只能作为从设备。MAX6675 SO端输出温度数据的格式如图4所示,MAX6675 SPI接口时序如图5所示。依据MAX6675手册可知,MAX6675从SPI串行接口输出数据的过程如下:MCU使CS变低并提供时钟信号给SCK,由SO读取测量结果。CS变低将停止任何转换过程;CS变高将启动一个新的转换过程。一个完整串行接口读操作需16个时钟周期,在时钟的下降沿读16个输出位,第1位和第15位是一伪标志位,并总为0;第14位到第3位为以MSB到LSB顺序排列的转换温度值;第2位一般为低,当热电偶输入端开路时为高,因此,可依据该位检测热电偶输入端是否开路;第1位为低以提供MAX6675器件身份码,第0位为三态。
图3 MAX6675 与MCU连接示意图
位
|
空标志位
|
12位温度值
|
热电偶输入
|
设备身份
|
状态
|
位
|
15
|
14
|
13
|
12
|
11
|
10
|
9
|
8
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
|
0
|
MSB
|
|
|
|
|
|
|
|
|
|
|
LSB
|
|
|
|
图4 MAX6675 SO端输出数据的格式
图5 MAX6675 SPI接口时序
3、 测温应用
下面给出MAX6675应用于嵌入式系统的具体方法。我们在实际开发应用过程中,需要进行多点温度测量,考虑到系统测量误差的一致性,这里我们选择多路开关控制测量端热电偶的接入,变换电路采用单片MAX6675,主控MCU选择沁恒CH32V307VCT6,图6给出MAX6675与MCU构成的测温电路,及相应的温度值读取、转换程序。
MAX6675与CH32V307VCT6 MCU的接口电路如图6所示。
图6 MAX6675与CH32V307VCT6 MCU的接口电路图
本例使用CH32V307VCT6 MCU的SPI1总线接口与MAX6675进行通信,PA5为SPI1的串行时钟输出端(SCK),PA6为SPI1的串行数据输入端(MISO), PA4为MAX6675的片选信号(
),TCS0、TCS1、TCS2为多路开关的选择信号,000~111分别对应1~8号热电偶。由于涉及到一些商业问题,图中仅给出MAX6675的信号连接部分,请谅解。
下面给出相应的温度值读取程序及数据转换程序。SPI_MAX6675_Init()为SPI1端口初始化函数,MAX6675_ReadByte()为读SPI端口数据函数,Get_max6675temp()为温度读取转换函数。程序运行结果如图7。
图7 运行结果
4 总结
由以上实例,我们可以看出,MAX6675具有电路设计简单、使用方便、可扩展性好等特点,但我们也应该看到MAX6675也有自身的不足,单此转换时间较长,按照手册说明要求,转换时间大于0.2S。因此,对于一些高速场景不太适合。整体来说,MAX6675是一款高性价比的K型热电偶温度转换芯片。
MAX6675_SP.c
#include <MAX6675_SP.h>
#include "stdio.h"
#include "ch32v30x.h"
max6675_read Read_max6675_temp;
uint8_t MAX6675_ReadByte(uint8_t cc);
//MAX6675初始化
void SPI_MAX6675_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
/* 使能 SPI1 时钟 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);
/* ---------通信I/O初始化----------------
* PA5-SPI1-SCK :MAX6675_SCK
* PA6-SPI1-MISO:MAX6675_SO
* PA7-SPI1-MOSI:MAX6675_SI
*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 复用输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* ---------控制I/O初始化----------------*/
/* PA4-SPI1-NSS:MAX6675_CS */ // 片选
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推免输出
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA, GPIO_Pin_4); // 先把片选拉高,真正用的时候再拉低
/* SPI1 配置 */
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_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
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_Init(SPI1, &SPI_InitStructure);
/* 使能 SPI1 */
SPI_Cmd(SPI1, ENABLE);
printf("max6675 Init Ok! \r\n");
}
//读数据
uint8_t MAX6675_ReadByte(uint8_t cc)
{
while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPI1, 0xff);
while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
return SPI_I2S_ReceiveData(SPI1);
}
//读温度
/*
********************************************************************************
** [url=home.php?mod=space&uid=32621]@name[/url] : Get_max6675temp
** @函数功能 : 获取MAX6675读取的热电偶的值
** @函数说明 :K型热电偶读取函数
** @输入参数 :K型热电偶读取函数
** @输出参数 :成功返回TRUE 否者热电偶
********************************************************************************
*/
float Get_max6675temp()
{
uint8_t c=0x00,flag;
u16 i,t;
float temprature;
Read_max6675_temp.readtemp_timer = 0;
MAX6675_CSL();
c = MAX6675_ReadByte(c);
i = c;
i = i<<8;
c = MAX6675_ReadByte(c);
MAX6675_CSH();
i = i|c; //i是读出来的原始数据
flag = i&0x04; //flag保存了热电偶的连接状态
t = i>>3;
temprature =(float)1023.75*t/4096;
if(i!=0) //max6675有数据返回
{
if(flag==0) //热电偶已连接
{
printf("temperature: %4.2f \r\n",temprature);
}
}
else //max6675没有数据返回
{
printf("The thermocouple is not connected\r\n");
}
return temprature;
}
MAX6675_SP.h
#ifndef _MAX6675_H
#define _MAX6675_H
#include "stdio.h"
#define MAX6675_CS_PORT GPIOA
#define MAX6675_CS_PIN GPIO_Pin_4
#define MAX6675_CSL() GPIO_ResetBits(MAX6675_CS_PORT, MAX6675_CS_PIN)
#define MAX6675_CSH() GPIO_SetBits(MAX6675_CS_PORT, MAX6675_CS_PIN)
void SPI_MAX6675_Init(void);
float Get_max6675temp();
#endif