找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8851|回复: 10
打印 上一主题 下一主题
收起左侧

单片机+LCD12864温度显示(DS18B20)

  [复制链接]
跳转到指定楼层
楼主
ID:531882 发表于 2019-7-22 21:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

---------------------------------------------------------------LCD12864温度显示(DS18B20)------------------------------------------------------------
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcden=P3^4;      //定义lcd使能端
sbit lcdrs=P3^5;      //定义lcd数据命令选择端
sbit lcdwr=P3^6;      //定义lcd读写选择端
sbit lcdrd=P3^7;      //定义并串选择端
sbit DQ=P2^2;       //定义DS18B20数据线引脚端
uchar high,low;
char a,d2,d1,d0;
float f_temp;
uint i,j,temp;
uchar code line1[] = {"电工电子创新协会"};
uchar code line2[]="当前温度:";
uchar code line3[]="00.0度";
//-------------------毫秒级延时函数-------------------------
void delay_ms(uint z)      //延时z毫秒
{
uint x,y;
for(x=z;x>0;x--)
  for(y=115;y>0;y--);
}
//------------lcd写指令函数-------------
void wr_cmd(uchar cmd)
{
lcden=0;
lcdrs=0;
P0=cmd;
delay_ms(1);
lcden=1;
delay_ms(1);
lcden=0;
}
//-----------lcd写数据函数-----------
void wr_dat(uchar dat)
{
lcden=0;
lcdrs=1;
P0=dat;
delay_ms(1);
lcden=1;        
delay_ms(1);
lcden=0;
}

//-----------------------用户界面文字显示函数--------------------------
void face_dis()      
{
wr_cmd(0x30);           //选择功能:8位数据基本指令操作
wr_cmd(0x0c);          //整体显示开,不显示光标
wr_cmd(0x01);          //lcd清屏
wr_cmd(0x02);          //游标归原点
wr_cmd(0x80);
for(a=0;a<16;a++)         //写入第二行数据
{
  wr_dat(line1[a]);
}

wr_cmd(0x90);          //设置第二行起始位
for(a=0;a<10;a++)         //写入第二行数据
{
  wr_dat(line2[a]);
}
wr_cmd(0x8c);          //设置第三行起始位
for(a=0;a<6;a++)         //写入第三行数据
{
  wr_dat(line3[a]);
}
}
//------------------------用户界面数据显示函数-------------------------------
void dat_dis()
{
wr_cmd(0x8c);  //显示温度
wr_dat(0x30+d2);
wr_dat(0x30+d1);
wr_dat(0x2e);  //写入“.”号
wr_dat(0x30+d0);
}
//-----------------------------初始化函数------------------------------------
void init()
{
delay_ms(20);      //等待液晶输入电源稳定
lcdrd=1;       //选定lcd与单片机并行连接
lcdwr=0;       //因为我们不需要从lcd模块读数据,所以可直接将此端口清零,便于之后利用矩阵键盘
face_dis();       //显示用户界面
}
//-----------------------获温部分:初始化函数--------------------
void init_temp()
{
DQ=0;  //拉低总线,产生复位信号
i=80;while(i>0)i--;  //延时480~960us
DQ=1;  //拉高总线
i=4;while(i>0)i--;  //延时15~60us
while(DQ);  //等待产生应答脉冲
i=70;while(i>0)i--;  //延时至少480us
}
//------------------获温部分:写函数-------------------------------
void wr_temp(uchar dat)  //写1个字节
{
bit testb;
for(j=8;j>0;j--)
{
  testb=dat&0x01;
  dat=dat>>1;
  if(testb)  //写1
  {
   DQ=0;  //拉低总线,产生写时间隙
   i++;  //延时大于1us
   DQ=1;  //拉高总线
   i=8;while(i>0)i--;  //延时至少60us,供DS18B20采样
  }
  else    //写0
  {
   DQ=0;  //拉低总线,产生写时间隙
   i=8;while(i>0)i--;  //保持至少60us,供DS18B20采样
   DQ=1;  //拉高总线
   i++;i++;
  }
}
}
//------------------获温部分:读函数-------------------------------
uchar rd_temp()  //读1个字节
{
bit b;  //定义存放接收到的1个字节
uchar i_b;
uchar rdbyte;
for(j=8;j>0;j--)
{
  DQ=0;  //拉低总线,产生读时隙
  i++;  //延时大于1us
  DQ=1;  //释放总线
  i++;i++;  //给一定时间让总线释放
  b=DQ;  //读取数据
  i=8;while(i>0)i--;  //延时至少60us
  i_b=b;
  rdbyte=(i_b<<7)|(rdbyte>>1);  //将读取到得一位值左移7位,存放读取的数据变量rdbyte右移1位
}
return rdbyte;
}
//----------------------温度获取函数-----------------------

12864温度显示——成功.zip

33.56 KB, 下载次数: 446, 下载积分: 黑币 -5

完整代码

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏10 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:774122 发表于 2020-7-6 22:25 | 只看该作者
可以问一下么,怎么调到在第一行显示  当前温度:xx.x度
回复

使用道具 举报

板凳
ID:510861 发表于 2020-7-8 07:24 来自手机 | 只看该作者
看着很简单,做起来好蓝
回复

使用道具 举报

地板
ID:160725 发表于 2020-7-17 08:40 | 只看该作者
认真学习 才是硬道理
回复

使用道具 举报

5#
ID:830257 发表于 2020-11-25 09:29 | 只看该作者
没有仿真图?
回复

使用道具 举报

6#
ID:848824 发表于 2021-1-14 22:01 | 只看该作者
所有引脚都接吗,我没不会能给个接线图吗
回复

使用道具 举报

7#
ID:390416 发表于 2021-1-15 11:49 | 只看该作者
我们写的DS18B20的代码 初始化是不需要死等延迟的,有需要的可以下载
http://www.51hei.com/bbs/dpj-200968-1.html
回复

使用道具 举报

8#
ID:962672 发表于 2021-9-4 09:43 | 只看该作者
;**********************************************************************
;晶振为12MHZ,显示实时时间,温度
;测量温度范围为-55~+99摄氏度
;***********************************************************************
                T_RST                        EQU                P1.5                //DS1302复位线引脚
                T_CLK                        EQU                P1.6                //DS1302时钟线引脚
                T_IO                        EQU                P1.7                //DS1302数据线引脚

                TEM_L                        EQU                40H                        //存放从DS18B20中读出的高、低位温度值
                TEM_H                        EQU                41H               
                TEM_NUM                        EQU                42H                        //存放温度转换后的整数部分
                FLAG0                        EQU                45H                        //FLAG0存放温度的符号
                DQ                                EQU                P2.3                //DS18B20数据线

                RS                                BIT                P2.0                //LCD控制线定义
                RW                                BIT                P2.1               
                E                                BIT                P2.2

                SKIP_B20                EQU                0CCH                //DS18B20跳过ROM命令
                START_B20                EQU                44H                        //DS18B20温度变换命令
                READDS                        EQU                0BEH                //DS18B20读暂存器命令
               
                ORG                0000H
                AJMP        MAIN
                ORG                0100H
MAIN:        MOV                SP,#90H
                ACALL        LCD_INT                                          //进行LCD初始化
                MOV                A,#8BH                                                //在LCD第一行第12列显示WEEK
                LCALL        W_COM
                MOV                A,#57H                                                //字母'W'的字符库为01010111
                LCALL        W_DAT
                MOV                A,#45H                                                //字母'E'的字符库为01000101
                LCALL        W_DAT
                MOV                A,#45H                                                
                LCALL        W_DAT
                MOV                A,#4BH                                                //字母'K’的字符库为01001011
                LCALL        W_DAT
                MOV                A,#0C0H                                                //第二行第一列显示TIME
                LCALL        W_COM
                MOV                A,#54H                                                //字母'T'的字符库为01010100
                LCALL        W_DAT
                MOV                A,#49H                                                //字母'I'的字符库为01001001
                LCALL        W_DAT
                MOV                A,#4DH                                                //字母'M'的字符库为01001101
                LCALL        W_DAT
                MOV                A,#45H                                                //字母'E'的字符库为01000101
                LCALL        W_DAT
               
        

                 MOV                60H,#00H                                        //设置秒存储单元
                MOV                61H,#00H                                        //设置分存储单元
                MOV                62H,#16H                                        //设置时存储单元
                MOV                63H,#05H                                        //设置日存储单元
                MOV                64H,#01H                                        //设置月存储单元
                MOV                65H,#03H                                        //设置星期存储单元
                MOV                66H,#18H                                        //设置年存储单元
                LCALL        SET1302                                                //向DS1302写入时间

REP:          LCALL        GET1302                                                //读出时间
            LCALL        GET_TEM                                                  //读出转换后的温度值
                  LCALL        TEM_COV

;;;;;;;;;;在LCD第一行显示年月日和星期;;;;;;;;;;                        
                 MOV            A,#80H                                                 //显示在LCD第一行第一列
                   LCALL        W_COM                                                 //调用LCD写命令子程序
                MOV            A,#'2'
                 ACALL        W_DAT                                                 //调用LCD写数据子程序
                 MOV            A,#'0'
                 ACALL        W_DAT
                 MOV            A,56H                                                //年拆分成十位与个位,转换字符显示
                 MOV            B,#10H
                 DIV            AB
                 ADD            A,#30H                                                 //数字的字符库从00110000B即30H开始
                 ACALL        W_DAT
                 MOV           A,B
                 ADD            A,#30H
                 ACALL        W_DAT
                 MOV            A,#'-'
                 ACALL        W_DAT
                 MOV            A,54H                                                  //月拆分成十位与个位,转换字符显示
                 MOV            B,#10H
                 DIV            AB
                 ADD            A,#30H
                 ACALL        W_DAT
                 MOV            A,B
                 ADD            A,#30H
                 ACALL        W_DAT
                 MOV            A,#'-'
                 ACALL        W_DAT
                 MOV            A,53H                                                //日拆分成十位与个位,转换字符显示
                 MOV            B,#10H
                 DIV            AB
                 ADD            A,#30H
                 ACALL        W_DAT
                 MOV            A,B
                 ADD            A,#30H
                 ACALL        W_DAT
                MOV          A,#8FH                                                //设置LCD显示星期的位置为第一行第十六列
                  LCALL        W_COM
                 MOV            A,55H                                                 //显示星期
                 ADD            A,#30H
                 LCALL        W_DAT

;;;;;;;;;;在LCD第二行显示时分秒和温度;;;;;;;;;;;;;
                MOV                A,#0C4H                                                //写入显示缓冲区的起始地址为第二行第五列开始
                   LCALL        W_COM
                   MOV            A,52H                                                  //小时拆分成十位与个位,转换字符显示
                 MOV            B,#10H
                 DIV            AB
                 ADD            A,#30H
                 LCALL        W_DAT
                 MOV            A,B
                 ADD            A,#30H
                   LCALL        W_DAT
                 MOV            A, #':'
                 LCALL        W_DAT
                 MOV            A,51H                                                  //分拆分成十位与个位,转换字符显示
                 MOV            B,#10H
                 DIV            AB
                 ADD            A,#30H
                 LCALL        W_DAT
                 MOV            A,B
                 ADD            A,#30H
                 LCALL        W_DAT
                 MOV            A, #':'
                  LCALL        W_DAT
                 MOV            A,50H                                                 //秒拆分成十位与个位,转换字符显示
                 MOV            B,#10H
                 DIV            AB
                 ADD            A,#30H
                 LCALL        W_DAT
                 MOV            A,B
                 ADD            A,#30H
                  LCALL        W_DAT
                  MOV                A,#0CDH                                                //温度显示在LCD第二行第十四列
                LCALL        W_COM
                  MOV                A,FLAG0                                                //显示温度正负号
                ACALL        W_DAT
                   MOV                A,TEM_NUM                                        //温度整数拆分成十位和个位显示
                MOV                B,#0AH                                       
                DIV                AB                                                        //商送给A,余数送给B
                ADD                A,#30H
                CJNE        A,#30H,REP1                                        //如果十位为0,则不显示
                MOV                A,#20H                                                //字符库中00100000B(20H)为空白
REP1:        ACALL        W_DAT                                                //调用LCD写数据子程序
                MOV                A,B                                                        //将求得的余数送给A
                ADD                A,#30H
                ACALL        W_DAT                                                //调用LCD写数据子程序
                LJMP           REP

/******************时间**************************/
;;;;;;;;累加器A写一字节到DS1302;;;;;;;;;;;;;
WE:                MOV                70H,#08H                                                //一个字节八位,移动八次
INB1:        MOV                A,B                                                                //将命令字送给A
                RRC                A                                                                //通过A移入进位标志位C
                MOV                B,A
                MOV                T_IO,C                                                        //移入到芯片内
                SETB        T_CLK
                CLR                T_CLK
                DJNZ        70H,INB1
                RET

;;;;;;;;读一字节到累加器A中;;;;;;;;;;;;;;;;;
READ:        MOV                70H,#08H                                                //一个字节八位,移动八次
OUTB1:        MOV                C,T_IO                                                        //从芯片内移动到进位标志位C
                RRC                A                                                                //通过C再移入累加器A中
                SETB        T_CLK
                CLR                T_CLK
                DJNZ        70H,OUTB1
                RET

;;;;;;;;;向DS1302写入时间子程序;;;;;;;;;;;;;;
SET1302:CLR          T_RST                                                           //RST引脚为低电平,数据传送终止
        CLR          T_CLK                                                        //清零时钟总线
                SETB         T_RST                                                        //RST引脚为高电平,逻辑控制有效
                MOV          B,#8EH                                                        //控制命令字(10001110-进行存取时间,写操作)
                LCALL          WE                                                                //调用写字节命令
                MOV            B,#00H                                                        //写操作前清写保护位W
                LCALL          WE
                SETB           T_CLK
                CLR            T_RST
        MOV            R0,#60H                                                 //秒 分 时  日 月 星期  年  数据存储在60-66H单元
            MOV            R7,#07H                                                        //共7个字节
        MOV            R1,#80H                                                        //写秒寄存器命令
S1:                CLR                T_RST
                CLR                T_CLK
                SETB        T_RST
                MOV                B,R1                                                        //写入写秒指令
                LCALL        WE
                MOV                A,@R0                                                        //将秒存储单元中的数值送给A
                MOV                B,A
                LCALL        WE
                INC                R0                                                                //R0加一,指向下一个写入的日历、时钟数据
                INC                R1                                                                //指向下一个时间寄存器
                INC                R1
                SETB        T_CLK
                CLR                T_RST
                DJNZ        R7,S1
                CLR                T_RST
                CLR                T_CLK
                SETB        T_RST
                MOV                B,#8EH                                                        //控制命令字(10001110-进行存取时间,写操作)
                LCALL        WE
                MOV                B,#80H                                                        //控制寄存器中WP置1
                LCALL        WE
                SETB        T_CLK
                CLR                T_RST                                                        //结束写过程
                RET

;;;;;;;;;;;;;;;读时间子程序;;;;;;;;;;;;;;;;;               
GET1302:MOV           R0,#50H
        MOV           R7,#7
        MOV           R1,#81H                                                 //读秒寄存器命令
G1:                CLR            T_RST
        CLR            T_CLK
        SETB           T_RST
        MOV            B,R1                                                          //写入读秒寄存器命令
        LCALL          WE                                                               
        LCALL          READ
        MOV            @R0,A                                                          //存入读出数据
        INC            R0                                                          //指向下一个存放日历、时钟的存储单元
        INC            R1                                                          //指向下一个日历、时钟寄存器
        INC            R1   
        SETB           T_CLK
        CLR            T_RST
        DJNZ           R7,G1                                                         //未读完,继续读下一个
        RET        
               
/********************温度************************/
;;;;;;;;;;;;;;DS18B20复位程序;;;;;;;;;;;;;;;;;
B20_INT:SETB        DQ                                                                 //将数据线置高电平“1”
                NOP                                                                                  //延时        
                NOP
                CLR                DQ                                                                //数据线拉到低电平“1”
                MOV                R7,#0CH                                                        //延时60*12=720US
INT_DEL:ACALL        DEL60US
                DJNZ        R7,INT_DEL
                SETB        DQ                                                                //数据线拉到高电平“1”
                ACALL        DEL60US                                                        //延时等待
                ACALL        DEL60US
                MOV                C,DQ                                                        //将数据线的状态送给C,判断初始化是否成功,是否产生一个低电平
                JC                ERROR                                                        //如果C等于1,则跳出,初始化失败
                ACALL        DEL60US                                                        //初始化成功,CPU读到数据线上的低电平,继续延时
                ACALL        DEL60US
                ACALL        DEL60US
                ACALL        DEL60US
                RET
ERROR:        CLR                DQ                                                                //初始化未成功,继续进行初始化
                SJMP        B20_INT
                RET

;;;;;;;;;;;;;;;;;读DS18B20一个字节到累加器A子程序;;;;;;;;;;;;
R_BYTE:        MOV                R7,#08H                                                        //读取8位为一字节
                SETB        DQ
                NOP
                NOP
LOOP:        CLR                DQ                                                                //将数据线从高电平拉为低电平时,作为一个读周期的开始
                NOP                                                                                //延时,保证低电平至少为1US
                NOP
                NOP
                SETB        DQ                                                               
                MOV                R6,#07H                                                        //循环到A的最高位
                DJNZ        R6,[        DISCUZ_CODE_1        ]nbsp;                                                         
                MOV                C,DQ                                                        //将数据线中的值送给进位标志位C
                ACALL        DEL60US
                RRC                A                                                                //累加器A带进位右移
                SETB        DQ
                DJNZ        R7,LOOP                                                        //将一字节读到累加器A
                ACALL        DEL60US
                ACALL        DEL60US
                RET
               
;;;;;;;;;;;;;累加器A写到DS18B20子程序;;;;;;;;;;
W_BYTE:        MOV                R7,#08H                                                         //将8位连续数据(一字节)写入A
                SETB        DQ                                                                //拉高数据线
                NOP
                NOP
LOOP1:        CLR                DQ                                                                //将数据线拉到低电平,作为写周期的开始
                MOV                R6,#07H                                                        //循环到累加器A的最高位Acc.7
                DJNZ        R6,$
                RRC                A                                                                //从累加器A的最高位开始写入
                MOV                DQ,C                                                        //将进位C送给DS18B20(写入时序,0或者1时序)
                ACALL        DEL60US                                                        //保持60US
                SETB        DQ                                                                //在15US内将数据线拉为高电平
                DJNZ        R7,LOOP1                                                //将一字节写入A
                RET
DEL60US:MOV                R6,#1EH                                                        //延时(30*2)us
                DJNZ        R6,$
                RET

;;;;;;;;;;;读温度子程序;;;;;;;;;;;;;;;;;;
GET_TEM:ACALL        B20_INT                                                        //DS18B20复位程序
                MOV                A,#0CCH                                                        //DS18B20跳过ROM命令
                ACALL        W_BYTE                                                        //调用写DS18B20子程序
                ACALL        DEL60US
                ACALL        DEL60US
                MOV                A,#44H                                                        //DS18B20温度转换命令,开始装换温度
                ACALL        W_BYTE                                                        //调用写DS18B20子程序
                ACALL        DEL60US
                ACALL        B20_INT                                                        //写完之后,将DS18B20复位
                MOV                A,#0CCH                                                        //DS18B20跳过ROM命令
                ACALL        W_BYTE                                                        //调用写DS18B20子程序
                ACALL        DEL60US
                MOV                A,#0BEH                                                        //DS18B20读暂存器命令
                ACALL        W_BYTE                                                        //调用写DS18B20子程序
                ACALL        DEL60US
                ACALL        R_BYTE                                                        //读温度低字节
                MOV                TEM_L,A                                                        //将读出的温度低字节保存在40H
                   ACALL        R_BYTE                                                        //读温度高字节
                MOV                TEM_H,A                                                        // 将读出的温度高字节保存在41H
                RET

;;;;;将从DS18B20中读出的温度转换成整数显示;;;;;;;;;;;;
TEM_COV:MOV                FLAG0,#'+'                                                //设置当前温度为正,并且存放在45H
                MOV                A,TEM_H                                                        //将读取的温度高字节送给A
                SUBB        A,#0F8H                                                        //判断C的值是否为1,为1则为正,为0则为负
                JC                TEM0                                                        //看温度值是否为负,不是(C=1),转
                MOV                FLAG0,#'-'                                                //是,置FLAG0为负
                MOV                A,TEM_L                                                        //将读取的温度低字节送给A
                CPL                A                                                                //求此时负值温度的补码
                ADD                A,#01H
                MOV                TEM_L,A                                                        //将求得的补码存放在40H
                MOV                A,TEM_H                                                         //将读取的温度高字节送给A
                CPL                A
                ADDC        A,#01H
                MOV                TEM_H,A                                                        //在将其补码放在41H
TEM0:        MOV                A,TEM_L                                                        //存放整数部分到TEMPER_NUM
                ANL                A,#0F0H                                                        //取出温度低字节的高四位
                SWAP        A                                                                //将取出的高四位存放在A中低四位位置
                MOV                TEM_NUM,A                                                //将其存放在42H
                MOV                A,TEM_H
                SWAP        A
                ORL                A,TEM_NUM
                MOV                TEM_NUM,A
                RET

/***************LCD显示*******************/
;;;;;;LCD初始化子程序;;;;;;;;;;;;
LCD_INT:MOV                A,#00000001H                                        //清屏
                ACALL        W_COM                                                        //调用读命令子程序
                MOV                A,#00111000B                                        //传输8位数据,显示两行,使用5*7的字符
                LCALL        W_COM
                MOV                A,#00001100B                                        //显示器开,光标关,字符不闪烁
                LCALL        W_COM
                MOV                A,#00000110B                                        //字符不动,光标自动右移一格
                LCALL        W_COM
                RET
;;;;;写入命令子程序(RS=0,RW=0);;;;;;
W_COM:        ACALL        F_BUSY
                CLR                E
                CLR                RS
                CLR                RW
                SETB        E
                MOV                P0,A
                CLR                E
                RET
;;;;;写入数据子程序(RS=1,RW=0);;;;;
W_DAT:        ACALL        F_BUSY
                CLR                E
                SETB        RS                                                   
                CLR                RW
                SETB        E
                MOV                P0,A
                CLR                E
                RET

;;;;;查忙子程序;;;;;;;;;;;;;
F_BUSY:        PUSH        ACC
                MOV                P0,#0FFH
                CLR                RS                                                                //忙标志
                SETB        RW                                                
WAIT:        CLR                E                                                                //给使能端有效信号(下降沿触发)
                SETB        E
                JB                P0.7,WAIT                                                //直接寻址位P0.7是否为1,为1则忙,继续等待
                POP                ACC
                RET
                END                                                
                                                        
回复

使用道具 举报

9#
ID:822775 发表于 2021-10-11 18:32 | 只看该作者
温度显示,是不是用到温度传感器,那个12864跟1602有什么区别
回复

使用道具 举报

10#
ID:944118 发表于 2022-6-10 18:14 | 只看该作者
仿真图画不对啊,求个仿真图兄弟
回复

使用道具 举报

11#
ID:959705 发表于 2023-3-7 17:13 | 只看该作者
温度测不出来有点问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表