其他物联网感知方面内容见:目录
使用铂热电阻PT100,其阻值会随着温度的变化而改变。PT后的100即表示它在0℃时阻值为100欧姆,在100℃时它的阻值约为138.5欧姆。厂家提供有PT100在各温度下电阻值值的分度表,在此可以近似取电阻变化率为 0.385Ω/℃。向PT100输入稳恒电流,再通过A/D转换后测PT100两端电压,即得到PT100的电阻值,进而算出当前的温度值。
采用2.55mA的电流源对PT100进行供电,然后用运算放大器LM324搭建的同相放大电路将其电压信号放大25倍后输入到AD0804中。利用电阻变化率0.385Ω/℃的特性,计算出当前温度值
热敏电阻传感器项目设计总体设计流程图如图所示
铂电阻是用很细的铂丝(Ф0.03~0.07mm)绕在云母支架上制成,是国际公认的高精度测温标准传感器。因为铂电阻在氧化性介质中,甚至高温下其物理、化学性质都非常稳定,因此它具有精度高、稳定性好、性能可靠的特点。铂电阻在中温(-200~650℃)范围内得到广泛应用。目前市场上已有用金属铂制作成的标准测温热电阻,如PT100、PT500、PT1000等。它的电阻—温度关系的线性度非常好,在-200~650℃温度范围内线性度已经非常接近直线。
铂电阻的测量精度、测量范围、线性度等特性都非常好,pt100是铂热电阻,它的阻值会随着温度的变化而改变。PT后的100即表示它在0℃时阻值为100欧姆,在100℃时它的阻值约为138.5欧姆。
电阻与温度的关系:R=αT+100。
常用的Pt电阻接法有三线制和两线制,其中三线制接法的优点是将PT100的两侧相等的的导线长度分别加在两侧的桥臂上,使得导线电阻得以消除。常用的采样电路有两种:一为桥式测温电路,一为恒流源式测温电路。
本设计采用恒流源式测温电路。电路接线图如图
输出信号U=IR(I=2.55mA,R是pt100的电阻)。
输出电压U的范围是0.2048v~0.3628v。电压变化0.1580v。
A/D转换即模数转换(Analog to Digital Conversion),输入模拟量(比如电压信号),输出一个与模拟量相对应的数字量(常为二进制形式)。
例如参考电压VREF为5V,采用8位的模数转换器时,当输入电压为0V时,输出的数字量为0000 0000,当输入的电压为5V时,输出的数字量为1111 1111。当输入的电压从从0V到5V变化时,输出的数字量从0000 0000到1111 1111变化。这样每个输入电压值对应一个输出数字量,即实现了模数转换。
分辨率是指使输出数字量变化1时的输入模拟量,也就是使输出数字量变化一个相邻数码所需输入模拟量的变化值。
分辨率与A/D转换器的位数有确定的关系,可以表示成FS / 2 n 。FS表示满量程输入值,n为A/D转换器的位数。
例如,对于5V的满量程,采用4位的ADC时,分辨率为5V/16=0.3125V (也就是说当输入的电压值每增加0.3125V,输出的数字量增加1);采用8位的ADC时,分辨率为5V/256=19.5mV(也就是说当输入的电压值每增加19.5mV,则输出的数字量增加1);当采用12位的ADC时,分辨率则为5V/4096=1.22mV(也就是说当输入的电压值每增加1.22mV ,则输出的数字量增加1)。显然,位数越多,分辨率就越高。
CS:芯片片选信号,低电平有效。即=0时,该芯片才能正常工作,高电平时芯片不工作。在外接多个ADC0804芯片时,该信号可以作为选择地址使用,通过不同的地址信号使能不同的ADC0804芯片,从而可以实现多个ADC通道的分时复用。
RD:启动ADC0804进行ADC采样,该信号低电平有效,即信号由低电平变成高电平时,触发一次ADC转换。
WR:低电平有效,即=0时,DAC0804把转换完成的数据加载到DB口,可以通过数据端口DB0~DB7读出本次的采样结果。
VIN(+)和VIN(-):模拟电压输入端,单边输入时模拟电压输入接VIN(+)端,VIN(-)端接地。双边输入时VIN(+)、VIN(-)分别接模拟电压信号的正端和负端。当输入的模拟电压信号存在“零点漂移电压”时,可在VIN(-)接一等值的零点补偿电压,变换时将自动从VIN(+)中减去这一电压。
VREF/2:参考电压接入引脚,该引脚可外接电压也可悬空,若外接电压,则ADC的参考电压为该外界电压的两倍,如不外接,则VREF与Vcc共用电源电压,此时ADC的参考电压即为电源电压Vcc的值。
CLK IN和CLK R:外接RC振荡电路产生模数转换器所需的时钟信号,时钟频率CLK = 1/1.1RC,一般要求频率范围100KHz~1460KHz。
AGND和DGND:分别接模拟地和数字地。
INTR:转换结束输出信号,低电平有效,当一次A/D转换完成后,将引起=0,实际应用时,该引脚应与微处理器的外部中断输入引脚相连(如51单片机的,脚),当产生信号有效时,还需等待=0才能正确读出A/D转换结果,若ADC0804单独使用,则可以将引脚悬空。
DB0~DB7:输出A/D转换后的8位二进制结果。
补充说明:ADC0804片内有时钟电路,只要在外部“CLK IN(引脚4)”和“CLKR(引脚19)”两端外接一对电阻电容即可产生A/D转换所要求的时钟,其振荡频率为fCLK≈1/1.1RC。其典型应用参数为:R=10KΩ,C=150PF,fCLK≈640KHz,转换速度为100μs。若采用外部时钟,则外部fCLK可从CLK IN 端送入,此时不接R、C。允许的时钟频率范围为100KHz~1460KHz。
如图所示,ADC0804的工作时序图(Timing Diagrams):
图中给出的其实就是使ADC0804正确工作的软件编程模型。由图可见,实现一次ADC转换主要包含下面三个过程:
1.启动转换:由图2-5中的上部“FIGURE 10A”可知,在信号为低电平的情况下,将引脚先由高电平变成低电平,经过至少tW(WR)I 延时后,再将引脚拉成高电平,即启动了一次AD转换。
注:ADC0804使用手册中给出了要正常启动AD转换的低电平保持时间tW(WR)I的最小值为100ns,即拉低后延时大于100ns即可以,具体做法可通过插入NOP指令或者调用delay()延时函数实现,不用太精确,只要估计插入的延时大于100ns即可。
2.延时等待转换结束:依然由图2-5中的上部“FIGURE 10A”可知,由拉低信号启动AD采样后,经过1到8个Tclk+INTERNAL Tc延时后,AD转换结束,因此,启动转换后必须加入一个延时以等待AD采样结束。
注:手册中给出了内部转换时间“INTERNAL Tc”的时间范围为62~73个始终周期,因此延时等待时间应该至少为8+73=81个时钟周期。比如,若R为150K, C为150pF,则时钟频率为Fclk=1/1.1RC=606KHz,因此时钟周期约为Tclk=1/Fclk=1.65us。所以该步骤至少应延时81*Tclk=133.65us. 具体做法可通过插入NOP指令或者调用delay()延时函数实现,不用太精确,只要估计插入的延时大于133.65us即可。
3.读取转换结果:由图2-5的下部“FIGURE 10B”可知,采样转换完毕后,在信号为低的前提下,将脚由高电平拉成低电平后,经过tACC的延时即可从DB脚读出有效的采样结果。
注:手册中给出了tACC的典型值和最大值分别为135ns和200ns,因此将引脚拉低后,等待大于200ns后即可从DB读出有效的转换结果。具体做法可通过插入NOP指令或者调用delay()延时函数实现,不用太精确,只要估计插入的延时大于200ns即可。
对采样值进行运算变换,换算出实际的滑动变阻器输入电压值。
对于任何一个A/D采样器而言,其转换公式如下:
其中:
Vout:输入ADC的模拟电压值。
Dsample:ADC转换后的二进制值。本试验的ADC0804为八位。
Dmax:ADC能够表示的刻度总数。ADC0804为八位ADC,因此
Vref:ADC参考电压值,本试验ADC0804的Vref被设置为5V
因此,对于本试验,转换公式为
LM324系列器件带有差动输入的四运算放大器。与单电源应用场合的标准运算放大器相比,它们有一些显著优点。该四放大器可以工作在低到3.0伏或者高到32伏的电源下,静态电流为MC1741的静态电流的五分之一。共模输入范围包括负电源,因而消除了在许多应用场合中采用外部偏置元件的必要性。每一组运算放大器可用图2-7所示的符号来表示,它有5个引出脚,其中“+”、“-”为两个信号输入端,“V+”、“V-”为正、负电源端,“Vo”为输出端。两个信号输入端中,Vi-(-)为反相输入端,表示运放输出端Vo的信号与该输入端的相位相反;Vi+(+)为同相输入端,表示运放输出端Vo的信号与该输入端的相位相同。这个是最常用的运算放大器1,2,3脚是一组5,6,7脚是一组,8,9,10脚是一组,12,13,14脚是一组,剩下的两个脚是电源,1,7,8,14是各组放大器的输出脚,其它的就是输入脚。
LM324系列由四个独立的,高增益,内部频率补偿运算放大器,其中专为从单电源供电的电压范围经营。从分裂电源的操作也有可能和低电源电流消耗是独立的电源电压的幅度。
应用领域包括传感器放大器,直流增益模块和所有传统的运算放大器现在可以更容易地在单电源系统中实现的电路。例如,可直接操作的LM324系列,这是用来在数字系统中,轻松地将提供所需的接口电路,而无需额外的±15V电源标准的5V电源电压。
ADC0804的分辨率度是5/255=0.0196。要使精度达到0.5℃,温度增加1℃时ADC至少要增加1。pt100温度在-50℃~110℃输出电压变化范围要大于5*160/255=3.138。
所以模拟信号应在3.138v~5v之间。所以放大倍数应该大于3.138/0.1580=19.9小于5/0.1580=31.6。所以设计放大25倍。
用LM324设计放大25倍电路。
在图2-8中R6、R7是比例电阻。3是输入端1是输出端U=U0(1+R7/R6),放大倍数A=U/U0=25。
常见的LED数码管为“8”字型的,共计8段。每一段对应一个发光二极管。有共阳极和共阴极两种,如图2-9所示。共阴极发光二极管的阴极连在一起,通常公共阴极接地。当阳极为高电平时,发光二极管发光。
同样,共阳极发光二极管的阳极连接在一起,公共阳极接正电压,当某个发光二极管的阴极接低电平时,发光二极管发光,显示相应的段。
LED数码管中还有一个圆点型发光二极管(在图中以dp表示),用于显示小数点。通过七个发光二极管亮暗的不同组合,可以显示各种数字。
为了使数码管显示不同的符号或数字,实际上是确定哪些段发光、哪些段不发光,就要为LED数码管提供段码(字型码)。
LED数码管共计8段。正好是一个字节。习惯上是以“a”段对应段码字节的最低位。各段与字节中各位对应关系如表
代码位 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|
显示位 | dp | g | f | E | d | c | b | a |
LED静态显示方式
无论多少位LED数码管,同时处于显示状态。
静态显示方式,各位的共阴极(或共阳极)连接在一起并接地(或接+5V);每位的段码线(a~dp)分别与一个8位的I/O口锁存器输出相连。如果送往各个LED数码管所显示字符的段码一经确定,则相应I/O口锁存器锁存的段码输出将维持不变,直到送入另一个字符的段码为止。因此,静态显示方式的显示无闪烁,亮度都较高,软件控制比较容易。
静态显示器电路,各位可独立显示,静态显示方式接口编程容易,但是占用口线较多。如果要显示4位,则要占用4个8位I/O口。因此在显示位数较多的情况下,由于这种方式占用的I/O口太多。所以在实际应用中,一般不采用静态显示方式,而是采用动态显示方式。
LED动态显示方式
无论在任何时刻只有一个LED数码管处于显示状态,即单片机采用“扫描”方式控制各个数码管轮流显示。
在多位LED显示时,为简化硬件电路,通常将所有显示位的段码线的相应段并联在一起(可以减少段码线),由一个8位I/O口控制,而各位的共阳极或共阴极分别由相应的I/O线控制,形成各位的分时选通。
段码线占用一个8位I/O口,而位选线占用一个I/O口的4根引脚。
采用动态“扫描”显示方式。即在某一时刻,只让某一位的位选线处于选通状态,而其它各位的位选线处于关闭状态,同时,段码线上输出相应位要显示字符的段码。
例如,在共阴极方式时,段码为“0X00”,则当W0=0,最左一位亮,W1=1时,第二位亮,…….
虽然这些字符是在不同时刻出现,但在某一时刻,只有一位显示,其他各位熄灭,由于余辉和人眼的“视觉暂留”作用,只要每位显示间隔足够短,则可以感觉到“多位同时亮”,达到同时显示的效果。
LED不同位显示的时间间隔(扫描间隔)应根据实际情况而定。如果要显示位数较多,则将占大量的单片机时间,因此动态显示的实质是以牺牲单片机时间来换取I/O端口的减少。
动态扫描方式的各位数码管逐个轮流显示,当扫描频率较高的时,其显示效果较好。这种方式功耗小,硬件资源要求少,所以应用较多。
动态显示的优点是硬件电路简单,LED越多,优势越明显。缺点是显示亮度不如静态显示的亮度高。如果“扫描”速率较低,会出现闪烁现象。
代码如下:
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ad0_7 P1 //AD数据口
sbit cs=P2^4; //片选信号,低电平有效,控制芯片的启动和结果读取
sbit rd=P2^7; //读数据控制,低电平有效
sbit wr=P2^6; //AD启动控制,上升沿有效
sbit intr=P2^5; //AD转换完成输出低电平
uchar i;
uchar led[11]={ 0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x40, //"-"
};
uchar dat_AD[4]={0};
//启动AD转换子程序//////////////////
void start_ad(void)
{ cs=0; //允许AD
wr=0;
_nop_();
wr=1; //WR由低变高时启动AD转换
while(intr); //等待转换完成,低电平有效
cs=1; //停止AD转换
}////////////////////
read_ad()
{ uint ad_data;
ad0_7=0xff;
cs=0; //允许读
rd=0; //读取转换数据结果
_nop_();
ad_data=ad0_7; //把数据存到AD——data中
rd=1;cs=1; //停止读取AD
return(ad_data);
}
// 数据处理函数
//实际测量当0度时,AD数据为133,所以数据处理时判断AD数据和133的大小来识别正负温度。
//由于ADC芯片精度不够,所以测量时有误差,8位AD的分辨率为19.5mV,约为20mV,
//放大电路输出的电压,温度每变化一度,电压变化只有10mV左右,所以测量有误差,
//以下温度和AD数据的计算公式为实测数据后线性拟合得到的,实际线性拟合得到公式为:y=0.503x+133.63.
//因为AD数据为0-255的整数,所以公式简化为以下计算方式
void data_shout(uint ad_data)
{
float temp;
uint T;
if(ad_data<79)
{
temp=614.422-7.811*ad_data;
T=(uint)temp;
dat_AD[0]=10;
} //负温度 dat_AD[0]中为温度符号数据
else if(ad_data<=204)
{
temp=7.990*ad_data-628.491;
T=(uint)temp;
dat_AD[0]=T/1000;
} //正温度
else if(ad_data>204)
{
temp=8.124*ad_data-655.742;
T=(uint)temp;
dat_AD[0]=T/1000;
} //ad_data=T;
dat_AD[1]=T%1000/100; //温度值的十位
dat_AD[2]=T%100/10; //2温度值的个位
dat_AD[3]=T%10; //温度值的小数位
}
//显示函数
void disp(){
switch(i){
case 0: P0=0xfe;P3=led[dat_AD[0]];i++;break; //显示符号位
case 1: P0=0xfd;P3=led[dat_AD[1]];i++;break;
case 2: P0=0xfb;P3=led[dat_AD[2]]|0x80;i++;break;
case 3: P0=0xf7;P3=led[dat_AD[3]];i=0;break;
}
}
//定时器初始化
//用作数码管显示的刷新
void t0init(){
TMOD=0x01;
TH0=(65535-2000)/256; //定时20ms时间
TL0=(65535-2000)%256;
EA=1;
ET0=1;
TR0=1;
}
//定时器中断函数,在中断中刷新数码管显示
void Time0( ) interrupt 1{
TH0=(65535-2000)/256;
TL0=(65535-2000)%256;
disp();
}
//主函数
void main(void){
t0init(); //初始化
while(1){
start_ad(); //开始AD
data_shout(read_ad()); //数据处理
}
}