温控报警及显示系统的设计:温控报警
摘 要:基于AT89S52单片机与DS18B20温度传感器设计了一种温控上下限可调的温度报警及显示系统。该设计具有硬件电路相对简单,价格低廉、可靠性高、实时性好等特点。突出特点在于:具有温控的上、下限,而且温控值可键控调整,使得该设计的应用范围非常广泛,通用性极高。
关键词:AT89S52单片机;DS18B20;温度报警器;温控可调
1.引言
我国的火灾自动报警控制系统经历了从无到有、从简单到复杂的发展过程,其智能化程度也越来越高。在大型仓库、商场、高级写字楼、宾馆等场所大型火灾报警系统的研发,及在居民住宅区、机房、办公室等小型防火单位采用的实用的火灾自动探测报警装置,都离不开温度报警显示,因此研制一种结构简单、价格低廉的温度报警器是非常必要的,其发展前景广阔.本设计采用DS18B20温誉信御度传感器,其测温范围为-55~+125℃,并可设置温度报警的上、下值,当温度高于上限或低于下限时,系统自动报警。报警值具有可调性且温度测量范围较广,因此具有较高的应用前景。
2、系统组成框图
本系设计是基于AT89S52单片机的温度报警显示系统,系统组成框图如图1所示。用单片机AT89S52控制温度传感器DS18B20,读取数据。对DS18B20转换后的数据进行处理,将符号位、整数值和小数值分别存坦芹放在特定的存储单元中,转换成实际温度值通过液晶屏实时显示。通过键盘输入模块预先设定温度的上下限值,当温度超出报警值时,实时声光报警。
图1.系统组成框图
3.设计原理
(1)控制模块设计
本设计控制模块使用的单片机是最新型号的AT89S52单片机[1]。AT89S52是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程 Flash存储器。使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位 CPU 和在系统可编程Flash,使得 AT89S52为众多嵌入式控制应用系统提供高灵活、有效的解决方案。
(2)温度传感模块设计
本设计采用Dallas 最新单线数字温度传感器DS18B20[2]作温度检测器。DS18B20能够直接将所采集得信号进行模/数转换。这样应用系统的硬件电路中就不需要增加类似于ADC0809之类的模/数转换器,可直接送单片机处理,节约成本。DS18B20是美国DALLAS半导体公司继DS1820之后最新推出的一种改进型智能温度传感器。与传统的热敏电阻相比,他能够直接读出被测温度并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。测温范围-55~+125℃,以0.5℃递增,可以分别在93.75ms和750 ms内完成9位和12位的数字量,并且从DS18B20读出的信息或写入DS18B20的信息仅需要一根数据线(单线接口)读写,温度变换功率来源于数据总线,总线本身也可以向所挂接的DS18B20供电,而无需额外电源。因而使用DS18B20可使系统结构更趋简单,可靠性更高,其封装如图2所示。
图2 DS18B20芯片封装图
(3) 液晶显示模块设计
对于本系统而言,温度值的显示是一个重要的环节。设计中需显示的信息较多,为使显示内容更加丰富,采用LCD液晶显示。JM1602A[3]液晶显示器,它是一种字符点阵液晶显示器,主要由行驱动/列驱动组成,可完成字符点阵显示。JM1602A的实物图如图3所示: 带字库的JM1602可以显示汉字字符且编程简单,构成良好的人机交流界面,增强系统可操作性。另外考虑到本设计要显示字母,采用带字库庆岩的液晶显示“DS18B20 OK!”、“TEMP”等信息,直观效果非常好,功能比较强,操作也相对简单。
图3 LCD1602实物图
液晶模块与控制模块的通讯设计电路如图4所示:液晶显示使用并口方式,其中RD0-RD7为单片机的并行数据口, RA1为并行的指令/数据选择信号,RA2为并行的读写选择信号,RA3为并行的使能信号。
图4 LCD1602模块与控制模块通讯电路图
(4)报警模块设计
由于DS18B20具备自动的上、下限,当温度超出或低于报警值时,系统发出信号到报警系统,触发报警电路。报警考虑不同环境的影响采用声/光同时报警。蜂鸣器发出报警峰鸣,发光二极管闪烁。当单片机RC4端口为高电平时,三极管导通蜂鸣器发声报警。这个实验是喇叭里发出滴的按键声音声音,送出的端口是RC4(即单片机的p3.7口),输出1khz频率信号报警,每一秒交换一次。硬件中增加了发光二极管,和蜂鸣器一起接RC4端口,采用高电平触发,结构更简单,实现了声光报警,电路图如图5所示。
图5 声光报警电路图
(5)键盘输入方案
单片机的键盘结构可以采用独立式和矩阵式键盘两种[4]。独立式按键指直接用I/O口线构成单个按键电路,每个独立式按键单独占用一位I/O口线。电路配置灵活,软件结构简单。但在按键数量较多时,I/O口线浪费大。如果应用系统中的键较少,就可采用简单的键盘接口电路。 由于本设计要设置四个按键,按键较少,故采用独立式按键。由单片机的p1.1-p1.4的四个端口分别检测四个按键,通过键扫描程序实时的监测按键是否操作。四个按键的功能如表1所示:
5、系统软件设计
根据本设计温度报警显示的要求,系统首先对单片机的系统进行初始化和常量的设置[5],然后调用温度传感器的初始化子程序初始化芯片,芯片随即开始工作,系统读取转换的温度值通过液晶屏实时显示,键扫描初始设置的温度上下限,比较实时的温度是否超过限制值,一旦超过马上通过声光报警。软件设计流程图如图6所示。
图6 系统软件流程图
6、结语
通过实际测试,本系统可以监控环境温度,实时性较好并可以人为的设制温度上下限,而新型温度器芯片的实用,又使得设计成本下降,因此具有较为广泛的应用前景。
参考文献
[1]周兴华,手把手教你学单片机,北京航空航天大学出版社,67-79, 2007
基于单片
1加指互说23456789101112131415161718192021222324252627282930313233343536373839404142434九校干4454647484静肥计盟盟乱盟球服额改9505152535455565758596061626培庆套3646566676869707172737475767778798081落办挥西班硫频各济铁828384858687河双支一没只劳扬杆声投88899091远进929394959697989910010110210310410510末乎海口卫操阳杀象率烈610710810911局求均01111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431混宁总形婷传当示史点展441451461471481491501511521531541551561适站话席都57158159160161162163164165166167168169170171172173174久说17517617负七土7178179180181182183184185186187188189190191192193194195196掌让金宁显消烧若197198199200201至着雷2022032042052062072082092102112122132142152162172182192202燃跟室备军名微责触哪21222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257/******************************************型花范岩格胜** 读取DS18呢卫配B20温度,通过LCD1602显示出来第一行: 实时温度值第二行: 最大值和最小值********************************************/ /*头文件*/#include <reg52.h> #include <intrins.h>#define uint unsigned int#define uchar unsigned char#define _Nop() _nop_() sbit DQ =P2^2; //定义DS18B20通信端口sbit lcd_rs_port = P3^5; /*定义LCD控制端口*/sbit lcd_rw_port = P3^6;sbit lcd_en_port = P3^4;#define lcd_data_port P0////////////////////////////////////////sbit WELA=P2^7; //数码管的位选信号void delay1 (void)//关闭数码管延时程序{ int k; for (k=0; k<1000; k++); }////////////////////////////////////// //////////////以下是LCD1602驱动程序//////////////// void lcd_delay(uchar ms) /*LCD1602 延时*/{ uchar j; while(ms--){ for(j=0;j<250;j++) {;} } } void lcd_busy_wait() /*LCD1602 忙等待*/{ lcd_rs_port = 0; lcd_rw_port = 1; lcd_en_port = 1; lcd_data_port = 0xff; while (lcd_data_port&0x80); lcd_en_port = 0; } void lcd_command_write(uchar command) /*LCD1602 命令字写入*/{ lcd_busy_wait(); lcd_rs_port = 0; lcd_rw_port = 0; lcd_en_port = 0; lcd_data_port = command; lcd_en_port = 1; lcd_en_port = 0; } void lcd_system_reset() /*LCD1602 初始化*/{ lcd_delay(20); lcd_command_write(0x38); lcd_delay(100); lcd_command_write(0x38); lcd_delay(50); lcd_command_write(0x38); lcd_delay(10); lcd_command_write(0x08); lcd_command_write(0x01); lcd_command_write(0x06); lcd_command_write(0x0c); } void lcd_char_write(uchar x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/{ x_pos &= 0x0f; /* X位置范围 0~15 */ y_pos &= 0x01; /* Y位置范围 0~ 1 */ if(y_pos==1) x_pos += 0x40; x_pos += 0x80; lcd_command_write(x_pos); lcd_busy_wait(); lcd_rs_port = 1; lcd_rw_port = 0; lcd_en_port = 0; lcd_data_port = lcd_dat; lcd_en_port = 1; lcd_en_port = 0; } void lcd_bad_check() /*LCD1602 坏点检查*/{ char i,j; for(i=0;i<2;i++){ for(j=0;j<16;j++) { lcd_char_write(j,i,0xff); } } lcd_delay(200); lcd_delay(200); lcd_delay(200); lcd_delay(100); lcd_delay(200); lcd_command_write(0x01); /* clear lcd disp */}//////////////////以上是LCD1602驱动程序//////////////// //////////////////以下是DS18B20驱动程序//////////////////延时函数void delay(unsigned int i){ while(i--);} //初始化函数Init_DS18B20(void){ unsigned char x=0; DQ = 1; //DQ复位 delay(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay(14); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay(20);} //读一个字节ReadOneChar(void){ unsigned char i=0; unsigned char dat = 0; for (i=8;i>0;i--){ DQ = 0; // 给脉冲信号 dat>>=1; DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80; delay(4); } return(dat);} //写一个字节WriteOneChar(unsigned char dat){ unsigned char i=0; for (i=8; i>0; i--){ DQ = 0; DQ = dat&0x01; delay(5); DQ = 1; dat>>=1; }} //读取温度ReadTemperature(void){ unsigned char a=0; unsigned char b=0; unsigned int t=0; float tt=0; Init_DS18B20(); WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 Init_DS18B20(); WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 a=ReadOneChar(); b=ReadOneChar(); t=b; t<<=8; t=t|a; tt=t*0.0625; //将温度的高位与低位合并 t= tt*10+0.5; //对结果进行4舍5入 return(t);}//////////////////以上是DS18B20驱动程序//////////////// /*定义数字ascii编码*/unsigned char mun_char_table[]={"0123456789abcdef"}; unsigned char temp_table[] ={"Temp: . 'C"};unsigned char temp_high_low[]={"H: . L: . "}; /*1MS为单位的延时程序*/void delay_1ms(uchar x){ uchar j; while(x--){ for(j=0;j<125;j++) {;} } } main(){ unsigned int i=0; unsigned int temp_high; unsigned int temp_low; ReadTemperature(); /*读取当前温度*/ lcd_system_reset(); /*LCD1602 初始化*///////////////////////////////////////////////////////////////// P0=0XFF;//关掉数码管的位选信号。阻止数码管受到P0口信号的影响。 delay(); WELA=1; delay(); WELA=0;//////////////////////////////////////////////////////////////// lcd_bad_check(); /*LCD1602 坏点检查*/ for (i=0;i<12;i++) lcd_char_write(i,0,temp_table[i]); for (i=0;i<16;i++) lcd_char_write(i,1,temp_high_low[i]); i=ReadTemperature(); /*读取当前温度*/ temp_high = i; temp_low = i; while(1){ i=ReadTemperature(); //读取当前温度 if(temp_high<i) temp_high=i; if(temp_low>i) temp_low=i; lcd_char_write(6,0,mun_char_table[i/100]); /*把温度显示出来*/ lcd_char_write(7,0,mun_char_table[i%100/10]); lcd_char_write(9,0,mun_char_table[i%10]); lcd_char_write(2,1,mun_char_table[temp_high/100]); /*显示最高温度*/ lcd_char_write(3,1,mun_char_table[temp_high%100/10]); lcd_char_write(5,1,mun_char_table[temp_high%10]); lcd_char_write(10,1,mun_char_table[temp_low/100]); /*显示最低温度*/ lcd_char_write(11,1,mun_char_table[temp_low%100/10]); lcd_char_write(13,1,mun_char_table[temp_low%10]); delay_1ms(100); }}
avr单片机18B20温度传感器编程
;这是关于DS18B20的读写程序,数据脚P2.2,晶振12MHZ
;温度传感器18B20汇编程序,采用器件默认的12位转化,最大转化时间750微秒
;可以将检测到的温度直接显示到AT89C51开发实验板的两个数码管上
;显示温度00到99度,很准确哦~~无需校正!
ORG 0000H ;单片机内存分配申明!
TEMPER_L EQU 29H;用于保存读出温度的低8位
TEMPER_H EQU 28H;用于保存读出温度的高8位
FLAG1 EQU 38H;是否检测到DS18B20标志位
a_bit equ 20h ;数码管个位数存放内存位置
b_bit equ 21h ;数码管十位数存放内存位置
TEMP_TH EQU
MAIN:
LCALL GET_TEMPER;调用读温度子程序 ,显示范围00到99度,显示精度为1度
;因为12位转化时每一位的精度为0.0625度,我们不要求显示小数所以可以抛弃29H的低4位
;将28H中的低4位移入29H中的高4位,这样获得一个新字节,这个字节就是实际测量获得的温度
MOV A,29H
MOV C,40H;将28H中的最低位移入C
RRC A
MOV C,41H
RRC A
MOV C,42H
RRC A
MOV C,43H
RRC A
MOV 29H,A
LCALL DISPLAY ;调用数码管显示子程序
CPL P1.0
AJMP MAIN
; 这是DS18B20复位初始化子程序
INIT_1820:
SETB P3.5
NOP
CLR P3.5 ;主机发出延时537微秒的复位低脉冲
MOV R1,#3
TSR1:MOV R0,#107
DJNZ R0,$
DJNZ R1,TSR1
SETB P3.5 ;然后拉高数据线
NOP
NOP
NOP
MOV R0,#25H
TSR2:
JNB P3.5,TSR3 ;等待DS18B20回应
DJNZ R0,TSR2
LJMP TSR4 ; 延时
TSR3:
SETB FLAG1 ; 置标志位,表示DS1820存在
CLR P1.7 ;检查到DS18B20就点亮P1.7LED
LJMP TSR5
TSR4:
CLR FLAG1 ; 清标志位,表示DS1820不存在
CLR P1.1 ;点亮P1。1脚LED表示温度传感器通信失败
LJMP TSR7
TSR5:
MOV R0,#117
TSR6:
DJNZ R0,TSR6 ; 时序要求延时一段时间
TSR7:
SETB P3.5
RET
; 读出转换后的温度值
GET_TEMPER:
SETB P3.5
LCALL INIT_1820 ;先复位DS18B20
JB FLAG1,TSS2
CLR P1.2
RET ; 判断DS1820是否存在?若DS18B20不存在则返回
TSS2:
CLR P1.3 ;DS18B20已经被检测到!!!!!!!!!!!!!!!!!!
MOV A,#0CCH
LCALL WRITE_1820
MOV A,#44H ;发出温度转换命令
LCALL WRITE_1820
;这里通过调用显示子程序实现延时一段时间,等待AD转换结束,12位的话750微秒
LCALL DISPLAY
LCALL INIT_1820 ;准备读温度前先复位
MOV A,#0CCH ; 跳过ROM匹配
LCALL WRITE_1820
MOV A,#0BEH ; 发出读温度命令
LCALL WRITE_1820
LCALL READ_18200; 将读出的温度数据保存到35H/36H
CLR P1.4
RET
;写DS18B20的子程序(有具体的时序要求)
WRITE_1820:
MOV R2,#8;一共8位数据
CLR C
WR1:
CLR P3.5
MOV R3,#6
DJNZ R3,$
RRC A
MOV P3.5,C
MOV R3,#23
DJNZ R3,$
SETB P3.5
NOP
DJNZ R2,WR1
SETB P3.5
RET
; 读DS18B20的程序,从DS18B20中读出两个字节的温度数据
READ_18200:
MOV R4,#2 ; 将温度高位和低位从DS18B20中读出
MOV R1,#29H ; 低位存入29H(TEMPER_L),高位存入28H(TEMPER_H)
RE00:
MOV R2,#8;数据一共有8位
RE01:
CLR C
SETB P3.5
NOP
NOP
CLR P3.5
NOP
NOP
NOP
SETB P3.5
MOV R3,#9
RE10:
DJNZ R3,RE10
MOV C,P3.5
MOV R3,#23
RE20:
DJNZ R3,RE20
RRC A
DJNZ R2,RE01
MOV @R1,A
DEC R1
DJNZ R4,RE00
RET
;显示子程序
display: mov a,29H;将29H中的十六进制数转换成10进制
mov b,#10 ;10进制/10=10进制
div ab
mov b_bit,a ;十位在a
mov a_bit,b ;个位在b
mov dptr,#numtab ;指定查表启始地址
mov r0,#4
dpl1: mov r1,#250 ;显示1000次
dplop: mov a,a_bit ;取个位数
MOVC A,@A+DPTR ;查个位数的7段代码
mov p1,a ;送出个位的7段代码
setb p2.0 ;开个位显示
acall d1ms ;显示1ms
clr p2.0
mov a,b_bit ;取十位数
MOVC A,@A+DPTR ;查十位数的7段代码
mov p1,a ;送出十位的7段代码
setb p2.1 ;开十位显示
acall d1ms ;显示1ms
clr p2.1
djnz r1,dplop ;100次没完循环
djnz r0,dpl1 ;4个100次没完循环
ret
;1MS延时(按12MHZ算)
D1MS: MOV R7,#80
DJNZ R7,$
RET
numtab: ;数码管共阳极0~9代码
DB 0C0H,0F9H,0A4H,0B0H,99H, 92H,82H,0F8H,80H,90H
end
感觉对你有用就赏分吧~