远 程 温 度 控 制
摘要
本设计以单片机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 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 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 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(count set_count=130; //1 } else { set_count=43; //0 } flag=0; count=0; TR0=1; while(count /***********************发送红外数据*******************************************/ void sendcode(void) { set_count=346;//发送4.5ms 38K红外光 flag=1; count=0; TR0=1; while(count while(count 河北机电职业技术学院 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(count while(count while(count while(count 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 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 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 因篇幅问题不能全部显示,请点此查看更多更全内容