DS18B20数字温度传感器的驱动设计与实现

2023-07-09

温控报警及显示系统的设计:温控报警

  摘 要:基于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

感觉对你有用就赏分吧~

文章推荐

相关推荐