永发信息网

以AT89C51单片机和DS18B20实现温度检测显示并报警的程序和电路图,显示用M016L液晶模块显示

答案:1  悬赏:20  手机版
解决时间 2021-11-18 14:34
  • 提问者网友:杀手的诗
  • 2021-11-18 03:42
以AT89C51单片机和DS18B20实现温度检测显示并报警的程序和电路图,显示用M016L液晶模块显示
最佳答案
  • 五星知识达人网友:掌灯师
  • 2021-11-18 04:34
汇编语言程序:
 
;*********************************************************************
;程序适合单个DS18B20和MCS-51单片机的连接,晶振为12MHz
;测量的温度范围-55℃~+99℃,温度精确到小数点后一位 
;*********************************************************************
TEMPER_L    EQU    30H       ;存放从DS18B20中读出的高、低位温度值
TEMPER_H    EQU    31H
TEMPER_NUM  EQU    32H       ;存放温度转换后的整数部分
TEMPER_POT  EQU    33H       ;存放温度转换后的小数部分
FLAG0       EQU    34H       ;FLAG0存放温度的符号 
DQ           EQU    P1.0      ;DS18B20数据线
RS   BIT   P1.7              ;LCD1602控制线定义
RW   BIT   P1.6
E    BIT   P1.5
SkipDs18b20    EQU    0CCH   ;DS18B20跳过ROM命令
StartDs18b20   EQU    44H    ;DS18B20温度变换命令     
ReadDs          EQU    0BEH   ;DS18B20读暂存器命令
 
       ORG 0000H
       SJMP MAIN
       ORG 0040H
 MAIN:MOV SP,#60H
    ACALL  LCD_INIT
    MOV   A,#80H            ;lcd第1行第1列开始显示temperature:
    ACALL  WC51R
    MOV   A,#'t'                 
    ACALL  WC51DDR
    MOV   A,#'e'                
    ACALL  WC51DDR
    MOV   A,#'m'                
    ACALL  WC51DDR
    MOV   A,#'p'                
    ACALL  WC51DDR
    MOV   A,#'e'                 
    ACALL  WC51DDR
    MOV   A,#'r'                 
    ACALL  WC51DDR
    MOV   A,#'a'                
    ACALL  WC51DDR
    MOV   A,#'t'                
    ACALL  WC51DDR
    MOV   A,#'u'                 
    ACALL  WC51DDR
    MOV   A,#'r'                 
    ACALL  WC51DDR
    MOV   A,#'e'                
    ACALL  WC51DDR
    MOV   A,#':'                
    ACALL  WC51DDR
REP:LCALL GET_TEMPER    ;读出转换后的温度值
     LCALL TEMPER_COV
    MOV   A,#0c6H           ;lcd第2行第7列开始显示温度
    ACALL  WC51R
    MOV   A,FLAG0           ;显示符号
    ACALL  WC51DDR
    MOV   A,TEMPER_NUM      ;温度整数拆分成十位和个位显示
    MOV   B,#10
    DIV   AB
    ADD   A,#30H
    CJNE  A,#30H,REP1       ;如果十位为0不显示
    MOV   A,#20H
REP1:ACALL  WC51DDR
    MOV   A,B
    ADD   A,#30H       
     ACALL  WC51DDR
    MOV   A,#'.'            ;显示小数点 
     ACALL  WC51DDR
    MOV   DPTR,#TABLE
    MOV   A,TEMPER_POT      ;显示小数部分
    MOVC  A,@A+DPTR
     ACALL  WC51DDR     
     LJMP REP
;DS18B20复位程序
DS18B20_INIT:SETB  DQ
    NOP
    NOP
    CLR     DQ
    MOV R7,#9
INIT_DELAY: CALL    DELAY60US
    DJNZ    R7,INIT_DELAY
    SETB    DQ
    CALL    DELAY60US
    CALL    DELAY60US
    MOV     C,DQ
     JC  ERROR
    CALL    DELAY60US
    CALL    DELAY60US
    CALL    DELAY60US
    CALL    DELAY60US
    RET
ERROR:CLR   DQ
     SJMP    DS18B20_INIT
     RET
;读DS18B20一个字节到累加器A程序
READ_BYTE:  MOV     R7,#08H
    SETB    DQ
    NOP
    NOP
LOOP:CLR    DQ
     NOP
    NOP
    NOP
    SETB    DQ
    MOV     R6,#07H
    DJNZ    R6,$
    MOV     C,DQ
    CALL    DELAY60US
    RRC     A
    SETB    DQ
    DJNZ    R7,LOOP
    CALL    DELAY60US
    CALL    DELAY60US
    RET
;累加器A写到DS18B20程序
WRITE_BYTE: MOV     R7,#08H
    SETB    DQ
    NOP
    NOP
LOOP1:CLR  DQ
     MOV     R6,#07H
    DJNZ    R6,$
    RRC     A
    MOV     DQ,C
    CALL    DELAY60US
    SETB    DQ
    DJNZ    R7,LOOP1
    RET
DELAY60US:MOV   R6,#1EH
    DJNZ    R6,$
    RET
;读温度程序
GET_TEMPER: CALL    DS18B20_INIT    ;DS18B20复位程序
     MOV     A,#0CCH                 ;DS18B20跳过ROM命令
    CALL    WRITE_BYTE
    CALL    DELAY60US
    CALL    DELAY60US
    MOV     A,#44H                  ;DS18B20温度变换命令
    CALL    WRITE_BYTE
    CALL    DELAY60US
CALL    DS18B20_INIT            ;DS18B20复位程序
    MOV         A,#0CCH                 ;DS18B20跳过ROM命令
    CALL    WRITE_BYTE
    CALL    DELAY60US
    MOV         A,#0BEH                 ;DS18B20读暂存器命令
    CALL    WRITE_BYTE
    CALL    DELAY60US
    CALL    READ_BYTE               ;读温度低字节
    MOV     TEMPER_L,A
    CALL    READ_BYTE               ;读温度高字节
    MOV     TEMPER_H,A
    RET     
;将从DS18B20中读出的温度拆分成整数和小数
TEMPER_COV:
    MOV    FLAG0,#'+'                  ;设当前温度为正
    MOV    A,TEMPER_H
    SUBB    A,#0F8H
    JC      TEM0                   ;看温度值是否为负?不是,转
    MOV    FLAG0,#'-'                  ;是,置FLAG0为'-'
    MOV    A,TEMPER_L
    CPL    A
    ADD    A,#01
    MOV    TEMPER_L,A
    MOV    A,TEMPER_H
    CPL    A
    ADDC   A,#00
    MOV    TEMPER_H,A
TEM0:
    MOV    A,TEMPER_L            ;存放小数部分到TEMPER_POT     
    ANL    A,#0FH
    MOV    TEMPER_POT,A
    MOV    A,TEMPER_L             ;存放小数部分到TEMPER_NUM
    ANL    A,#0F0H
    SWAP   A
    MOV    TEMPER_NUM,A
    MOV    A,TEMPER_H
    SWAP    A
    ORL    A,TEMPER_NUM
    MOV    TEMPER_NUM,A       
    RET
    ;LCD初始化子程序
LCD_INIT:MOV  A,#00000001H  ;清屏
    ACALL  WC51R
    MOV   A,#00111000B  ;使用8位数据,显示两行,使用5×7的字型
    LCALL  WC51R
    MOV   A,#00001100B   ;显示器开,光标关,字符不闪烁
    LCALL  WC51R
    MOV   A,#00000110B   ;字符不动,光标自动右移一格
    LCALL  WC51R
    RET
    ;检查忙子程序
    F_BUSY:PUSH  ACC    ;保护现场
    MOV   P2,#0FFH
    CLR  RS
    SETB  RW
WAIT:   CLR   E
    SETB  E
    JB   P2.7,WAIT      ;忙,等待
    POP   ACC               ;不忙,恢复现场
    RET
    ;写入命令子程序
WC51R:  ACALL  F_BUSY
    CLR   E
    CLR  RS
    CLR  RW
    SETB  E
    MOV  P2,ACC
    CLR  E
    RET
    ;写入数据子程序
WC51DDR:ACALL  F_BUSY
    CLR   E
    SETB  RS
    CLR  RW
    SETB  E
    MOV  P2,ACC
    CLR  E
    RET
TABLE: DB   30H,31H,31H,32H,33H,33H,34H,34H
        DB   35H,36H,36H,37H,38H,38H,39H,39H  ;小数温度转换表
    END
 
C语言程序:
//程序适合单个DS18B20和MCS-51单片机的连接,晶振为12MHz
//测量的温度范围-55℃~+99℃,温度精确到小数点后一位 
 
#include 
#define uchar unsigned char
#define uint unsigned int
sbit  DQ =P1^0;                       //定义端口
sbit  RS=P1^7;
sbit  RW=P1^6;
sbit  EN=P1^5;
union{
    uchar c[2];
    uint x;
}temp;
uchar flag;//flag为温度值的正负号标志单元, "1"表示为负值,"0"时表示为正值。 
uint cc,cc2;//变量cc中保存读出的温度值   
float cc1;
uchar buff1[13]={"temperature:"};
uchar buff2[6]={"+00.0"};
//检查忙函数
void  fbusy()
{
    P2 = 0xff;
    RS = 0;
    RW = 1;
    EN = 1;
    EN = 0;
    while((P2 & 0x80))
    {
    EN = 0; 
    EN = 1;     
    }
}
//写命令函数
void  wc51r(uchar  j)
{
    fbusy();
    EN = 0;
    RS = 0;
    RW = 0;
    EN = 1;
    P2 = j;
    EN = 0;
}
//写数据函数
void  wc51ddr(uchar  j)
{
    fbusy();        //读状态;
    EN = 0;
    RS = 1;
    RW = 0;
    EN = 1;
    P2 = j;
    EN = 0;
}
void  init()
{
wc51r(0x01);         //清屏
wc51r(0x38);         //使用8位数据,显示两行,使用5*7的字型
wc51r(0x0c);         //显示器开,光标开,字符不闪烁
wc51r(0x06);         //字符不动,光标自动右移一格
}
void delay(uint useconds)                 //延时程序
{
  for(;useconds>0;useconds--);
}
uchar ow_reset(void)                       //复位
{
  uchar presence;
  DQ = 0;                               // DQ 低电平
  delay(50);                           // 480ms
  DQ = 1;                                // DQ 高电平
  delay(3);                             // 等待
  presence = DQ;                       // presence 信号
  delay(25);
  return(presence);                     // 0允许, 1禁止
}                                         
uchar read_byte(void)                    //从单总线上读取一个字节
{
  uchar i;
  uchar value = 0;
  for (i=8;i>0;i--)
  {
    value>>=1;
    DQ = 0;
    DQ = 1;
    delay(1);
    if(DQ)value|=0x80;
    delay(6);
  }
  return(value);
}
void write_byte(uchar val)       //向单总线上写一个字节
{
  uchar i;
  for (i=8; i>0; i--)             // 一次写一字节
  {
    DQ = 0;
    DQ = val&0x01;
    delay(5);
    DQ = 1;
    val=val/2;
  }
  delay(5);
}
 
void Read_Temperature(void)     //读取温度
{
  ow_reset();
  write_byte(0xCC);               // 跳过 ROM
  write_byte(0xBE);               // 读
  temp.c[1]=read_byte();
  temp.c[0]=read_byte();
  ow_reset();
  write_byte(0xCC);
  write_byte(0x44);               // 开始 
  return;
}
void main()                        //主程序
{
uchar  k;
delay(10);
  EA=0;
  flag=0;
  init();
wc51r(0x80);                      //写入显示缓冲区起始地址为第1行第1列
for (k=0;k<13;k++)              //第一行显示提示信息"current temp is:"
    { wc51ddr(buff1[k]);}
while(1)
 {
  delay(10000); 
  Read_Temperature();             //读取双字节温度
  cc=temp.c[0]*256.0+temp.c[1];
  if  (temp.c[0]>0xf8) {flag=1;cc=~cc+1;}else flag=0;
  cc1=cc*0.0625;              //计算出温度值
 
  cc2=cc1*100;                  //放大100倍,放在整型变量中便于取数字
  buff2[1]=cc2/1000+0x30;if ( buff2[1]==0x30) buff2[1]=0x20;//取出十位,转换成字符,如果十位是0不显示。
  buff2[2]=cc2/100-(cc2/1000)*10+0x30;//取出个位,转换成字符
  buff2[4]=cc2/10-(cc2/100)*10+0x30;//取出小数点后一位,转换成字符
  if (flag==1) buff2[0]='-';else buff2[0]='+';
  wc51r(0xc5);            //写入显示缓冲区起始地址为第2行第6列     
  for (k=0;k<6;k++)         //第二行显示温度
    { wc51ddr(buff2[k]);}
}
}

 
我要举报
如以上回答内容为低俗、色情、不良、暴力、侵权、涉及违法等信息,可以点下面链接进行举报!
点此我要举报以上问答信息
大家都在看
推荐资讯