热电偶是一种感温元件 , 它把温度信号转换成热电动势信号 , 通过电气仪表转换成被测介质的温度。热电偶测温的基本原理是两种不同成份的均质导体组成闭合回路 , 当两端存在温度梯度时 , 回路中就会有电流通过,此时两端之间就存在 Seebeck 电动势——热电动势,这就是所谓的塞贝克效应。两种不同成份的均质导体为热电极,温度较高的一端为工作端, 温度较低的一端为自由端,自由端通常处于某个恒定的温度下。根据热电动势与温度的函数关系 , 制成热电偶分度表 ; 分度表是自由端温度在 0 ℃ 时 的条件下得到的,不同的热电偶具有不同的分度表。在热电偶回路中接入第三种金属材料时 , 只要该材料两个接点的温度相同 , 热电偶所产生的热电势将保持不变,即不受第三种金属接入回路中的影响。因此 , 在热电偶测温时 , 可接入测量仪表 , 测得热电动势后 , 即可知道被测介质的温度。
热电偶的种类
K 型(镍铬 - 镍硅) WRN 系列 N 型(镍铬硅 - 镍硅镁) WRM 系列
E 型(镍铬 - 铜镍) WRE 系列 J 型(铁 - 铜镍) WRF 系列
T 型(铜 - 铜镍) WRC 系列 S 型(铂铑 10- 铂) WRP 系列
R 型(铂铑 13- 铂)WRQ系列 B 型(铂铑 30- 铂铑 6 )WRR 系列
热电偶作为一种主要的测温元件,具有结构简单、制造容易、使用方便、测温范围宽、测温精度高等特点。但是将热电偶应用在基于单片机的嵌入式系统领域时,却存在着以下几方面的问题。①非线性:热电偶输出热电势与温度之间的关系为非线性关系,因此在应用时必须进行线性化处理。②冷补偿:热电偶输出的热电势为冷端保持为0℃时与测量端的电势差值,而在实际应用中冷端的温度是随着环境温度而变化的,故需进行冷端补偿。③数字化输出:与嵌入式系统接口必然要采用数字化输出及数字化接口,而作为模拟小信号测温元件的热电偶显然法直接满足这个要求。因此,若将热电偶应用于嵌入式系统时,**须进行复杂的信号放大、A/D转换、查表线性线、温度补偿及数字化输出接口(a)**等软硬件设计。如果能将上述的功能集成到一个集成电路芯片中,即采用单芯片来完成信号放大、冷端补偿、线性化及数字化输出功能,则将大大简化热电偶在嵌入式领域的应用设计。
热电偶工作原理:
当有两种不同的导体或半导体A和B组成一个回路,其两端相互连接时,只要两结点处的温度不同,一端温度为T,称为工作端或热端,另一端温度为T0 ,称为自由端(也称参考端)或冷端,回路中将产生一个电动势,该电动势的方向和大小与导体的材料及两接点的温度有关。这种现象称为“热电效应”,两种导体组成的回路称为“热电偶”,这两种导体称为“热电极”,产生的电动势则称为“热电动势”。热电动势由两部分电动势组成,一部分是两种导体的接触电动势,另一部分是单一导体的温差电动势。
(摘自《传感器原理》)
MAX6675满足了(a)条件,即集其成了热电偶放大器、冷端补偿、A/D转换器及SPI串口的热电偶放大器与数字转换器。
MAX6675冷端温度补偿、热电偶数字转换器可进行冷端温度补偿,并将K型热电偶信号转换成数字信号。数据以SPI™兼容的12位分辨率只读格式输出。该转换器可将温度解析为0.25°C,允许读数高达+ 1024°C。在0°C至+ 700°C温度范围内具有8LSB的热系数精度。
MAX6675的主要特性如下:
①简单的SPI串行口温度值输出;
②0℃~+1024℃的测温范围;
③12位0.25℃的分辨率;
④片内冷端补偿;
⑤高阻抗差动输入;
⑥热电偶断线检测;
⑦单一+5V的电源电压;
⑧低功耗特性;
⑨工作温度范围-20℃~+85℃;
⑩2000V的ESD信号。
备注:该器件采用8引脚SO帖片封装。
引脚 名称 功能
1 GND 接地端
2 T- K型热电偶负极
3 T+ K型热电偶正极
4 VCC 正电源端
5 SCK 串行时钟输入
6 CS 片选端,CS为低时、启动串行接口
7 SO 串行数据输出
8 N.C. 空引脚
MAX6675内部具有将热电偶信号转换为与ADC输入通道兼容电压的信号调节放大器,T+和T-输入端连接到低噪声放大器A1,以保证检测输入的高精度,同时使热电偶连接导线与干扰源隔离。热电偶输出的热电势经低噪声放大器A1放大,再经过A2电压跟随器缓冲后,被送至ADC的输入端。在将温度电压值转换为相等价的温度值之前,它需要对热电偶的冷端温度进行补偿,冷端温度即是MAX6675周围温度与0℃实际参考值之间的差值。对于K型热电偶,电压变化率为41μV/℃,电压可由线性公式**Vout=(41μV/℃)×(tR-tAMB)**来近似热电偶的特性。上式中,Vout为热电偶输出电压(mV),tR是测量点温度;tAMB是周围温度。
典型应用电路显示了MAX6675与微控制器接口。 MAX6675处理来自热电偶的读数,并通过串行接口传输数据。强制CS为低电平并在SCK处施加时钟信号以读取SO的结果。 强制CS低立即停止任何转换过程。 发起新的转化通过迫使CS高来进行处理。强制CS为低电平以输出SO引脚上的第一位。 一个完整的串行接口读取需要16个时钟周期。在时钟的下降沿读取16个输出位。第一位D15是伪符号位,始终为零。 D14–D3位包含转换后的温度从MSB到LSB的顺序。 D2位通常为低电平且当热电偶输入打开时变为高电平。 D1是低电平,为MAX6675和D0位提供器件ID是三态。数据格式如下图:
(以上介绍官方芯片手册翻译过来,若有错误欢迎评论指出)
max6675 头文件
#ifndef __max6675_H
#define __max6675_H
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
typedef struct __MAX6675
{
u16 temperatureBasic;
long temp;
float temperatureHandle;
u8 checkFlag;
}MAX6675;
extern MAX6675 max6675;
#define MAX6675PORT GPIOA
#define MAX6675PIN_CLK GPIO_Pin_11
#define MAX6675PIN_SO GPIO_Pin_12
#define MAX6675PIN_CS GPIO_Pin_6
#define MAX6675CLK RCC_APB2Periph_GPIOA
//IO operation function
#define MAX6675_CS PAout(6)
#define MAX6675_CLK PAout(11)
#define MAX6675_SO PAin(12)
//Function declaration
void max6675_Init(void);
u16 max6675_ReadData(void);
void max6675_HandleData(void);
void max6675_ReadDataCnt(u16 count);
void max6675_ExcuteTest(void);
void max6675_TimeBase_Init(u16 arr,u16 pre);
#endif
max6675 C文件
#include "max6675.h"
#include "usart.h"
MAX6675 max6675={0,0,0.0,0};
/*
* Function name: initialize MAX6675
* author: liuxianfei0810
* Parameter: None
* Return value: None
*/
void max6675_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_APB2PeriphClockCmd(MAX6675CLK,ENABLE);//Turn on the clock
//Initialization pin
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=MAX6675PIN_CLK|MAX6675PIN_CS;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(MAX6675PORT,&GPIO_InitStruct);
GPIO_SetBits(MAX6675PORT,MAX6675PIN_CLK|MAX6675PIN_CS);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin=MAX6675PIN_SO;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(MAX6675PORT,&GPIO_InitStruct);
MAX6675_CLK=MAX6675_CS=1;
}
u16 max6675_ReadData(void)
{
u16 dat=0;
u16 i=0;
//时序中各时间延时如下:(根据官方手册)
/*
fSCL <= 4.3MHz
tCH >= 100ns
tCL >= 100ns
tCSS >= 100ns
tDV <= 100ns
tTR <= 100ns
tDO <= 100ns
*/
MAX6675_CLK=0;
MAX6675_CS=0;
for(i=0;i<16;i++)
{
MAX6675_CLK=1;
delay_us(1);
dat<<=1;
if(MAX6675_SO)
dat|=0x01;
MAX6675_CLK=0;
delay_us(1);
}
MAX6675_CS=1;
max6675.temperatureBasic=dat;
return dat;
}
void max6675_HandleData(void)
{
max6675.temperatureBasic>>=3;
max6675.temperatureBasic&=~(0xf<<12);
max6675.temperatureHandle=(float)max6675.temperatureBasic*0.25;
}
void max6675_ReadDataCnt(u16 count)
{
u16 i=0;
max6675.temp=0;
max6675.temperatureBasic=0;
max6675.temperatureHandle=0.0;
for(i=0;i<count;i++)
{
max6675.temp+= max6675_ReadData();
delay_ms(1);
}
max6675.temperatureBasic=(u16)(max6675.temp/count);
}
void max6675_ExcuteTest(void)
{
if(max6675.checkFlag)
{
max6675.checkFlag=0;
//close timer
max6675_ReadDataCnt(20);
// max6675_ReadData();
max6675_HandleData();
printf("\r\nMAX6675采集的原始数据为: %d \r\n\r\n",max6675.temperatureBasic);
printf("\r\nMAX6675处理后的数据为: %f 度\r\n\r\n",max6675.temperatureHandle);
TIM_Cmd(TIM2,ENABLE);
}
else;
}
void max6675_TimeBase_Init(u16 arr,u16 pre)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//Turn on the clock
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=arr;
TIM_TimeBaseInitStruct.TIM_Prescaler=pre;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE );
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
TIM_Cmd(TIM2,ENABLE);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
{
max6675.checkFlag=1;
}
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
TIM_Cmd(TIM2,DISABLE);
}
备注:通过定时器延时,具体延时时间自己按要求设定