本文阐述了B型热电偶的实现TCB使用19位温度测量的相关内容ADC数字转换器MAX31856进行转换
目录
- 前言
- 1、热电偶的定义和原理
-
- 1.定义热电偶
- 2.热电偶的温度测量原理
- 3.热电偶的技术优势
- 四、常见热电偶参数
- 二、硬件设计
-
- 2.1主控芯片及外围电路
- 2.2MAX31856及TCB测温模块
- 2.3DS1302时间模块
- 2.4数码管模块
- 三、软件设计
-
- 3.软件设计过程
- 3.2 串口收发软件设计(及数码管)
- 3.3MAX31856的软件设计
- 3.4 DS1302的软件设计
- 3.5 处理温度数据
- 附录
-
- 附录1 完整的系统电路
- 附录2 MAX31856的SPI通信时序要求
- 附录3 MAX31856寄存器
- 附录4 DS1302通信时序
- 附录5 程序源码
-
- allfunc.h
- main.c
- max31856.h
- max31856.c
- uart0.h
- uart0.c
- ds1302.h
- ds1302.c
前言
它是工业环境中非常重要的数据。本课题采用来测量800~1200℃的工业环境温度,并通过串口形式发送到温度和时间的数据。 热电偶是一种基于热电效应的温度测量元件。它结构简单,坚固耐用,使用方便,精度高,测量范围广,易于长距离、多点、集中测量和自动控制,是一种广泛使用的温度计。通过19位ADC的来对热电偶两端的电压进行数字转换,转换器温度分辨率达0.0078125°C,允许读得最高 1800°C、最低-210°C (取决于热电偶类型)温度读数,热电偶电压测量精度达到±0.15%。
1、热电偶的定义和原理
1.定义热电偶
热电偶(thermocouple)它是温度测量中常用的温度测量元件。它可以直接测量温度,将温度信号转换为热电势信号,并通过仪器转换为被测介质的温度。
2.热电偶的温度测量原理
热电偶温度测量的基本原理是两种不同成分的材料导体形成闭合电路。当两端温差时,电流通过电路,两端之间存在电势-热电势。两种不同成分的均质导体为热电极,温度较高的一端为工作端,温度较低的一端为自由端,自由端通常处于恒温下。热电偶分度表是根据热电势与温度之间的函数关系制成的;分度表是自由端温度为0℃不同的热电偶有不同的分度表,可以通过网络轻松找到。
3.热电偶的技术优势
热电偶测温范围广,性能稳定,精度高。热电偶通常与被测介质直接接触,不受中间介质的影响。性能可靠,机械强度好。使用寿命长,组装简单方便。
四、常见热电偶参数
热电偶的型号主要有S型,R型、B型、N型、K型、E型、J几种类型和T型S、R、B属于贵金属热电偶(即铂铑热电偶),N、K、E、J、T属廉金属热电偶。
- S 铂铑合金(铑含量10 %) 纯铂 0-1600
- R 铂铑合金(铑含量133) %) 纯铂 0-1600
- B 铂铑合金(铑含量30%) 铂铑合金(铑含量6%) ) 0-1800
- K 镍铬镍硅 0-1300
- T 纯铜 铜镍 0-350
- J 铁 铜镍 0- 500
- N 镍铬硅 镍硅 0- 800
- E 镍铬 铜镍 0-600 热电偶类型: 装配热电偶、铠装热电偶、端面热电偶、压簧固定热电偶、高温热电偶、铂铑热电偶、防腐热电偶、耐磨热电偶、高压热电偶、特殊热电偶、手持式热电偶、微型热电偶、贵金属热电偶 ,快速热电偶、钨磷热电偶、单芯铠装热电偶等。
常用的热电偶温度势转换公式及相应表
二、硬件设计
2.1主控芯片及外围电路
MSP430F249的XT2OUT、XT2IN接8MHz晶振电路,XOUT、XIN接32.768KHz晶振电路。电路图如下图所示。
2.2MAX31856及TCB测温模块
将MAX31856的CS、SCK、SDI、SDO分别与MSP430F249的P11、P33、P31、P32连接。将DRDY接到LED1的负极,将FAULT接到LED两种情况分别发生负极。其中,在T 、T-在数据高电平时,应在两端添加103和104滤波电容器以滤除噪声DVDD将噪音连接到地面进行过滤。 当热电偶线与不同的金属接触时,通常在连接处或与PCB的焊接处“( 冷端)形成额外的热电偶。为了补偿这些额外的热电偶引起的误差,必须测量冷端温度。这是通过-20内部高精度温度传感器实现的°C至 85°C在温度范围内,精度优于±0.7°C。通过将MAX31856安装在冷端附近,可测量冷端温度,补偿冷端效应。 MAX31856的位置,因为MAX31856包括内部冷端温度传感器,将其安装在温度尽可能接近冷端的位置。如果热电偶引线直接焊接PCB,MAX31856应尽量靠近热电偶引线,尽量减少IC热梯度与热电偶连接。如果热电偶引线端接在连接器上,IC尽量靠近连接器安装,尽量减少连接器和IC热梯度之间。
2.3DS1302时间模块
DS1302需要一个32.768KHz晶振提高时钟频率,其电路图如图3-5所示。
2.4数码管模块
三、软件设计
请参见附录5。
3.1软件设计流程
软件开始需要进行初始化,然后读时间和对温度然后通过串口发送数据进行显示,之后进入低功耗休眠模式。低功耗模式下,定时器继续工作,当到达一定时间后,退出休眠模式。从而,可以实现周而复始地读取时间和温度,以及发送时间和温度数据并通过串口显示。软件设计流程图如图所示。
3.2 串口收发软件设计(及数码管)
由于串口的收发内容的形式是ASCII码,因此要进行发送时,首先将要发送的内容转换成为字符串格式。对此,可以使用stdio.h中的sprintf函数。其使用功能如下。 int sprintf(char *str, const char *format, …) 发送格式化输出到 str 所指向的字符串。但是,对于IAR平台而言,不支持对浮点数据的转换,所以在将浮点数转换成字符串时,可以将它分成整数和小数两个部分的整数进行转换。 将转换后的字符串依次送入发送寄存器UCA0TXBUF中,及实现了将时间和温度数据发送到串口显示的功能。 对于数码管,它仅用于显示温度数据。将获得的温度数据通过数学方法得到每一位数码管要显示的数字,然后通过定时器中断循环实现数码管的动态显示。
3.3MAX31856的软件设计
MAX31856的数据传输是通过SPI协议进行的,其通信的时序参数要求见附录2。 对于MSP430F249的USCI中的SPI模块,在进行通信时无法按照MAX31856的SPI通信时序来进行。故此,使用4个普通IO口来模拟SPI通信。下面展示读写MAX31856寄存器的程序。
uchar max31856_read_register(uchar addr)
{
CS_Low;
uchar i;
uchar dat;
addr &= ~0x80;
for (i = 0; i < 8; i++)
{
SCK_Low;
if (addr & 0x80)
SIMO_High;
else
SIMO_Low;
addr <<= 1;
SCK_High; //上升沿数据采样
}
for (i = 0; i < 8; i++)
{
SCK_Low;
SCK_High;
dat <<= 1; //高位在前
if (SOMI_IN)
dat |= 0x01;
else
dat &= ~0x01;
}
CS_High;
return dat;
}
void max31856_write_register(uchar addr, uchar data)
{
addr |= 0x80;
CS_Low;
uchar i;
for (i = 0; i < 8; i++)
{
SCK_Low;
if (addr & 0x80)
SIMO_High;
else
SIMO_Low;
addr <<= 1;
SCK_High; //上升沿数据采样
}
for (i = 0; i < 8; i++)
{
SCK_Low;
if (data & 0x80)
SIMO_High;
else
SIMO_Low;
data <<= 1;
SCK_High; //上升沿数据采样
}
CS_High;
}
与MAX31856的通信通过16个包含转换、状态和配置数据的8位寄存器实现,全部设置均通过选择相应寄存器单元的对应地址完成,寄存器存储器映射所示为温度、状态和配置寄存器的地址。存取寄存器时,使用地址0Xh为读操作,地址8Xh为写操作。读写数据时,寄存器MSB在前。如果对只读寄存器执行写操作,不改变该寄存器的值。 对于MAX31856简单初始化而言,需要设置的寄存器有CR0、CR1、MASK这三个寄存器,其详细位说明见附录3。而读取温度时,仅需要读取寄存器LTCBH、LTCBM、LTCBL即可。 MAX31856将冷端温度数据储存在寄存器0Ah和0Bh。使能冷端温度检测时,这些寄存器为只读,其中包含实测冷端温度加冷端失调寄存器的数值。冷端温度检测使能时,读取寄存器操作将DRDY引脚复位为高电平。应通过多字节传输读取该寄存器的两个字节,以确保两个字节的数据来自同一次温度更新。禁止冷端温度检测时,这些寄存器为可读/写寄存器,其中包含最新的实测温度值。如果需要,禁止内部冷端检测时,可将来自外部温度传感器的数据写入这些传感器。最大冷端温度箝位在128°C,最小温度箝位在-64°C。如果需要,可向冷端失调寄存器(09h)写入温度偏移值。那么寄存器0Ah和0Bh中储存的值将等于实测值加失调值。失调寄存器的MSB为4°C,LSB为0.0625°C。失调值应用到实测冷端温度后得到的结果范围为-8°C至+7.9375°C。默认失调值为0°C (00h)。 热电偶线性化及编码到温度的转换由于所有热电偶都具有非线性,必须对冷端补偿后的原始值进行线性修正,并转换为温度值。为实现这一处理,利用LUT产生经过线性化和冷端补偿的温度值;每次转换后,将其作为19位数据储存在线性化热电偶温度寄存器(0Ch、0Dh和0Eh)中。应通过多字节传输读取全部三个字节,以确保所有数据来自于同一次数据更新。 综上,将MAX31856的CR0寄存器配置为0x80,即设置为连续转换模式;CR1寄存器配置为0x40,即16个采样数据平均,B型热电偶;MASK寄存器配置为0xff;然后按照每5秒读一次线性化热电偶温度寄存器,并将二进制数据转换成对应的温度,通过串口发送和显示在数码管上。 上述寄存器配置的代码如下:
void Max31856_Init(void)
{
max31856_write_register(MAX31856_CR1_REG, 0x40);
max31856_write_register(MAX31856_MASK_REG, 0xff);
max31856_write_register(MAX31856_CR0_REG,0x088);
}
对于读取线性化热电偶温度寄存器(0Ch、0Dh和0Eh)的代码如下:
float thermocouple_read_temperature(void)
{
Unsigned long tc_temp;
temp = max31856_read_register24(MAX31856_LTCBH_REG);
tc_temp >>= 5; // bottom 5 bits are unused
float tc_temp_float = tc_temp;
tc_temp_float *= 0.0078125;
// max31856->thermocouple_c = tc_temp_float;
// max31856->thermocouple_f = (1.8 * tc_temp_float) + 32.0;
return tc_temp_float;
}
3.4 DS1302的软件设计
关于DS1302的通信时序,请见附录4。介绍完其通信时序后,当然少不了要对DS1302的相关控制寄存器的简要说明,其控制寄存器见4-2所示。 它一共有7个时间相关的寄存器,可读可写,读写地址不一样。寄存器地址从低到高分别对应的是秒、分、时、日、月、星期、年份的值。在设置时间和获取时间时,就是直接对这几个寄存器的值进行操作的。可以发现,关于时间的寄存器的格式是BCD码的形式,因此在对时间进行读写时要进行数据转换操作。 对于8F/8E寄存器的最高位WP为写保护,在对寄存器进行写入操作前(包括设置时间操作),应该将WP清零。当写操作结束后,为了避免DS1302不被误写操作,应当将WP置高。 对于串口发送实时时钟相关程序,只需要按照一定的格式发送到串口,然后MSP430F249通过串口接收中断依次获取收到的数据,当达到规定的格式的长度时,将这些数据(ASCII码)转为BCD码后重新写入到DS1302即可。例如串口发送“10:20:30”一共8个字符,(不需要换行,换行会产生错误),然后接收到数据后存入数组中,当数组存入8个数据后进行判断第3个和第5个字符是否j均为 ’ : ’ ,然后将这些数据转为BCD码后设置时间。当然,为了保证获取的时间数据不出错,可以按照时间的范围要求进一步进行判断后才决定是否使用接收到的时间进行设置,然后发送是否设置成功。具体代码如下:
#pragma vector = USCIAB0RX_VECTOR
__interrupt void USCIAB0RX(void)
{
static uchar index = 0;
int hour, minite, second;
timedataset[index++] = UCA0RXBUF;
if (index == 8)
{
index = 0;
if (timedataset[2] == ':' && timedataset[5] == ':')
{
hour = (timedataset[0] - '0') * 10 + (timedataset[1] - '0');
minite = (timedataset[3] - '0') * 10 + (timedataset[4] - '0');
second = (timedataset[6] - '0') * 10 + (timedataset[7] - '0');
if ((hour <= 23 && hour >= 0) && (minite >= 0 && minite <= 59) && (second >= 0 && second <= 59))
{
wdata[2] = (timedataset[0] - '0') << 4 | (timedataset[1] - '0');
wdata[1] = (timedataset[3] - '0') << 4 | (timedataset[4] - '0');
wdata[0] = (timedataset[6] - '0') << 4 | (timedataset[7] - '0');
Set_DS1302(wdata); //设置时间
PutString("\r\nThe time you sent has been set!\r\n");
}
else
PutString("\r\nWorning:The time you sent is wrong!\r\n");
}
else
PutString("\r\nWorning:The time you sent is wrong!\r\n");
}
}
3.5 温度数据的处理
对于热电偶测量的温度可能存在一定误差,为了减小误差可以将采样的温度求平均值操作后输出。对于MAX31856而言,其内部可设置为1、2、4、8、16个采样点求均值的操作。对此,我们可以设置为16个采样点求均值操作。
附录
附录1 系统完整电路
附录2 MAX31856的SPI通信时序要求
MAX31856SPI接口要求 SPI读时序
SPI写时序
SPI单字节读时序
SPI单字节写时序
附录3 MAX31856寄存器
附录4 DS1302通信时序
DS1302读一个字节时序
DS1302写一个字节
附录5 程序源码
allfunc.h
#ifndef _ALL_FUNC_H_
#define _ALL_FUNC_H_
#include <msp430f249.h>
#define CPU (8000000)
#define delay_us(x) (__delay_cycles((double)x*CPU/1000000.0))
#define delay_ms(x) (__delay_cycles((double)x*CPU/1000.0))
typedef unsigned int uint;
typedef unsigned char uchar;
#endif
main.c
/********************************************** 程序功能:在八位数码管上显示温度并发送到串口,串口显示时间和温度 ----------------------------------------------- 测试说明:观察数码管显示和串口接收的数据 ***********************************************/ #include "uart0.h" #include "stdio.h" #include "ds1302.h" #include "max31856.h" #define wei_h P5OUT |= BIT6 #define wei_l P5OUT &= ~BIT6 #define duan_h P5OUT |= BIT5 #define duan_l P5OUT &= ~BIT5 #define wei \ { \ wei_l; \ wei_h; \ wei_l; \ } #define duan \ { \ duan_l; \ duan_h; \ duan_l; \ } //数码管7位段码:0--f uchar scandata[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; uchar seg_show[8]; //记录显示位数的全局变量 uchar cnt = 0; //数码管显示位控制 const char timeStr[] = "time:"; const char temperStr[] = "temperature:"; uint temper_zheng; //温度整数部分 uint temper_xiao; //温度小数部分 float ftemper; //温度浮点数 char string[80]; //用于串口发送 uchar temp; //用于控制更新时间 max31856_cfg_t max31856 = { 0}; //未用 //秒,分,时,日,月,星期,年 unsigned char wdata[7] = { 0x59, 0x01, 0x20, 0x10, 0x04, 0x01, 0x22}; //写时间 unsigned char rdata[10]; //读时间 uchar timedataset[8] = { '1', '0', ':', '2', '5', ':', '3', '6'}; void Seg_Tran(void) { seg_show[0] = temper_zheng / 1000; seg_show[1] = temper_zheng / 100 % 10; seg_show[2] = temper_zheng / 10 % 10; seg_show[3] = temper_zheng % 10; seg_show[4] = temper_xiao / 1000; seg_show[5] = temper_xiao / 100 % 10; seg_show[6] = temper_xiao / 10 % 10; seg_show[7] = temper_xiao % 10; } /********************主函数********************/ void main(void) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 /*下面几行程序关闭所有的IO口*/ P2DIR = 0XFF; P2OUT = 0XFF; P4DIR = 0XFF; P4OUT = 0XFF; P5DIR = 0XFF; P5OUT = 0XFF; ClkInit(); //初始化时钟 InitUART(); //初始化 SPI_Init(); //初始化SPI // Set_DS1302(wdata); //设置时间 Reset_DS1302(); //复位 PutString("Hellow! Welcome to use the temperature test system!\r\n"); //欢迎界面 Max31856_Init(); //初始化max31856 // max31856_oneshot_temperature(); // while (DRDY_IN);//等待温度转换成功 // ftemper = thermocouple_read_temperature(); //读温度 //初始化定时器中断 CCTL0 = CCIE; //使能CCR0中断 CCR0 = 1000; TACTL = TASSEL_2 + ID_3 + MC_1; //定时器A的时钟源选择SMCLK,增计数模式 __enable_interrupt(); //使能全局中断 while (1) { Get_DS1302(rdata); //获取当前时间 if (temp != rdata[5]) { temp = rdata[5]; /*调试SPI用*/ // max31856_write_register(MAX31856_MASK_REG,0x55); // temper_zheng = max31856_read_register(MAX31856_MASK_REG); ftemper = thermocouple_read_temperature(); //读取温度 temper_zheng = (uint)ftemper; //格式转换 temper_xiao = (uint)(ftemper - temper_zheng) * 10000; //获取小数部分 // temper_zheng = max31856_read_register(0x06); Seg_Tran(); sprintf(string, "%s20%02d-%02d-%02d %02d:%02d:%02d\r\n%s%4d\r\n", timeStr, rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], temperStr, temper_zheng); //将时间和温度及数据输出为字符串,方便串口发送 PutString(string); //发送字符串 } LPM1; //进入休眠模式 } } #pragma vector = TIMERA0_VECTOR /* 定时器中断服务函数 功能:主要实现数码管的动态显示以及退出休眠模式 */ __interrupt void timer0(void) { static uchar uc100ms = 0; uc100ms %= 300; if ((!(uc100ms++)) | (temp != rdata[5])) LPM1_EXIT; P4OUT = 0x00; //消影 duan; P4OUT = scandata[seg_show[cnt]]; //输出段选信号 if (cnt == 3) P4OUT |= 0x80; duan; P4OUT = ~(1 << cnt); //输出位选信号 wei; cnt++; cnt &= 7; //位计数变量在0~7之间循环 } /* 串口接收中断服务函数 功能:主要实现串口实时时钟设置和检测 */ #pragma vector = USCIAB0RX_VECTOR __interrupt void USCIAB0RX(void) { static uchar index = 0; int hour, minite, second; timedataset[index++] = UCA0RXBUF; if (index == 8) { index = 0; if (timedataset[2] == ':' && timedataset[5] == ':') { hour = (timedataset[0] - '0') * 10 + (timedataset[1] - '0'); minite = (timedataset[3] - '0') * 10 + (timedataset 标签:
传感器tcbh1141耐高压传感器f热电偶传感器f耐磨耐腐型热电偶电阻cj电容器ch介质电容