基于max6675的分布式温度测量系统设计
<div class='showpostmsg'> 本帖最后由 宜城龙山 于 2023-10-26 11:09 编辑<p align="center"><b>基于</b><b>max6675</b><b>的分布式温度测量系统设计</b></p>
<p> </p>
<p>热电偶作为一种主要的测温元件,具有结构简单、制造容易、使用方便、测温范围宽、测温精度高等特点。但是将热电偶自身存在以下不足:①非线性:热电偶输出热电势与温度之间的关系为非线性关系,故在应用时须进行线性化处理。②冷补偿:热电偶输出的热电势为冷端保持为0℃时与测量端的电势差值,实际应用时冷端的温度会随着环境温度的变化而变化,因此需进行冷端补偿。③输出量值小:热电偶的输出为模拟小信号,通常在mv量级,不能直接与MCU连接,需经线性放大后经AD转换后输入到MCU进行处理。因此,在工业应用中通常做法是:先将热电偶的输出信号经运放对信号放大、A/D转换送入MCU,在使用分段查表线性化、温度补偿等软件处理后,能获得所需的结果,不仅软硬件设计复杂,而且系统误差较大,给一般使用者带来较大的难度。工程开发人员迫切需求一款集信号采集放大、冷端补偿、线性化及数字化输出功能的热电偶温度转换单芯片。</p>
<p>ADI公司推出的MAX6675即是一款集成了热电偶放大器、冷端补偿、A/D转换及SPI串口通信的热电偶温度转换芯片。</p>
<p>1、性能特点</p>
<p>MAX6675的主要特性如下:</p>
<ul>
<li>通信接口:SPI串行口输出温度值</li>
<li>测温范围:0℃~+1024℃</li>
<li>分辨率:12位,0.25℃</li>
<li>冷端补偿:片内</li>
<li>输入方式:高阻抗差动</li>
<li>电源电压:单一+5V</li>
<li>工作温度范围:-20℃~+85℃</li>
<li>ESD:2000V</li>
<li>具有热电偶断线检测功能</li>
</ul>
<p>该器件采用8引脚SO帖片封装。引脚排列如图1所示,引脚功能如表1所列。</p>
<p align="center"> </p>
<div style="text-align: center;">
<div style="text-align: center;"></div>
<p>图1 MAX6675 引脚图</p>
</div>
<p align="left">表1 MAX6675 引脚功能</p>
<table align="center" style="border-collapse:collapse; border:none">
<tbody>
<tr>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">序号</p>
</td>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p align="center">名 称</p>
</td>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p align="center">功 能</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">1</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">GND</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">接地端</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">2</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">T-</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">K型热电偶负极</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">3</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">T+</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">K型热电偶正极</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">4</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">V<sub>CC</sub></p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">电源正</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">5</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">SCK</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">时钟信号输入端</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">6</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"></p>
<p> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">片选信号,</p>
为低时启动串行口
<p> </p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">7</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">SO</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">串行数据输出端</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">8</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">N.C.</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="left">空引脚</p>
</td>
</tr>
</tbody>
</table>
<p>2、工作原理</p>
<p>MAX6675的内部结构如图2所示。内部主要由信号调节放大器(A1、A2)、12位的模拟/数字转换器(ADC)、冷端补偿传感和校正(COLD_JUNCTION COMPENSATION DIODE)、数字控制器(DIGTAL CONTROLLER)、1个SPI兼容接口及相关的逻辑控制。</p>
<p align="center"> </p>
<div style="text-align: center;">
<div style="text-align: center;"></div>
<p>图2 MAX6675 内部结构图</p>
</div>
<p> </p>
<p>2.1 温度变换</p>
<p>MAX6675的T+和T-输入端连接到低噪声放大器A1,以保证检测输入的高精度,同时可起到将热电偶连接导线与干扰源隔离的作用。热电偶输出的热电势经低噪声放大器A1放大,再经过A2电压跟随器缓冲后,被送至ADC的输入端。在将温度电压值转换为对应的温度值之前,需要对热电偶的冷端温度进行补偿,冷端温度即是MAX6675周围温度与0℃实际参考值之间的差值。对于K型热电偶,电压变化率为41μV/℃,输出电压可由下面的线性公式来近似热电偶的输出电压值:</p>
<p align="center">V<sub>out</sub>=41×(t<sub>R</sub>-t<sub>AMB</sub>)</p>
<p>上式中,V<sub>out</sub>为热电偶输出电压(mV),t<sub>R</sub>是测量点温度;t<sub>AMB</sub>是周围温度。</p>
<p>2.2 冷端补偿</p>
<p>热电偶是通过检测热、冷两端温度的差值,其节点温度可在0℃~+1023.75℃范围变化。冷端即安装MAX6675的电路板周围温度,其温度变化范围在-20℃~+85℃内。当冷端温度波动时,需要通过补偿来消除检测误差。</p>
<p>MAX6675是通过内部的温度检测二极管将周围温度转换为温度补偿电压,并与电偶电压一起送到ADC中转换,以计算热电偶的热端温度。当热电偶的冷端与芯片温度相等时,MAX6675可获得最佳的测量精度。因此在实际测温应用时,应尽量避免在MAX6675附近放置发热器件或元件,因为这样会造成冷端误差。</p>
<p>2.3 噪声补偿</p>
<p>MAX6675的测量精度对电源耦合噪声较敏感。为降低电源噪声影响,可在MAX6675的电源引脚附近接入1只0.1μF陶瓷旁路电容。</p>
<p>2.4 SPI串行接口</p>
<p>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位为三态。</p>
<div style="text-align: center;"></div>
<p align="center">图3 MAX6675 与MCU连接示意图</p>
<p> </p>
<table style="border-collapse:collapse; border:none">
<tbody>
<tr>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:1px solid black" valign="top">
<p>位</p>
</td>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p align="center">空标志位</p>
</td>
<td colspan="12" style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p>12位温度值</p>
</td>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p align="center">热电偶输入</p>
</td>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p>设备身份</p>
</td>
<td style="border-bottom:1px solid black; border-top:1px solid black; border-right:1px solid black; border-left:none" valign="top">
<p>状态</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center">位</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">15</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">14</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">13</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">12</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">11</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">10</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">9</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">8</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">7</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">6</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">5</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">4</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">3</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">2</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">1</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">0</p>
</td>
</tr>
<tr>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:1px solid black" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">0</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">MSB</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center">LSB</p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
<td style="border-bottom:1px solid black; border-top:none; border-right:1px solid black; border-left:none" valign="top">
<p align="center"> </p>
</td>
</tr>
</tbody>
</table>
<p align="center">图4 MAX6675 SO端输出数据的格式</p>
<div style="text-align: center;"></div>
<p align="center">图5 MAX6675 SPI接口时序</p>
<p>3、 测温应用</p>
<p>下面给出MAX6675应用于嵌入式系统的具体方法。我们在实际开发应用过程中,需要进行多点温度测量,考虑到系统测量误差的一致性,这里我们选择多路开关控制测量端热电偶的接入,变换电路采用单片MAX6675,主控MCU选择沁恒CH32V307VCT6,图6给出MAX6675与MCU构成的测温电路,及相应的温度值读取、转换程序。</p>
<p>MAX6675与CH32V307VCT6 MCU的接口电路如图6所示。</p>
<div style="text-align: center;"></div>
<div style="text-align: center;"></div>
<p align="center">图6 MAX6675与CH32V307VCT6 MCU的接口电路图</p>
<p align="center"> </p>
<div>本例使用CH32V307VCT6 MCU的SPI1总线接口与MAX6675进行通信,PA5为SPI1的串行时钟输出端(SCK),PA6为SPI1的串行数据输入端(MISO), PA4为MAX6675的片选信号(</div>
<p>),TCS0、TCS1、TCS2为多路开关的选择信号,000~111分别对应1~8号热电偶。由于涉及到一些商业问题,图中仅给出MAX6675的信号连接部分,请谅解。</p>
<p> </p>
<p>下面给出相应的温度值读取程序及数据转换程序。SPI_MAX6675_Init()为SPI1端口初始化函数,MAX6675_ReadByte()为读SPI端口数据函数,Get_max6675temp()为温度读取转换函数。程序运行结果如图7。</p>
<div style="text-align: center;"></div>
<p align="center">图7 运行结果</p>
<p>4 总结</p>
<p>由以上实例,我们可以看出,MAX6675具有电路设计简单、使用方便、可扩展性好等特点,但我们也应该看到MAX6675也有自身的不足,单此转换时间较长,按照手册说明要求,转换时间大于0.2S。因此,对于一些高速场景不太适合。整体来说,MAX6675是一款高性价比的K型热电偶温度转换芯片。</p>
<p> </p>
<pre>
<code>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);
}
//读温度
/*
********************************************************************************
** @name : 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;
}
</code></pre>
<pre>
<code>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</code></pre>
<p align="left"> </p>
<p> </p>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]