温度数据采集处理:
主要原理是使用ADC采集模拟量并转化为数字量, 并由89C52单片机通过串口通信发送给计算机
外围电路图:
- 使用PT100作为作为温度传感器
- 使用1/4w色环电阻作为分压电阻
- 使用XPT2046作为ADC
- 使用89C52作为MCU
数据采集步骤:
- 连接外部电路
- 设置串口波特率4800
- 串口发送
1
, 控制MCU开始采集数据 - 打开设备电源, 快速调节制冷片电流至指定值
- 待数据稳定后(约1min~1min30s), 串口发送
2
, 控制MCU停止数据采集 - 保存串口数据, 开始数据处理
数据处理:
串口接收的数据为xpt2046采集后的未经处理的值, 通过额外的C++ 程序将这些数据转化为温度:
物理量意义:
计算公式:
一些常量的测量值(实验平台不同, 数值不同):
通过Excel将温度数据转化为折线图:
通过Matlab将数据拟合成光滑曲线:
待完成
数据采集+通信程序源码:
MCU与ADC之间的驱动程序这里不做展开分析, 直接放上源码:
xpt2046.h
#ifndef __XPT2046_H_
#define __XPT2046_H_
#define u1 unsigned char
#define u2 unsigned int
sbit din=P3^4;
sbit cs=P3^5;
sbit dclk=P3^6;
sbit dout=P3^7;
void delay5us(void); //误差 0us
u2 adread(u1 com);
u2 readdata();
void senddata(u1 com);
#endif
xpt2046.c
#include "reg52.h"
#include "xpt2046.h"
void senddata(u1 com)
{
u1 f1;
cs=0;
dclk=0;
for(f1=0;f1<8;f1++)
{
com=com<<1;
din=CY;
dclk=1;
dclk=0;
}
}
u2 readdata()
{
u2 dat;
u1 f2;
cs=0;
dclk=0;
for(f2=0;f2<12;f2++)
{
dat=dat<<1;
dat=dat|dout;
dclk=1;
dclk=0;
}
return dat;
}
u2 adread(u1 com)
{
u1 f1;
u2 addat;
senddata(com);
for(f1=6;f1>0;f1--);
dclk=1;
dclk=0;
addat=readdata();
cs=1;
return addat;
}
AD转换(XPT2046).c
//头文件引入//
#include "reg52.h"
#include "xpt2046.h"
#include "stdio.h"
#define u1 unsigned char
#define u2 unsigned int
sbit a1=P2^2;
sbit a2=P2^3;
sbit a3=P2^4;
u1 code c1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u1 v[4];
u1 flag=0,flag2=0,flag3;
float t2;
u2 dat,dat2;
void datapro();
//子函数定义//
void delayms(u2 xx) //延时函数定义//
{
u2 i; //延时函数两个参数都要 U2
u2 o;
for(o=xx;o>0;o--)
for(i=124;i>0;i--);
}
//中断配置//
void sdeploy()
{
T2CON=0x34;
IE=IE|0x90;
PCON=0x00;
SCON=0x50;
RCAP2H=0XFF;
RCAP2L=0XB1;
/* IP=0X10; */
}
void t1intdeploy()
{
TMOD=TMOD|0x10;
TH1=0x3C; //每50ms溢出一次//
TL1=0xb0;
TR1=0;
IE=IE|0x08;
}
void t1int()interrupt 3
{
u1 t;
TF1=0;
TH1=0x3C;
TL1=0xb0;
t++;
if(t==2)
{
t=0;
flag2=1;
}
}
//数据处理//
void datapro()
{
dat=adread(0xE4);
delayms(1);
dat2=adread(0xD4);
}
//数码管显示函数//
void smgdisplay()
{
u1 g;
for(g=0;g<4;g++)
{
switch(g)
{
case(0): //逐个选择case发送段选数据//
a1=0;a2=0;a3=0;
break;
case(1):
a1=1;a2=0;a3=0;
break;
case(2):
a1=0;a2=1;a3=0;
break;
case(3):
a1=1;a2=1;a3=0;
break;
}
P0=v[g];
delayms(1); //延时//
P0=0x00;
delayms(1); //消影//
}
}
void judge()
{
switch(flag)
{
case(1):
ES=0;
TI=1;
printf("Open ADC\n");
while(TI==0);
TI=0;
TR1=1;
flag=0;
ES=1;
break;
case(2):
ES=0;
TI=1;
printf("Close ADC\n");
while(TI==0);
TI=0;
TR1=0;
flag=0;
ES=1;
break;
case(3):
ES=0;
TI=1;
printf("Error\n");
while(TI==0);
TI=0;
flag=0;
ES=1;
break;
}
}
void main()
{
t1intdeploy();
sdeploy();
v[0]=c1[0];
v[1]=c1[0];
v[2]=c1[0];
v[3]=c1[0];
while(1)
{
judge();
smgdisplay();
if(flag2==1)
{
datapro();
v[0]=c1[dat%1000%100%10];
v[1]=c1[dat%1000%100/10];
v[2]=c1[dat%1000/100];
v[3]=c1[dat/1000];
t2=(float)dat*5.0/4096.0;
flag2=0;
ES=0;
TI=1;
// printf("The Voltage is %fV\n",t2);
printf("%d\n%d\n",dat,dat2);
// printf("%d\n",dat2);
while(TI==0);
TI=0;
ES=1;
}
}
}
//T2中断服务任务分配//
void sint()interrupt 4
{
u1 a;
RI=0;
a=SBUF;
switch(a)
{
case(0x31):
flag=1;
break;
case(0x32):
flag=2;
break;
default:
flag=3;
}
a=0;
}
数据处理源码:
#include <iostream>
#include <bits/stdc++.h>
#include <cstdio>
#include <fstream>
#include <sstream>
#include <time.h>
using namespace std;
int main(int argc, char *argv[]){
fstream fIn;
fIn.open ("data.txt",ios_base::in);
auto fOut=fopen("dataOut1.txt","w+");
auto fOut2=fopen("dataOut2.txt","w+");
string lineNow;
/**
* Vcc 输入电压
* R1 分压电阻实际阻值
* R0_0 测量系统短接阻值
* u1 分压电阻电压
* u0 PT100电压
* r0 PT100电阻
* t0 PT100理论计算温度
* segDis 单片机原始数据
*/
const double Vcc=5.03, R1=99.7, R0_0=3.7;
double u1, u0, r0, t0;
int segDis;
stringstream ss;
int startTime=clock ();
getline(fIn,lineNow);
while(lineNow!="Open ADC"){
getline(fIn,lineNow);
}
getline(fIn,lineNow);
while(lineNow!="Close ADC"){
ss<<lineNow;
ss>>segDis;
ss.clear();
// printf("%d\n",segDis);
u1=segDis*1.0/4096*Vcc;
u0=Vcc-u1;
r0=u0/(Vcc-u0)*R1-R0_0;
t0=(r0/100-1)/0.00390802;
fprintf(fOut,"%lf\n",t0);
getline(fIn,lineNow);
ss<<lineNow;
ss>>segDis;
ss.clear();
// printf("%d\n",segDis);
u1=segDis*1.0/4096*Vcc;
u0=Vcc-u1;
r0=u0/(Vcc-u0)*R1-R0_0;
t0=(r0/100-1)/0.00390802;
fprintf(fOut2,"%lf\n",t0);
getline(fIn,lineNow);
}
fIn.close ();
printf("数据处理结束, 耗时%d mm",clock ()-startTime);
return 0;
}