标签:
一、实验目的 |
二、实验材料 |
三、实验原理 |
振动传感器实验环境由PC机(安装有Windows XP操作系统、ADS1.2集成开发环境和J-Link-ARM-V410i仿真器)、J-Link-ARM仿真器、NXP LPC2378实验节点板、振动传感器、实验模块和LCD显示实验模块组成,如图4.2.1所示。
1.拓展知识 |
(1)气体压力传感器简介
气体传感器是一种将气体的成份、浓度等信息转换成可以被人员、仪器仪表、计算机等利用的信息的装置!气体传感器一般被归为化学传感器的一类,尽管这种归类不一定科学。气体传感器包括:半导体气体传感器、电化学气体传感器、催化燃烧式气体传感器、热导式气体传感器、红外线气体传感器等。
(2)气体传感器的分类
1)半导气体传感器
这种类型的传感器在气体传感器中约占60%,根据其机理分为电导型和非电导型,电导型中又分为表面型和容积控制型.
2)固体电解质气体传感器
这种传感器元件为离子对固体电解质隔膜传导,称为电化学池,分为阳离子传导和阴离子传导,是选择性强的传感器,研究较多达到实用化的是氧化锆固体电解质传感器,其机理是利用隔膜两侧两个电池之间的电位差等于浓差电池的电势。稳定的氧化铬固体电解质传感器已成功地应用于钢水中氧的测定和发动机空燃比成分测量等。为弥补固体电解质导电的不足,近几年来在固态电解质上燕镀一层气体敏膜,把围周环境中存在的气体分子数量和介质中可移动的粒子数量联系起来。
3)接触燃烧式气体传感器
接触燃烧式传感器适用于可燃性气H2、CO、CH4的检测。可燃气体接触表面催化剂Pt 、Pd 时燃烧、破热,燃烧热与气体浓富有关。这类传感器的应用面广、体积小、结构简单、稳定性好,缺点是选择性差。
4)电化学气体传感器
电化学方式的气体传感器常用的有两种
( 1 )恒电位电解式传感器是将被测气体在特定电场下电离,由流经的电解电流测出气体浓度,这种传感器灵敏度高,改变电位可选择的检洌气体,对毒性气体检测有重要作用。
( 2) 原电池式气体传感器在KOH电解质溶液中,pt —Pb或Ag —Pb 电极构成电池,已成功用于检测O2,其灵敏度高,缺点是透水逸散吸潮,电极易中毒。
5)光学气体传感嚣
( 1 ) 直接吸收式气体传感器:红外线气体传感器是典型的吸收式光学气体传感器,是根据气体分别具有各自固有的光谱吸收谱检测气体成分,非分散红外吸收光谱对SO2、CO、C O2、NO等气体具有较高的灵敏度。另外紫外吸收、非分散紫外线吸收、相关分光、二次导数、自调制光吸收法对NO、N O2 SO2、C H( CH4) 等气体具有较高的灵敏度。
( 2 ) 光反应气体传感器:光反应气体传感器是利用气体反应产生色变引起光强度吸收等光学特性改变,传感元件是理想的,但是气体光感变化受到限制,传感器的自由度小。
2.BMP085电路及特性简介 |
如图4.2.2所示,为本次试验所用气压传感器BMP085的芯片控制引脚图。
图4.2.5为气压传感器BMP085的组成原件的规格信息(如果没有另作规定,以下所给的值是在电压温度范围内的最大值)。
图4.2.6给出BMP085最大额定参数的信息。
3.I2C总线 |
(1)I2C总线简介
I2C 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的,主要是用来连接整体电路(ICS) ,I2C是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实施数据传输的控制源。这种方式简化了信号传输总线。I2C 总线用于控制器件,从 E2PROM 中读出校准数据以及当 AD 转换完成后读出测量 数据。
随着大规模集成电路技术的发展,把CPU和一个单独工作系统所必需的ROM、RAM、I/O端口、A/D、D/A等外围电路集成在一个单片内而制成的单片机或微控制器愈来愈方便。目前,世界上许多公司生产单片机,品种很多。其中包括各种字长的CPU,各种容量的ROM、RAM以及功能各异的I/O接口电路等等,但是,单片机的品种规格仍然有限,所以只能选用某种单片机来进行扩展。扩展的方法有两种:一种是并行总线,另一种是串行总线。由于串行总线的连线少,结构简单,往往不用专门的母板和插座而直接用导线连接各个设备。因此,采用串行线可大大简化系统的硬件设计。PHILIPS公司早在十几年前就推出了I2C串行总线,利用该总线可实现多主机系统所需的裁决和高低速设备同步等功能。因此,这是一种高性能的串行总线。
BMP085 有一个主清除信号(XCLR)——低电平输入,用来复位 BMP085 和初始化寄存器和控制器。器件可以通过上电复位电路(POR)自动的复位。XCLR(是器件上的一个复位引脚)在不用的情况下可以空置。
(2) I2C 接口说明书
I2C 接口电气参数如下图所示
(4)I2C协议
I2C接口协议是一个特殊总线信号协议。有 Start(S)(开始信号)、Stop(P)(结束信号)、 二进制数据三不分组成,如下图。开始时,SCL 高,SDA 下降沿。之后,发送从器件地址。 在 7 位的地址位之后,是控制读写位,选择读写操作,如上图。当从器件识别到与其对应的 地址信息后,将向主机发送一个应答信号——在第 9 个时钟周期拉低 SDA。在停止时,SCL 保持高电平,SDA 上升沿。
4.使用过程 |
(1)数据转换
开始温度值 UT 测量和开始压强值 UP 测量的时序图如下。在开始信号之后,主机发送 器件地址(写),寄存器地址和控制寄存器数据。 BMP085 没接收到八位数据就向主机发送 应答信号主机在收到最后一个应答信号后发送停止信号。
同时,并不需要等待最大的转化时间之后再读取数据。可以利用器件的输出管脚 EOC (转换完毕信号)来检查转化是否完毕。逻辑 1 表示转换完成,逻辑 0 表示转换正在进行。 在转换完成后 BMP085 就自动切换到待命模式。
(2)读取 AD 转换器的结果和 E2PROM 中的数据
为了读出温度数据 UT(0-15bit)、压强数据(16-19bit)和 E2PROM 中的数据,操作步骤如下:
1) 在开始信号之后,主机发送模块的地址写命令和寄存器地址 。寄存器地址选择读寄存器:E2PROM 数据寄存器:0xAA—0xBF。温度或者压强值 UT 或 UP 0xF6(MSB) 0xF7(LSB)可选择 0xF8(XLSB)
2) 之后,主机发送从新开始信号,接着是器件读地址,然后收到从器件发来的应答信号。然后 BMP085 首先发送高 8 数据,主机收到数据后返回给 BMP085 一个应答信号,之后,BMP085 发送低 8 位数据。之后主机发送 not ack 信号和最后的停止信号。
3) 为了选择高分辨率,地址为 0xF8 的 XLSB 寄存器可以被读取,扩展 16 位数据到 19 位, 参考 Bosch 公司提供的 BMP085-SMD500-API 程序。
(3)测量温度和压力
噪音数据被计算为 10 个数据点的标准偏差。为了得到更多的有关噪声特点的信息,可以查 看相关具体应用的信息“在气压传感器应用中的噪声”。所有的模式可以在一个较高的速度下执行 ,例如,在传输速度为 128 次每秒的水平上, 电流消耗的增长与传输速度的增长成比例。这样噪声可以用软件的方法进一步降低。
校准系数
176 位的 E2PROM 被划分为 11 个字,每个字 16 位(11*16=176)。这样就包含了 11 个校准系数。每个器件模块都有自己单独的校准系数。在第一次计算温度压力数据之前,控制 器应该先读出读出 E2PROM 中的数据。(就是前面说的先读出校准数据,然后再开始采集数据)数据通信的准确性可以通过检查没有字的值是 0 和 0xFFFF 来确定。(PS:貌似意思是 E2PROM 中的值没有 0 和 0xFFFF,如果读出这些值就是错的)
四、实验内容 |
1.实验器材连线
本实验所使用的振动传感器实物图如图4.1.7所示。
uint8 sndBuf[30];
short AC1,AC2,AC3;
unsigned short AC4,AC5,AC6;
short B1,B2;
short MB,MC,MD;
long UT,UP;
long X1,X2,X3,T,tmp,tmp2;
long B3,B5,B6,B7;
unsigned long B4;
long p;
short oss;
//I2C初始化
I2C_Init(10000); // I2C配置及端口初始化
IRQEnable();
//设置LCD屏幕引脚
PINSEL3=PINSEL3 & 0x00000000;
IO1DIR=IO1DIR|0x05700000;
//屏幕初始化
RESET0; //复位
delay(50);
RESET1;
delay(100);
lcd_init();
delay(20);
LCD_Frame();
DispAscStr(0,12,"Pressure",8,&xpos,&ypos);
DispChnStr(xpos,ypos,"模块测试",4,&xpos,&ypos);
//读出E2PROM中的校准数据
//从0地址开始存放,一共读取22个字节
//见器件和寄存器地址,oxee为写操作,oxef为读操作
I2C_ReadNByte(0xee,1,0xaa,&sndBuf[0],22);
//以下过程完成
/*
AC1(0xAA,0XAB) (16BIT)
AC2(0xAC,0XAD) (16BIT)
AC3(0xAE,0XAF) (16BIT)
AC4(0xB0,0XB1) (16BIT)
AC5(0xB2,0XB3) (16BIT)
AC6(0xB4,0XB5) (16BIT)
B1(0xB6,0XB7) (16BIT)
B2(0xBB,0XB9) (16BIT)
MB(0xBA,0XBB) (16BIT)
MC(0xBC,0XBD) (16BIT)
MD(0xBE,0XBF) (16BIT)
*/
AC1=sndBuf[0]<<8;
AC1+=sndBuf[1];
AC2=sndBuf[2]<<8;
AC2+=sndBuf[3];
AC3=sndBuf[4]<<8;
AC3+=sndBuf[5];
AC4=sndBuf[6]<<8;
AC4+=sndBuf[7];
AC5=sndBuf[8]<<8;
AC5+=sndBuf[9];
AC6=sndBuf[10]<<8;
AC6+=sndBuf[11];
B1=sndBuf[12]<<8;
B1+=sndBuf[13];
B2=sndBuf[14]<<8;
B2+=sndBuf[15];
MB=sndBuf[16]<<8;
MB+=sndBuf[17];
MC=sndBuf[18]<<8;
MC+=sndBuf[19];
MD=sndBuf[20]<<8;
MD+=sndBuf[21];
delay(1000);
while(1)
{
/*
以下步骤完成如下工作:
//读未补偿的温度值
//(write 0x2e into reg 0xf4,wait 4.5ms)
读取温度,需要向控制寄存器0xf4中写入0x2e,
还需要等待4.5ms以上
read red 0xf6(MSB),0xf7(LSB)
UT=MSB << 8 + LSB
*/
sndBuf[0]=0x2E;
I2C_WriteNByte(0xee,1,0xF4,&sndBuf[0],1);
delay(1000);
//才可以从Oxf6或者0xf7中读取转换后的16位温度数据
I2C_ReadNByte(0xee,1,0xF6,&sndBuf[0],2);
UT=sndBuf[0]<<8;
UT+=sndBuf[1];
/*
读未补偿的压力值
需要向0xfe中写入0x34,延时至少4.5ms
write 0x34+(oss<<6) into reg 0xf4,wait 4.5ms
then read reg 0xf6(MSB),0XF7(LSB),0XF8(XLSB)
UP=(MSB<<16+LSB<<8+XLSB)>>(8-0ss)
*/
oss=0;
sndBuf[0]=0x34;
sndBuf[0]+=oss<<6;
I2C_WriteNByte(0xee,1,0xF4,&sndBuf[0],1);
delay(1000);
//再从0xf6或者0xf7中读取16位的气压信息
I2C_ReadNByte(0xee,1,0xF6,&sndBuf[0],3);
UP=sndBuf[0]<<16;
UP+=sndBuf[1]<<8;
UP+=sndBuf[2];
UP=UP>>(8-oss);
/*计算实际温度值
X1=(UT-AC6)*AC5/2^15;
X2=MC*2^11/(X1+MD)
B5=X1+X2
T=(B5+8)/2^4
*/
X1=UT-AC6;
X1*=AC5;
tmp=pow(2,15);
X1/=tmp;
//X2=MC*2^11/(X1+MD);
X2=MC;
tmp=pow(2,11);
X2*=tmp;
X2/=(X1+MD);
B5=X1+X2;
//T=(B5+8)/2^4;
T=B5+8;
tmp=pow(2,4);
T/=tmp;
/*计算实际压力值
B6=B5-4000
X1=(B2*(B6*B6/2^12))/2^11
X3=X1+X2
B3=((AC1*4+X3)<<0ss+2)/4
X1=AC3*B6/2^13
X2=(B1*(B6*B6/2^12))/2^16
X3=((X1+X2)+2)/2^12
B4=AC4*(unsigned long)(x3+32768)/2^15
B7=((unsigned long)UP-B3)*(50000>>oss)
IF(B7<0X80000000){P=(B7*2)/B4}
ELSE {P=(B7/B4)*2}
X1=(P/2^8)*(P/2^8)
X1=(X1*3038)/2^16
X2=(-7357*P)/2^16
P=P+(X1+X2+3791)/2^4
*/
B6=B5-4000;
tmp=pow(2,12);
tmp2=pow(2,11);
X1=(B2*(B6*B6/tmp))/tmp2;
tmp=pow(2,11);
X2=AC2;
X2=(X2&0x0000ffff);
X2*=B6;
X2/=tmp;
X3=X1+X2;
//B3=((AC1*4+X3)<<oss+2)/4;
B3=(AC1*4+X3)<<oss;
B3+=2;
B3/=4;
tmp=pow(2,13);
X1=AC3;
X1=(X1&0x0000ffff);
X1*=B6;
X1/=tmp;
tmp=pow(2,12);
tmp2=pow(2,16);
X2=(B1*(B6*B6/tmp))/tmp2;
X3=((X1+X2)+2)/(2*2);
tmp=pow(2,15);
B4=AC4*(unsigned long)(X3+32768)/tmp;
//B7=((unsigned long)UP-B3)*(50000>>oss);
B7=50000>>oss;
B7*=((unsigned long)UP-B3);
if(B7<0x80000000)
{
//p=(B7*2)/B4;
p=B7;
//p=p&0x0000ffff;
p*=2;
p/=B4;
}
else
{
//p=(B7/B4)*2;
p=B7;
//p=p&0x0000FFFF;
p/=B4;
p*=2;
}
tmp=pow(2,8);
X1=(p/tmp)*(p/tmp);
tmp2=pow(2,16);
X1=(X1*3038)/tmp2;
X2=(-7357*p)/tmp2;
tmp=pow(2,4);
p=p+(X1+X2+3791)/tmp;
/*
以下过程为将获得的温度和压力转换为显示屏输出
*/
//输出温度***.***
sndBuf[10]=T/100+‘0‘;
sndBuf[11]=T%100/10+‘0‘;
sndBuf[12]=‘.‘;
sndBuf[13]=T%10+‘0‘;
DispAscStr(0,40,&sndBuf[10],4,&xpos,&ypos);
//输出压力***.**kpa(千帕斯卡)
sndBuf[9]=p/100000+‘0‘;
sndBuf[10]=p%100000/10000+‘0‘;
sndBuf[11]=p%10000/1000+‘0‘;
sndBuf[12]=‘.‘;
sndBuf[13]=p%1000/100+‘0‘;
sndBuf[14]=p%100/10+‘0‘;
sndBuf[15]=p%10+‘0‘;
sndBuf[16]=‘k‘;
sndBuf[17]=‘P‘;
sndBuf[18]=‘a‘;
DispAscStr(0,100,&sndBuf[9],10,&xpos,&ypos);
delay(2000);
}
(2) 温度监控试验.
试验内容是当温度超过25度时,显示”temp high”。修改main.c中while ( 1){}如下面代码区所示。
while(1)
{
sndBuf[0]=0x2E;
I2C_WriteNByte(0xee,1,0xF4,&sndBuf[0],1);
delay(1000);
//才可以从Oxf6或者0xf7中读取转换后的16位温度数据
I2C_ReadNByte(0xee,1,0xF6,&sndBuf[0],2);
UT=sndBuf[0]<<8;
UT+=sndBuf[1];
X1=UT-AC6;
X1*=AC5;
tmp=pow(2,15);
X1/=tmp;
//X2=MC*2^11/(X1+MD);
X2=MC;
tmp=pow(2,11);
X2*=tmp;
X2/=(X1+MD);
B5=X1+X2;
//T=(B5+8)/2^4;
T=B5+8;
tmp=pow(2,4);
T/=tmp;
//输出温度***.***
sndBuf[10]=T/100+‘0‘;
sndBuf[11]=T%100/10+‘0‘;
sndBuf[12]=‘.‘;
sndBuf[13]=T%10+‘0‘;
DispAscStr(0,40,&sndBuf[10],4,&xpos,&ypos);
if(T>250)
DispAscStr(0,100,"temp high",9,&xpos,&ypos);
delay(2000);
}
(3) 气压监控试验.
试验内容是当温度超过25度时,显示”temp high”。修改main.c中while ( 1){}如下面代码区所示。
while(1)
{
oss=0;
sndBuf[0]=0x34;
sndBuf[0]+=oss<<6;
I2C_WriteNByte(0xee,1,0xF4,&sndBuf[0],1);
delay(1000);
//再从0xf6或者0xf7中读取16位的气压信息
I2C_ReadNByte(0xee,1,0xF6,&sndBuf[0],3);
UP=sndBuf[0]<<16;
UP+=sndBuf[1]<<8;
UP+=sndBuf[2];
UP=UP>>(8-oss);
B6=B5-4000;
tmp=pow(2,12);
tmp2=pow(2,11);
X1=(B2*(B6*B6/tmp))/tmp2;
tmp=pow(2,11);
X2=AC2;
X2=(X2&0x0000ffff);
X2*=B6;
X2/=tmp;
X3=X1+X2;
//B3=((AC1*4+X3)<<oss+2)/4;
B3=(AC1*4+X3)<<oss;
B3+=2;
B3/=4;
tmp=pow(2,13);
X1=AC3;
X1=(X1&0x0000ffff);
X1*=B6;
X1/=tmp;
tmp=pow(2,12);
tmp2=pow(2,16);
X2=(B1*(B6*B6/tmp))/tmp2;
X3=((X1+X2)+2)/(2*2);
tmp=pow(2,15);
B4=AC4*(unsigned long)(X3+32768)/tmp;
//B7=((unsigned long)UP-B3)*(50000>>oss);
B7=50000>>oss;
B7*=((unsigned long)UP-B3);
if(B7<0x80000000)
{
//p=(B7*2)/B4;
p=B7;
//p=p&0x0000ffff;
p*=2;
p/=B4;
}
else
{
//p=(B7/B4)*2;
p=B7;
//p=p&0x0000FFFF;
p/=B4;
p*=2;
}
tmp=pow(2,8);
X1=(p/tmp)*(p/tmp);
tmp2=pow(2,16);
X1=(X1*3038)/tmp2;
X2=(-7357*p)/tmp2;
tmp=pow(2,4);
p=p+(X1+X2+3791)/tmp;
//输出压力***.**kpa(千帕斯卡)
sndBuf[9]=p/100000+‘0‘;
sndBuf[10]=p%100000/10000+‘0‘;
sndBuf[11]=p%10000/1000+‘0‘;
sndBuf[12]=‘.‘;
sndBuf[13]=p%1000/100+‘0‘;
sndBuf[14]=p%100/10+‘0‘;
sndBuf[15]=p%10+‘0‘;
sndBuf[16]=‘k‘;
sndBuf[17]=‘P‘;
sndBuf[18]=‘a‘;
DispAscStr(0,100,&sndBuf[9],10,&xpos,&ypos);
//当气压超过80 KPA提示气压过高
if(p>80000)
DispAscStr(0,120,"press high",10,&xpos,&ypos);
delay(2000);
}
五、实验思考 |
1.怎样才能启动I2C总线并读取EEPROM中的内容?
2.怎样实现当温度或者气压低于某个值时或者气压和温度同时满足某个条件时发出警 告?
3.气压传感器有什么应用?
标签:
原文地址:http://blog.csdn.net/u010570551/article/details/51530794