您的当前位置:首页正文

远程温度控制

2022-11-17 来源:钮旅网
摘要

远 程 温 度 控 制

摘要

本设计以单片机STC89C52为核心部件,采用单总线型数字式的温度传感器DS18B20作为温度采集,分别用1602和数码管作为显示部件,用1838红外传送数据。该系统既可以对当前温度进行实时显示,又可以对温度进行无线发送与接收。两位整数两位小数的显示方式具有更高的显示精度。通过对系统软件和硬件的合理规划,发挥单片机自身集成多系统功能单元的优势,在不减少功能的前提下有效降低了成本,系统操作简便。

关键词:STC89C52 DS18B20

红外传送

河北机电职业技术学院

第一章 系统硬件电路设计

1.1 电路总体原理框图

温度测量,温度显示输出及加热系统控制的总体结构如图3-1所示。体统主要包括现场温度采集、实时温度显示、系统运行时间显示、加热控制参数设置、加热电路控制输出、报警装置和系统核心STC89C52单片机作为微处理器。

数字式温 度传感器 显示器 加热器 单 片 机 越线报警 控制器

键盘

图3-1 恒温控制系统设计方案框图

温度采集电路以数字量形式将现场温度传至单片机。单片机结合现场温度与功能要求设定的目标温度,按照PID控制算法进行实时控制量。以此控制量控制继电器开通和关断,决定加热电路的工作状态,使水温逐步稳定于要求设定的目标值。在水温到达设定的目标温度后,由于自然冷却而使其温度下降时,单片机通过采样回的温度与设置的目标温度比较,作出响应的控制,开启加热器。系统运行过程中的各种状态均可由液晶显示器1602实时显示。

1.2 单片机的选择

用STC89C52的单片机作为控制主机。之所以选择89C52作为主机,是因为89C52作为51系列单片机的一种,其使用性能稳定,价格便宜,完全能够满足此次设计的需求。而且89C52内部集成了程序存储器,可以装载用户程序,方便后续的课程设计需要,不像8031因为要外接程序存储器而是电路相对麻烦了。其实物图如图3-2:

1

河北机电职业技术学院

图3-2 STC89C52实物图

1.3 温度采集电路的设计

由于本设计是精确控制系统,并且有控制范围上的要求,所以在选择传感器上要着重考虑其精度和测试范围。AD590和DS18B20都包含一个可以精确测量环境温度的片内温度传感器,但AD590是模拟传感器,需对温度模拟信号进行数字化处理,在调理和放大信号时,又会带来新的误差,影响精度,而DS18B20包含一个10位AD转换器,是一个以0.0625的分辨力将温度数字化的数字式温度传感器,并且其测温理论范围为-55度到125度,因其精确度高,范围可选这两大特点,故本设计的传感器选为DS18B20。

温度采集电路模块如图3-3所示。DS18B20内部结构主要有四个部分组成:1)64为光刻ROM;2)温度传感器;3)非易失性温度报警触发器TH和TL;4)配置寄存器。其中DQ为数字信号输入/输出端;GND为电源地;VDD为外接供电电源输入端。器件用如下方式从单线通讯线上汲取能量:在信号线处于高电平期间把能量存储在内部电容里,在信号线处于低电平期间消耗电容上的电能工作,直到高电平到来再给寄生电源(电容)充电。DS18B20也可以用外部5V电源供电。

图3-3 温度采集电路

DS18B20中的温度传感器可完成对温度的测量,用12位存储温值度,用16

2

河北机电职业技术学院

位符号扩展的二进制补码读数形式提供,以0.0625℃/LSB形式表达,其中S为符号位,负温度S=1,正温度S=0。如下图3-4为18B20的温度存储方式:

图3-4 18B20的温度存储方式

这是12位转化后得到的12位数据,存储在18B20的两个8比特的RAM中,二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测得的数值乘以0.0625即可得到实际温度。

例如:0550H为+85℃, 0191H为+25.0625℃, FC90H为-55℃。

1.4LCD显示接口电路的设计

显示电路采用字符型液晶显示模块,它是一种专门用于显示字母、数字、符号等点阵式的LCD,本设计采用的是SMC1602A LCM,其显示容量16×2个字符。我们在经典电路上做了一点修改,就是没有在3号引脚上加一个电位器,直接接在5V电压上面,使液晶一直处于最大亮度,因为我们觉得调不调节亮度在这次设计中起的作用不大,所以就省掉了。模块电路如下图3-6:

图3-6 LCD显示接口电路的设计

液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图3-7是1602的内部显示地址。

3

河北机电职业技术学院

图3-7 1602的内部显示地址

1.7红外发送与接收部分

1、 编码原理

这里我们以运用比较广泛,解码比较容易的一类来加以说明,现以日本NEC为例说明编码原理。NEC码产生的遥控编码是连续的32位二进制码组,其中前16位为用户识别码,能区别不同的电器在设备,防止不同机种遥控码互相干扰。后16位为8位功能码及其反码。 NEC数据帧格式:

当一个键按下超过36ms,振荡器使芯片激活,将发射一组108ms的编码脉冲,这108ms发射代码由一个起始码(9ms的高电平),一个结果码(4.5ms低电平),低8位地址码(9~18ms),高8位地址码(9~18ms),8位数据码(9~18ms)和这8位数据码的反码(9~18ms)组成。数据串行发送,低位(bit0)在前,高位(bit7)在后。 NEC遥控发送数据格式2009-7-13 - 2009-7-20前导电平2009-7-13 - 2009-7-2032位二进制编码2009-7-13 - 2009-7-20连发代码低8位地址码高8位地址码8位数据8位数据反码4.5ms2.5ms

如果键按下超过108ms仍未松开,接下来发射的代码(连发代码)将仅由起始码(9ms的高电平)和结束码(2.5ms低电平)组成。

在NEC编码格式中“0”,“1”的表示方法(脉宽调制)如下:

遥控发射码“0”0.565ms1.125ms0.56ms

4

河北机电职业技术学院

遥控发射码“1”0.565ms2.25ms1.685ms

前导电平信号起始码 (9ms)结果码 (4.5ms)

为了降低电源功耗,上述“0”和“1”组成的32位二进制码经38kHz的载频进行二次调制以提高发射效率。

注意:代码格式应以接收代码为准(接收代码与发射代码反向)。

2.VS_1838红外一体化接收头的使用

红外线遥控信号的接收,可以使用一种集红外线接收和放大于一体的一体化红外线接收器,不需要任何外接元件,就能完成从红外线接收到输出与TTL电平信号兼容的所有工作,比如:VS_1838b,体积和普通的塑封三极管大小一样。 接收器对外只有3个引脚:Out、GND、Vcc与单片机接口非常方便。

型号: VS1838B 1. 特性

●小型设计; ●内置专用 IC;

●宽角度及长距离接收; ●抗干扰能力强;

●能抵御环境光线干扰;

5

河北机电职业技术学院

●低电压工作;

●工作电压 Vcc 2.7~ 5.5 V ●接收距离 L 18 20 M ●载波频率 f 38k Hz

●低电平输出 VOL Vin=0V Vcc=5V 0.2 0.4 V ●高电平输出 VOH Vcc=5V 4.5 V

注意:VS_1838b的初状态(空闲状态)Out引脚输出高电平。

VS_1838b输出电平格式如下:

VS_1838b输出的码“1”0.565ms2.25ms1.685ms

VS_1838b输出的码“0”0.565ms1.125ms0.56ms

结果码 (4.5ms)

VS_1838b输出的前导电平信号起始码 (9ms)

VS_1838b接收头输出数据帧格式低8位地址码高8位地址码8位数据8位数据反码

VS_1838b与单片机的连接图:

6

河北机电职业技术学院

VS_1838bGNOutDVcc+5V STC89C52INT1P3^3

1.8 总电路的设计

发射部分

接收部分

7

河北机电职业技术学院

图3-10 总电路图的设计

参考文献

[1] 李全利、迟荣强. 单片机原理及接口技术. 北京:高等教育出版社,2004.1 [2] 谭浩强. C程序设计(第二版). 北京:清华大学出版社,1999.12

[3] 康华光. 电子技术基础数字部分(第四版). 北京:高等教育出版社,1900.1 [4] 黄智伟. 全国大学生电子设计竞赛电路设计. 北京:北京航空航天大学出版社,2006.12

[5] 黄智伟. 全国大学生电子设计竞赛系统设计. 北京:北京航空航天大学出版社,2006.12

8

河北机电职业技术学院

程序清单

//*****************************LCD部分****************************// #include #include \"1602.h\" #include \"delay.h\" sbit e=P2^2; sbit rw=P2^1; sbit rs=P2^0;

uchar line1[]=\" WD : 00.00 \"; uchar line2[]=\" SD : 00 \";

void write_com(uchar com) //write the data {

e=0; rs=0; rw=0; P1=com;

delay_50us(10); e=1;

delay_50us(20); e=0; }

void write_data(uchar dat) //write the order {

e=0; rs=1; rw=0; P1=dat;

delay_50us(10); e=1;

delay_50us(20); e=0; }

void init() //initiate {

delay_1ms(15); write_com(0x38); delay_1ms(5); write_com(0x38); delay_1ms(5); write_com(0x38); write_com(0x38); write_com(0x08);

9

河北机电职业技术学院

write_com(0x01); write_com(0x06);

write_com(0x0c); }

void display_init() //显示初始化函数 {

uint j; init();

write_com(0x80); for(j=0;j<16;j++) {

write_data(line1[j]); //display the first line delay_50us(1); } write_com(0xc0); for(j=0;j<16;j++) {

write_data(line2[j]); //display the scend line delay_50us(1); } }

void show1(uchar add,uchar dat) //显示第一行在哪一位上的那一个字符 { //add是位地址偏移量 uchar shi,ge; //dat为要显示的数据 shi=dat/10; ge=dat%10;

write_com(0x80+add);

write_data(0x30+shi); //此时只为数值 write_data(0x30+ge); }

void show2(uchar add,uchar dat) //显示第二行在哪一位上的那一个字符 { //add是位地址偏移量 uchar shi,ge; //dat为要显示的数据 shi=dat/10; ge=dat%10;

write_com(0xc0+add); //此时只为数值 write_data(0x30+shi); write_data(0x30+ge); }

//***************************DS18B20部分**************************// #include #include \"DS18B20.h\" #include \"delay.h\" #include \"1602.h\"

10

河北机电职业技术学院

sbit DQ=P2^3; //define the bus

uchar T_int,T_dot; //整数部分与小数部分 float t; //温度返回值

void init_DS18b20() //init ds18b20 {

uchar n; DQ=1;

delay(8); DQ=0;

delay(80); DQ=1;

delay(8); n=DQ;

delay(4); while(!DQ); }

void write_byte(uchar dat) //write the byte to bus {

uchar i;

for(i=0;i<8;i++) {

DQ=0;

DQ=dat&0x01; delay(4); DQ=1; dat>>=1; }

delay(4); }

uchar read_byte() //read the byte from bus {

uchar i,value; for(i=0;i<8;i++) {

DQ=0;

value>>=1; DQ=1; if(DQ)

value|=0x80; delay(4); }

return value; }

11

河北机电职业技术学院

float read_temperature(void) //read the temperature from rom {

uchar T_L,T_H,dot; float temp;

init_DS18b20(); //初始化 write_byte(0xcc); // 跳过ROM write_byte(0x44); //开始记录温度

delay(300); //等待BS18b20读完 init_DS18b20(); //初始化一次 write_byte(0xcc); //跳过ROM write_byte(0xbe); //读取ROM T_L=read_byte(); T_H=read_byte(); dot=T_L&0x0f; T_H<<=4;

T_H+=((T_L&0xf0)>>4); temp=T_H+dot*0.0625; return temp; }

//*************************红外发送部分***************************// #include #include \"ir_send.h\" bit irout;//红外管状态

sbit ir=P2^7;//红外发射管控制脚

uint count, set_count;//中断计数,设定中断次数 bit flag,keyflag;//红外发送标志,按键标志位 uchar ircode,irdata1,irdata2;

/*********************************延时1ms*******************/ //************************************************ //延时函数,在12MHZ情况下 //一次大约延时1ms

//************************************************ void delayn(uint t) {

uint j;

for (;t>0;t--)

for (j=19;j>0;j--); }

void send_data(uchar a,uchar b) {

irdata1=a; irdata2=b; }

12

河北机电职业技术学院

/*******************发送8位红外数据**********************/ void sendcode_8(void) {

uchar i;

for(i=0;i<8;i++) {

set_count=43;//发送0.56ms 38k红外波(编码中的0.56ms低电平) flag=1; count=0; TR0=1;

while(countif(ircode&0x01)//判断红外编码最低位,1宽的高电平,0窄的高电平 {

set_count=130; //1 } else {

set_count=43; //0 }

flag=0; count=0; TR0=1;

while(countircode=ircode>>1; } }

/***********************发送红外数据*******************************************/ void sendcode(void) {

set_count=346;//发送4.5ms 38K红外光 flag=1; count=0; TR0=1;

while(countset_count=346;//间隔4.5ms flag=0; count=0; TR0=1;

while(count13

河北机电职业技术学院

ircode=irdata1;//发送8位数据码 sendcode_8();

ircode=irdata2; //发送8位数据反码 sendcode_8();

set_count=43;//发送0.56ms 38k红外波(编码中的0.56ms低电平) flag=1; count=0; TR0=1;

while(countdelayn(23);//延时23ms(编码中的23ms高电平) set_count=346;//发送4.5ms 38k红外波 flag=1; count=0; TR0=1;

while(countset_count=346;//间隔4.5ms flag=0; count=0; TR0=1;

while(countset_count=43;//发送0.56ms 38k红外波(编码中的0.56ms低电平) flag=1; count=0; TR0=1;

while(count/*******************************************定时器初始*******************************************/ void init_timer() {

EA=1;

TMOD=0X02;//8位自动重载模式 ET0=1;

TH0=0Xf4;//定时13us,38K红外波,晶振11.0592 TL0=0Xf4; count=0; flag=0;

14

化 河北机电职业技术学院

irout=1; }

/*******************************************定时器中断

*******************************************/ void timer0(void) interrupt 1 {

count++; if(flag==1) {

irout=~irout; } else {

irout=1; }

ir=irout; }

//*************************发送主程序部分*************************// #include \"1602.h\" #include \"DS18B20.H\" #include \"ir_send.h\" #include \"delay.h\" void main() {

float t; //温度返回值 uchar T_int; uchar T_dot;

uchar sd; //湿度 display_init(); init_timer(); while(1) {

sd=78;

t=read_temperature(); //检测温度

T_int=(int)t; //取温度的整数部分 T_dot=(t-T_int)*100; //取温度的小数部分 show1(9,T_int); //小数点前两位 show1(12,T_dot) ; //小数点后两位 // show1(3,T_int); //小数点前两位 show2(9,sd); send_data(T_int,sd); sendcode(); }

15

河北机电职业技术学院

}

//*************************数码管部分*************************// #include \"smg.h\" #include sbit du=P2^0; sbit we=P2^1;

uchar code smg_du[17]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8, 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E, 0xbf};

uchar smg_we[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //************************************************** //用指针的方法显示放在数组中的数

//************************************************** void display_table(uchar *p) {

uchar i;

for(i=0;i<8;i++) {

P1=0xff; we=1; we=0;

P1=smg_du[*p++]; du=1; du=0;

P1=smg_we[i]; we=1; we=0;

delay_1ms(1); } }

//*************************************** //直接输入要显示的数

//*************************************** /*

void display(uchar num0,uchar num1,uchar num2,uchar num4,uchar num5,uchar num6,uchar num7) {

P1=0xff; we=1; we=0;

P1=smg_du[num0]; du=1; du=0;

P1=smg_we[0];

16

num3,uchar 河北机电职业技术学院

we=1; we=0;

delay_1ms(1); P1=0xff; we=1; we=0;

P1=smg_du[num1]; du=1; du=0;

P1=smg_we[1]; we=1; we=0;

delay_1ms(1); P1=0xff; we=1; we=0;

P1=smg_du[num2]; du=1; du=0;

P1=smg_we[2]; we=1; we=0;

delay_1ms(1); P1=0xff; we=1; we=0;

P1=smg_du[num3]; du=1; du=0;

P1=smg_we[3]; we=1; we=0;

delay_1ms(1); P1=0xff; we=1; we=0;

P1=smg_du[num4]; du=1; du=0;

P1=smg_we[4]; we=1; we=0;

delay_1ms(1); P1=0xff;

17

河北机电职业技术学院

we=1; we=0;

P1=smg_du[num5]; du=1; du=0;

P1=smg_we[5]; we=1; we=0;

delay_1ms(1); P1=0xff; we=1; we=0;

P1=smg_du[num6]; du=1; du=0;

P1=smg_we[6]; we=1; we=0;

delay_1ms(1); P1=0xff; we=1; we=0;

P1=smg_du[num7]; du=1; du=0;

P1=smg_we[7]; we=1; we=0;

delay_1ms(1); } */

//**********************红外接收部分**********************// #include #include \"smg.h\" #include \"delay.h\" #include \"receive.h\"

uchar irtimer; //红外时间 uchar startflag; //开始标志位 uchar bitnum; uchar irdata[17]; //接收数组

uchar irreceiveok; //接收好的标志位 uchar irreceivedata; //接收到的数

uchar ircode[2]; //装入提取出来的数 uchar irprocessok; //提取完的标志位 uchar irdis[8]; //可显示的数

18

河北机电职业技术学院

/*******************************/ /* 定时器0初始化设置函数 */ /*****************************/ void time0init() {

TMOD=0x02; //定时计数器0,方式2 TH0=0X00;

TL0=0X00; //255为中断一次 ET0=1; EA=1; TR0=1; }

/*******************************/ /* 外部中断初始化设置函数 */ /******************************/ void int0init() {

IT0=1; EX0=1; EA=1; }

/*****************************/ /* 红外初始化 */ /****************************/ void ir_init() {

time0init(); int0init(); }

/**************************/ /* 定时器中断,计数 */ /*************************/ void ir_timer0() interrupt 1 {

irtimer++; //255 }

/*********************************************************/ /* 外部中断1 */ /* 这里是更具我发送的数据而设置的,74为74个irtimer */ /* 即为18.92ms的引导码,然后将接收到的多少个irtimer */ /* 装入irdata[]这个数组中 。 */ /********************************************************/ void ir_int0() interrupt 0 {

19

河北机电职业技术学院

if(startflag) {

if(irtimer>33) //如果为引导码,则开始装数 {

bitnum=0; //第一个为引导码 }

irdata[bitnum]=irtimer; //装入多少个irtimer irtimer=0; //每次都要清零 bitnum++;

if(bitnum==16) {

bitnum=0;

irreceiveok=1; //接收完的标志位 startflag=0; } } else {

startflag=1; irtimer=0; }

}

void ir_process() //提取irdata {

uchar i,j,k; uchar value; k=1;

for(i=0;i<2;i++) {

for(j=0;j<8;j++) {

value=value>>1; if(irdata[k]>15) value=value | 0x80; k++; }

ircode[i]=value; }

irprocessok=1; } void ir_work() {

irdis[0]=ircode[0]/10; irdis[1]=ircode[0]%10;

20

//

河北机电职业技术学院

irdis[2]=16; irdis[3]=16; irdis[4]=16; irdis[5]=16;

irdis[6]=ircode[1]/10; irdis[7]=ircode[1]%10; }

void ir_display() {

if(irreceiveok) {

ir_process(); irreceiveok=0; } if(irprocessok) {

ir_work(); irprocessok=0;

}

display_table(irdis); }

//*************************接收主程序部分*************************// #include \"receive.h\"

#define uchar unsigned char #define uint unsigned int void main() {

ir_init(); while(1) {

ir_display(); } }

21

因篇幅问题不能全部显示,请点此查看更多更全内容