首页 HD44780液晶控制器显示系统设计.doc

HD44780液晶控制器显示系统设计.doc

举报
开通vip

HD44780液晶控制器显示系统设计.docHD44780液晶控制器显示系统设计.doc 第3章 HD44780液晶控制器显示系统设计 89 第3章 HD44780液晶控制器显示 系统设计 在电子系统设计中,离不开显示,液晶显示器(LCD)的应用更是越来越广泛。目前主要有两种类型的液晶显示器,一种是“Alphanumaric LCDs”,只能显示字符和数字;另一种是“Graphical LCDs”,既能显示字符和数字,还能显示汉字和图形。液晶显示器是由液晶点阵及控制器两部分组成的,不同的液晶显示器所对应的控制器不尽相同。 本章详细介绍字符液晶显示器的工...

HD44780液晶控制器显示系统设计.doc
HD44780液晶控制器显示系统设计.doc 第3章 HD44780液晶控制器显示系统设计 89 第3章 HD44780液晶控制器显示 系统设计 在电子系统设计中,离不开显示,液晶显示器(LCD)的应用更是越来越广泛。目前主要有两种类型的液晶显示器,一种是“Alphanumaric LCDs”,只能显示字符和数字;另一种是“Graphical LCDs”,既能显示字符和数字,还能显示汉字和图形。液晶显示器是由液晶点阵及控制器两部分组成的,不同的液晶显示器所对应的控制器不尽相同。 本章详细介绍字符液晶显示器的工作原理和应用实例。通常,控制器和液晶屏制作在一起,也有的是分开的。液晶屏是一种物理器件,而我们研究的控制对象是电器件,即液晶显示控制器。所以,弄清液晶显示控制器的工作原理是应用液晶显示器必须的第一个步骤。 3.1 HD44780的工作原理 HD44780是一种点阵液晶显示控制器,用来控制字符液晶显示器,目前应用比较广泛。它有以下特点: , 内置CGROM字符发生器,含192个固定字符,可供用户显示调用。 , 内置CGRAM字符发生器,用户通过编程设计最多8个自定义字符,存放其中,供显示调用。 , 内置DDRAM显示数据存储器,可以存放最多80个显示字符。把CGROM或CGRAM中的显示数据调入DDRAM,便可在显示屏上显示。DDRAM中的单元和显示屏的位置存在一一对应关系。 , 自动复位上电功能。 , 双向8位或4位总线接口。 , 丰富的控制指令:清显存、光标位置设置、数据输入时光标或数据移位设置、开或关显示屏等。 下面详细介绍HD44780的各项功能。 Proteus显示控制系统设计与实例 90 3.1.1 初始化 HD44780模块有两个寄存器,一个用来输入指令,另一个用来读写数据。指令用来告诉模块怎样存放或哪里存放数据。如果模块上电时,上升沿时间满足图3-1所示的要求,则模块缺省执行内置的上电初始化程序如下: , 清显存 , 功能设置(DL=1,8位接口;N=0,单行显示;F=0,5×7点阵字体) , 显示开关控制(D=0,关闭显示;C=0,关闭光标;B=0,字符闪烁关闭) , 输入方式设置(I/D=1,设DDRAM计数器为自动加1方式) , DDRAM被选择 注:括号中的内容见表3-2。 图3-1 内部初始化的供电时序需求 上电之后,显示器将会忙大约15ms用以模块内部初始化。 如果上电时,上升沿时间t不能满足图3-1的要求,或系统有不同于缺省设rcc 置的参数需求(如显示屏需双行显示等),则初始化程序必须从主机(比如单片机)发出。推荐初始化指令如下: , 单行显示,5×7点阵字体 30H,30H,06H,0EH,01H(十六进制) , 单行显示,5×10点阵字体 34H,34H,06H,0EH,01H(十六进制) , 双行显示,5×7点阵字体 38H,38H,06H,0EH,01H(十六进制) 具体应用时程序如下: INIT_LCD1:(初始化子程序) MOV A,#3CH ;送初始化指令到累加器,8位接口,双行显示,5×10字体 CALL WCOM ;调指令写入子程序 MOV A,#0EH ;送初始化指令到累加器,开显示,开光标,关字符闪烁 CALL WCOM ;调指令写入子程序 MOV A,#06H ;DDRAM计数器自动加1,数据输入时显示不移位 CALL WCOM ;调指令写入子程序 MOV A,#01H ;清显示,光标返回显示屏左上角 第3章 HD44780液晶控制器显示系统设计 91 CALL WCOM ;调指令写入子程序 RET ;返回 为了确保初始化程序的执行,在调用初始化程序后,应调用一个15ms延时子程序。15ms的延时子程序提供如下,供读者参考: MOV R5,#10 CALL DELAY DELAY: MOV R6,#50 D1: MOV R7,#100 DJNZ R7,$ DJNZ R6,D1 DJNZ R5,DELAY RET 3.1.2 四位总线操作 HD44780模块的数据线D0~D7与主机接口可以选择8位或4位两种方式,在初化化时指定。4位总操作方式使用D4~D7,D0~D3悬空。8位十六进制代码或显示数据分两次传送,一次四位,高四位先传送。四位总线操作方式编程时比8位稍稍复杂些,但可以节省主机资源。模块初始化时,按以下指令操作: 双行显示,5×7点阵字体: 28H,28H,06H,0EH,01H(十六进制) 3.1.3 显示存储器地址 HD44780模块的显示RAM共可存放80个字符。如果显示内容少于80个字符,显示屏上要显示的内容与显示RAM之间是一对一的映射关系,显示内容取决于输入模式设置指令。 HD44780支持以下几种字符液晶显示屏: , 单行或双行16字符显示 , 四行16或20字符显示 , 四行40字符显示 HD44780的显示存储器采用固定地址分配 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 ,即控制不同的液晶显示屏,采用不同的显存地址,而且显存地址不能由用户来改变。 下面以常用的字符液晶显示器1602C为例,来说明HD44780的显存地址分配。 表3-1是HD44780的一个四行16个字符的液晶显示屏所对应的的显存地址图。 Proteus显示控制系统设计与实例 92 表3-1 HD44780 4×16显示屏DDRAM地址分配一览表 8F 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E CF C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE 9F 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF 从表中可以看出,要想把一个字符显示在液晶屏的某个位置,只需要把该字符的显示代码送到该地址所指向的DDRAM中去即可。比如,要把某个字符显示在屏幕的左上角位置,则把该字符的显示数据送到80H中去即可。 对于1602C来说,它是一个两行16字符的液晶显示器,显存地址的分配应该对应表3-1的前两行。即第一行的16个字符显示位置分别对应于DDRAM的80H~8FH,第二行的16个字符显示位置分别对应于DDRAM的C0H~CFH。显示一个字符时,应该先由主机通过8位或4位接口把显存地址以命令方式送出,再由主机通过8位或4位接口把显示字符代码以数据方式送出。 3.1.4 指令表 HD44780模块有11条专用控制指令。认识各条指令的功能及用法,是使用液晶控制器HD44780的关健。 表3-2是HD44780控制指令一览表。 表3-2 HD44780控制指令一览表 指令 RS R/W D7 D6 D5 D4 D3 D2 D1 D0 描述 清显示 0 0 0 0 0 0 0 0 0 1 清显示,光标回起始位 回原位 0 0 0 0 0 0 0 0 1 * 光标返回起始位,不清显示 输入方式设0 0 0 0 0 0 0 1 I/D S 设置DDRAM计数器为增量或置 减量(I/D),在数据读写期间 指定光标或显示移位(S) 显示开/关0 0 0 0 0 0 1 D C B 设置显示开/关(D),光标开/控制 关(C),光标位置字符闪烁(B) 光标或显示0 0 0 0 0 1 S/C R/L * * 移动光标或显示移位,不改变移位 DDRAM内容 功能设置 0 0 0 0 1 DL N F * * 设置数据总线位数(DL),显 示行数(N),字体大小(F) 设置CGRAM0 0 0 1 CGRAM地址A 设置CGRAM地址,在这条指令CG 地址 之后发送和接收CGRAM数据 第3章 HD44780液晶控制器显示系统设计 93 设置DDRAM地址,在这条指令设置DDRAM0 0 1 DDRAM地址ADD 之后发送和接收DDRAM数据 地址 读忙标志和0 1 BF 地址计数器AC 读忙标志位(BF)和地址计数地址 器内容 写数据 1 0 写数据 写数据到DDRAM或CGRAM,地 址计数器自动加1或减(1AC) 读数据 1 1 读数据 读数据从DDRAM或CGRAM,地 址计数器自动加1或减(1AC) I/D=1:自动加1 I/D=0:自动减1 S=1:数据输入时显示移位 S=0:数据输入时光标移位 S/C=1:显示移位,RAM不变 S/C=0:光标移位,RAM不变 R/L=1:向右移位 R/L=0:向左移位 DL=1:8位 DL=0:4位 N=1: 2 行 N=0: 1 行 F=1: 5×10 点阵字体 F=0: 5×7 点阵字体 D=1: 开显示 D=0: 关显示 C=1: 开光标 C=0: 关光标 B=1: 开闪烁 B=0: 关闪烁 BF=1:不能接受指令 BF=0:可以接受指令 *:取0或1都可以 3.1.5 读写时序 HD44780模块的读操作主要完成主机从模块内读取状态字或读取显示数据。只有主机判断HD44780处于不忙状态才能发送其它指令,如果主机与模块匹配较好或模块运行速度快时,也可以不进行判忙操作。写操作主要完成主机向HD44780进行指令传送或显示数据传送。读写操作一定要按照HD44780内部的读写时序才能正常进行。图3-2是HD44780的写操作时序。 2.2VRS0.6V RW脉宽 EN EN周期EN 图3-2 HD44780的写操作时序图 D0~D7 Proteus显示控制系统设计与实例 94 图中,EN是模块HD44780的使能端,必须给一个周期的脉冲信号才能有效,不能为固定的高电平。EN为高电平的宽度不少于450ns,程序实现上,可以调用一个周期为1000ns、占空比为50%的脉冲子程序产生程序,也可以用SETB和CLR指令搭配来完成。RS为命令或数据选择端,当RS=0时,总线上传送的是命令;当RS=1时,总线上传送的是数据。RW为读/写选择端,当RW=0时,为写操作;当RW=1时,为读操作。D0~D7为总线数据,可以传送命令,也可以传送数据,由RS来控制。 HD44780的读操作时序可以参考写操作时序,区别在于读操作时RW=1。 通常,在程序设计时,按照以上时序编写读操作和写操作子程序。当需要写入命令或数据时,只需调用相应子程序即可。下面是写操作子程序的例子,请读者认真 分析 定性数据统计分析pdf销售业绩分析模板建筑结构震害分析销售进度分析表京东商城竞争战略分析 并牵记,在本章的实例中要频繁使用。 WCOM: ;写命令子程序 MOV P0,A ;A中存放命令字 CLR RS ;RS=0,说明总线P0上传送的为命令 CLR WWR ;R/W=0,为写操作 CALL EN1 ;调使能脉冲产生子程序 RET WDATA: ;写数据子程 MOV P0,A SETB RS ;RS=1,说明总线P0上传送的为数据 CLR WWR CALL EN1 RET EN1: ;使能脉冲产生子程序 SETB EN ;E=1 CALL DE ;延时 CLR EN ;E=0 CALL DE ;延时 RET DE: MOV R7,#5 ;延时子程序 DJNZ R7,$ RET 3.1.6 CGROM HD44780模块的CGROM中存放的字符以及字符的显示代码如表3-3所示。用户只能选择192个字符中的字符来显示,另外可以通过编程自定义8个字符来显示。 第3章 HD44780液晶控制器显示系统设计 95 在表3-3中,有两种字体,一种是5×7点阵字体,其实是8×8点阵字体,左右留3列,下方留一行;另一种是5×10点阵字体,每个字实际占用8×16点阵。 表3-3 HD44780 CGROM字符一览表 显示数据按照表中的行、列坐标可以查出。高四位是列坐标,低四位是行坐标。比如第一行第二列的空格字符,即不显示任何字符,它的显示数据为00100000,即 Proteus显示控制系统设计与实例 96 20H;第二行第四列的大写A,它的显示数据为01000001,即41H。通常,在显示固定字符时,不采用查表方式,而是在程序中以数据块中存放字符串的形式来表示比较方便。 3.2 HD44780的综合应用实例 上一节已经介绍了HD44780的基本功能,本节给出一个控制器为HD44780的字符液晶显示器综合应用设计实例,目的在于使读者对HD44780的功能有一个全面和综合的了解与掌握,以便更好地理解后两节的内容。 设计任务: 在Proteus中设计一个由单片机AT89C51控制的字符液晶显示器LM016L显示电路,能够完成以下功能: (1)把程序中存放的两个数据块中的字符分别显示在LM016L的第一行和第二行。显示数据块为: DB“AT89C15-LM016L” DB“Zhu Qinghui Test” (2)自定义一个特殊字符“”,写入LCD的CGRAM,并取出该字符使之显示在LM016L的首行第16列。 3.2.1 系统硬件设计 LM016L是Proteus ISIS中的一个2行16列字符液晶显示器件,相当于实际器件1602C,它的控制器是HD44780。在第1章中,我们已经知道了LM016L在Proteus中存放的位置和如何取出该元件。下面直接给出系统电路原理图,如图3-3所示。 单片机与液晶显示器之间的接口方式有两种,直接访问方式和间接控制方式。直接访问方式是将液晶显示器直接挂在单片机的总线上,单片机将其作为存储器的一部分或I/O设备来实施控制。即把单片机的P2口接液晶显示器的控制端,P0口接液晶显示器的数据端。对于单片机来说,P2口是对外访问液晶显示器的地址高八位,P0口为低八位,同时P0口又是数据口。具体接法见第4章中的实例。间接控制方式是将液晶显示器与单片机的某个并行接口连接,单片机通过对该接口的操作实现对液晶显示器的控制。在间接控制方式下,液晶显示器需要一个8位并行接口作为数据总线;另外3位并行接口作为控制线RS、R/W、E。 在图3-3中,采用了间接控制方式,这种接线方式和编程方法易于被初学单片机的读者理解。单片机的P0口接LCD的数据口D0,D7,P2.0,P2.1分别接LCD的控制端RS、R/W和W。1kΩ的排阻是必需的,作为P0口的上拉电阻以增加P0 第3章 HD44780液晶控制器显示系统设计 97 口的驱动能力。如果去掉上拉电阻,LM016L将不显示。D0,D7既传送命令,又传送数据。当传送命令时,应同时使RS为0;当传送数据时,应同时使用RS为1。R/W是读写控制端,当R/W=0时,由单片机向LM016L发送命令或数据;当R/W=1时,由单片机从LM016L读取命令或数据。E为LM016L工作的使能端,前面已经1VSS2VDD介绍,不变的高电平或低电平不能使LM016L工作,必须由单片机在合适的时候给3VEE4RS5出一个周期约为1000ns、占空比为50%的脉冲。 RW6ELCD1LM016L7D08D19D210D311D4129D5138D614RP17D71K65432 1U11939XTAL1P0.0/AD038P0.1/AD137P0.2/AD21836XTAL2P0.3/AD335P0.4/AD434P0.5/AD533P0.6/AD6932RSTP0.7/AD721P2.0/A822P2.1/A923P2.2/A102924PSENP2.3/A113025ALEP2.4/A123126EAP2.5/A1327P2.6/A1428P2.7/A15110P1.0P3.0/RXD211P1.1P3.1/TXD312P1.2P3.2/INT0413P1.3P3.3/INT1514P1.4P3.4/T0615P1.5P3.5/T1716P1.6P3.6/WR817P1.7P3.7/RDAT89C51 图3-3 系统电路原理图 3.2.2 系统软件设计 系统软件设计采用模块化编程,由主程序调用各个子程序模块,子程序之间又互相嵌套。模块化编程增加了程序的可读性,初学者可以套用这些模块来轻松完成对LCD显示屏的控制。软件设计包含了对LM016L核心控制的所有环节,具有典型控制意义。 1. 主程序设计 系统主程序设计流程如图3-4所示,主要完成LCD初始化、DB块显示内容、以及对CGRAM的读、写。LM016L上电后15ms内进行内部初始化,此时不能完成对部分命令的操作,所以在主程序中初始化后调用了一个延时子程序,以等待初始化的完成。LM016L的初始化程序如下: MOV A,#3CH ;设LCD为两行显示,字体5×7,8线输入方式 CALL WCOM ;调用写命令子程序 Proteus显示控制系统设计与实例 98 MOV A,#0EH ;设置光标显示方式 CALL WCOM MOV A,#06H ;设置显示存储器地址计数器为自动加1方式 CALL WCOM MOV A,#01H ;清显示屏并使光标位于LCD首行首列 CALL WCOM 宏指令 清使能端 LCD初始化 调延时子程序 赋首行DB块地址?DPTR A?1 调显示子程序 赋次行DB块地址?DPTR A?2 调显示子程序 调写CGRAM子程序 调读CGRAM子程序图3-4 主程序流程图 等待 在主程序流程图中,判断累加器A中的数据为1时,把第一个DB块中的字符 DB块内容显示在LM016L的第一行,否则把第二个DB块中的字符显示在LM016L的第二行。显示完DB块内容后,向CGRAM中写入用户自义字符,并把该字符显示在LCD首结 束 行末位。 2. 子程序设计 子程序模块设计的主要内容有显示子程序、写命令子程序、写数据子程序、使能脉冲产生子程序、延时子程序、写CGARM子程序和读CGRAM子程序。 显示子程序流程图如图3-5(a)所示。首先判断累加器的内容是否为1,如果为1,把LM016L的DDRAM首行首列地址80H送入累加器A中,调命令写入子程序,把DDRAM的首地址80H通过AT89C51的P0口送给LM016L。如果累加器中的内容不为1,则把LM016L的DDRAM第二行首地址0C0H送入累加器A中,调命令 第3章 HD44780液晶控制器显示系统设计 99 写入子程序,把0C0H通过AT89C51的P0口送给LM016L。即先指定显示数据应显示的位置,然后调用显示数据写入子程序,把DB块内容逐字符送出。 显示地址?P0A=1YN RS?0A?#80HA?#0C0H 清WR写有效 调使能脉冲子程序调命令写入子程序 返 回 调数据写入子程序 返 回 (a)显示子程序 (b)写命令子程序 EN?1显示数据?P0 延时RS?1 EN?0清WR写有效 延时调使能脉冲子程序 返 回 返 回 (c)写数据子程序 (d)使能脉冲子程序 图3-5 子程序流程图 写命令子程序模块完成一个命令由单片机写入LCD,本设计主要用来完成LCD显示地址的写入。先把显示地址送入P0,再设RS=0、WR=0,即置LM016L为写命令状态,最后调用使能脉冲产生子程序,即把指定的显示地址送给了LM016L。流程图如图3-5(b)所示。 写数据子程序流程图如图3-5(c)所示。写数据和写命令子程序结构相似,不同的是写数据子程序中送给P0口的是显示数据(字符或数字),LM016L的状态设为RS=1、WR=0。 使能脉冲产生子程序流程图如图3-5(d)所示,主程序中已经对E清零了,所以子程序中置E为1,延时500ns,然后清E,再延时500ns,产生一个占空比为50%的使能脉冲信号。每次写命令或写数据时,必然调用该子程序才能完成相应的功能。 两个延时子程序,一个在主程序中调用,完成LM016L的初始化延时,时间要在15ms以上。另一个在使能脉冲子程序中调用,时间要求大于450ns。流程图略。 3. CGRAM的读写实现 如果想显示一个特殊的、CGROM中不存在的字符,可以向CGRAM中写入自 Proteus显示控制系统设计与实例 100 定义字符,然后再调入DDRAM即可显示。CGRAM共64字节,可存入用户自定义的5×7特殊字符8个或5×10特殊字符4个。CGRAM地址为40H~7FH。40H~47H存放用户的第一个5×7字符,依次类推。而40H中存放自定义字符的第一行编码,47H中存放该字符的第八行编码。如自定义字符“”,5×7(宽×高),可以分8行向CGRAM中写入数据。每行写入一个字节,高3位不用,设为000。LCD中对应显示的点为1,不显示的点为0,则40H~47H中应分别写入的编码为: 0 0 1 0 0B (04H) 0 1 0 1 0B (0AH) 1 0 0 0 1B (11H) 0 1 0 1 0B (0AH) 0 0 1 0 0B (04H) 0 1 0 1 0B (0AH) 0 0 1 0 0B (04H) 0 0 0 0 0B (00H) 从数据的排列可以看出该字符的形状。写CGRAM的具体程序如下: MOV A,#40H ;设CGRAM首字符首行地址 CALL WCOM ;调命令写入子程序 SETB RS ;设RS为1 MOV A,#04H ;字符首行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#0AH ;字符第二行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#11H ;字符第三行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#0AH ;字符第四行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#04H ;字符第五行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#0AH ;字符第六行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#04H ;字符第七行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#00H ;字符第八行编码值送累加器 CALL WDATA ;调数据写入子程序 由于LCD初始化时已设CGRAM地址指针为自动加1方式,所以只需设 第3章 HD44780液晶控制器显示系统设计 101 CGRAM的首行地址,以后顺序写入编码即可。因为是5×7字符,所以写入最后一行47H中的是#00H,即不显示任何点。 上述自定义字符分别存入了CGRAM中的40H~47H中,读者还可以再自定义7个字符,应分别存入CGRAM中的48H~4FH、50H~57H、58H~5FH、60H~67H、68H~6FH、70H~77H、78H~7FH中。只要模仿上段程序,先指定CGRAM首地址,顺序写入即可。 以上只是完成了字符的创建和存储任务,如果想把自定义字符显示在LCD上,还需要再编一小段程序才能实现。HD44780内部已定义好,CGRAM中40H~47H、48H~4FH、50H~57H、58H~5FH、60H~67H、68H~6FH、70H~77H、78H~7FH存入的自定义字符无论是什么,这八个字符对应的显示代码分别为00H、01H、02H、03H、04H、05H、06、07H。在上段程序中,因为把CGRAM的首地址设成了40H,所以只要把显示代码00H写入DDRAM的8FH中,上述自定义的符号“”就会显示在LM016L的右上角位置。读CGRAM或显示自定义字符子程序的流程图如图3-6所示。 WR?1 RS?0 调使能脉冲子程序 A?P0 Y 读忙标志位=1 N P0?#00H RS=1 调使能脉冲子程序 图3-6 读CGRAM子程序 A?P0 在程序中用以下语句实现: 返 回MOV A, #00H ;把自定义自符显示代码送累加器A MOV B, #15 ;设置显示位置为第"1"行的第16列 CALL LCDP1 ;调第一行显示子程序LCDP1 在子程序LCDP1中,执行80H+15,即把第一行DDRAM首地址加15,计算出第一行第16列的DDRAM地址,然后再把自定义符号的显示代码写入该显示单元。 4. 源程序(汇编语言) Proteus显示控制系统设计与实例 102 RS EQU P2.0 ;定义命令/数据选择端为P2.0 EN EQU P2.1 ;定义使能端为P2.1 WWR EQU P2.2 ;定义数据读写端为P2.2 ORG 0H JMP BEGIN BEGIN: CLR EN ;使能端先为低,液晶显示禁止 CALL SET_LCD ;调显示子程序SET_LCD CALL WCCGRAM ;调向CCRAM中写入自定义字符子程序 MOV A, #00H ;把WCCRAM子程序中定义的自定义自符送累加器A MOV B, #15 ;设置显示位置为第"1"行的第16列 CALL LCDP1 ;调第一行显示子程序LCDP1 JMP $ ;无限循环 SET_LCD: ;SET_LCD子程序 CLR EN ;清使能端 CALL INIT_LCD1 ;调显示屏初始化子程序INIT_LCD1 MOV R5,#10 ;R5设为10 CALL DELAY ;延时,LCD初始化15ms MOV DPTR,#LMESS1 ;把要显示的子符串1的地址给数据指针 MOV A,#1 ;把行号"1"送给累加器A CALL LCD_PRINT ;调显示输出子程序LCD_PRINT MOV DPTR,#LMESS2 ;把要显示的子符串2的地址给数据指针 MOV A,#2 ;把行号"2"送给累加器A CALL LCD_PRINT ;调显示输出子程序LCD_PRINT RET ;返回 INIT_LCD1: ;液晶显示初始化子程序 MOV A,#3CH ;8位I/O口初始化 CALL WCOM ;调写命令子程序WCOM MOV A,#0EH ;双列显示,字型使用5*7点阵 CALL WCOM ;调写命令子程序WCOM MOV A,#04H ;光标每次向右移一位,显示屏不移动 第3章 HD44780液晶控制器显示系统设计 103 CALL WCOM ;调写命令子程序WCOM MOV A,#01H ;清楚LCD显示屏 CALL WCOM ;调写命令子程序WCOM RET ;返回 LCD_PRINT: ;显示输出子程序LCD_PRINT CJNE A,#1,LINE2 ;如果A?1,执行LINE2子程序 LINE1: MOV A,#80H ;如果A=1,送液晶显示第一行的显示地址给A CALL WCOM ;调写命令子程序 JMP FILL ;调逐字符写入子程序FILL LINE2: MOV A,#0C0H ;送液晶显示第二行的显示地址给A CALL WCOM ;调写命令子程序 FILL: CLR A ;A清零 MOVC A, @A+DPTR ;把第字符串的首字符送出 CJNE A,#0,L1 ;判断A是否等0,即字符串结束否,不等0转L1 RET ;返回 L1: CALL WDATA ;字符串逐个送出子程序L1,调写数据子程序WDATA INC DPTR ;数据指针加1 JMP FILL ;调逐字符写入子程序FILL RET ;返回 EN1: ;使能信号子程序 SETB EN ;令使能端EN为高 CALL DELAY1 ;调延时子程序DELAY1 CLR EN ;令使能端EN为低 CALL DELAY1 ;调延时子程序DELAY1 RET ;返回 DELAY1: ;延时子程序DELAY1 MOV R7,#5 DJNZ R7,$ RET WCOM: ;写命令子程序 MOV P0,A ;把已经送给A的命令再送到P0口 Proteus显示控制系统设计与实例 104 CLR RS ;清RS,写命令条件之一 CLR WWR ;清WR,写命令另外一个条件 CALL EN1 ;调使能脉冲子程序EN1 RET ;返回 WDATA: ;写数据子程序WDATA MOV P0,A ;把已经送给A的显示数据送到P0口 SETB RS ;设RS为1,写数据条件之一 CLR WWR ;设WR为0,写数据的另外一个条件 CALL EN1 ;调使能脉冲子程序EN1 RET ;返回 DELAY: ;延时子程序DELAY MOV R6,#50 D1: MOV R7,#100 DJNZ R7,$ DJNZ R6,D1 DJNZ R5,DELAY RET LMESS1:DB "AT89C51-LM016L",0 ;显示在第一行的子符串,0为结束标志 LMESS2:DB "Zhu Qinghui Test",0 ;显示在第二行的子符串,0为结束标志 LCDP1: ;在第一行某列显示字符的子程序 PUSH ACC ;把累加器A中的内容压入堆栈 MOV A,B ;把B中的内容"15"送给A ADD A,#80H ;把液晶显示的首行地址加上"15"送入A,得首行末地址 CALL WCOM ;调命令写入子程序WCOM POP ACC ;弹出堆栈内容到A中 CALL WDATA ;调显示数据写入子程序WDATA RET ;返回 LCDP2: ;在第二行第某列显示字符的子程序 PUSH ACC ;把累加器A中的内容压入堆栈 MOV A,B ;把B中的内容"15"送给A ADD A,#0C0H ;把液晶显示的第二行地址加上"15"送入A,得第二行末地址 CALL WCOM ;调命令写入子程序WCOM 第3章 HD44780液晶控制器显示系统设计 105 POP ACC ;弹出堆栈内容到A中 CALL WDATA ;调显示数据写入子程序WDATA RET ;返回 WCCGRAM: ;写CGRAM子程序 MOV A,#40H ;设CGRAM首字符首行地址 CALL WCOM ;调命令写入子程序 SETB RS ;设RS为1 MOV A,#04H ;字符首行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#0AH ;字符第二行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#11H ;字符第三行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#0AH ;字符第四行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#04H ;字符第五行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#0AH ;字符第六行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#04H ;字符第七行编码值送累加器 CALL WDATA ;调数据写入子程序 MOV A,#00H ;字符第八行编码值送累加器 CALL WDATA ;调数据写入子程序 RET ;返回 END ;程序结束 3.2.3 Proteus仿真 1. 软件编写环境及调试 Proteus ISIS支持外部程序编辑器如Keil、IDE等,即可以在这些编辑器中进行 单片机程序编辑及调试,然后编译成“*.hex”文件。在Proteus ISIS 中双击单片机 元件AT89C51,出现编辑元件对话框,在“Program File”一项中选择已经编译好的 16进制程序文件“LM016L.hex”,点击“OK”,程序即虚拟下载到了单片机AT89C51 中。 Proteus显示控制系统设计与实例 106 Proteus ISIS自带有源程序编辑、编译及调试器。在主菜单“Source”通过适当的设置可以打开源程序编辑器“Source Editor”,如图3-7所示,比使用外部编辑器比更加方便,并且可以和硬件进行联调,当程序下载到单片机后,运行仿真,出现问题后可即时打开“Source Editor”,修改、编译、重新下载并仿真。 图3-7 Proteus ISIS自带的源程序编辑器 2. 交互仿真结果 程序下载到AT89C51后,选择Proteus ISIS 的仿真运行控制按钮“”中的“Play”键即可进行系统软、硬件的交互仿真。本设计的仿真结果如图3-8所示。可以看到,我们在设计中把自定义的特殊符号“”显示在了LM016L的首行最后一列上。 图3-8 系统在Proteus ISIS中的仿真结果 通过仿真结果可见,成功实现了原设计目的,如果要改变显示信息,只需改变主程序中的显示数据块内容或向CGRAM写入新的自定义字符。另外,LM016L的光标显示方式多样化,通过LCD初始化程序设置,可变换出不同的显示方式。 3.3 基于LM016L和DS1302的实时时钟设计 通过上一节的实例,我们对HD44780的控制方式已经有了全面的了解和掌握,这一节,我们使用LM016L结合实时时钟芯片DS1302,在Proteus中设计一个实时 第3章 HD44780液晶控制器显示系统设计 107 时钟,能够完成以下功能: (1)当开关未合上时,LM016L分两行分别显示以下内容: 第一行:“DS1302 RealClock”,第二行:“Please Select!” (2)当开关闭合时,LM016L分两行分别显示以下内容: 第一行:“Time: **-**-**”,第二行:“Date: **-**-** *” 第一行的“**-**-**”分别代表实时时间“时-分-秒”,由程序指定一个初时时间后,系统能够自动计时,其中小时为24进制,例如“23-49-21”表示23点49分21秒。第二行的“**-**-** *”分别代表实时日期的“年-月-日 星期几”,例如“10-07-30 5”意即2010年7月30日,星期五。 3.3.1 系统硬件设计 1VSS2VDD3VEE系统硬件主要由单片机AT89C51、字符液晶显示器LM016L、实时时钟芯片4RS5RW6DS1302以及电阻和开关组成,如图3-9所示。 ELCD1LM016L7D08D19D210D311D412D513D614D7 RP11U121939XTAL1P0.0/AD0338P0.1/AD1437P0.2/AD251836XTAL2P0.3/AD3635P0.4/AD4734P0.5/AD5833P0.6/AD69932RSTP0.7/AD721RESPACK-8P2.0/A822P2.1/A923P2.2/A102924PSENP2.3/A113025ALEP2.4/A123126R5EAP2.5/A132710kP2.6/A14U228P2.7/A1582R1R2R3VCC1X11101X110k10k10kP1.0P3.0/RXDVCC2211P1.1P3.1/TXD312P1.2P3.2/INT04135P1.3P3.3/INT1RST514732768HzP1.4P3.4/T0SCLK61563P1.5P3.5/T1I/OX2716P1.6P3.6/WR817DS1302P1.7P3.7/RDAT89C51 图3-9 系统电路原理图 LM016L通过上拉电阻接于AT89C51的P0口,所有接线和3.2节中的实例保持一致。下面重点介绍实时时钟芯片DS1302的工作原理及与单片机的接口。 1. DS1302功能简介 DS1302是DALLAS公司推出的涓流充电时钟芯片,内含有一个实时时钟/日历和 Proteus显示控制系统设计与实例 108 31字节静态RAM,通过简单的串行接口与单片机进行通信。实时时钟/日历电路提供秒、分、时、日、月、年、星期的信息,每月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM指示决定采用24或12小时格式。DS1302与单片机之间能简单地采用同步串行的方式进行通信,仅需用到三个口线:(1)RES(复位),(2)I/O(数据线),(3)SCLK(串行时钟)。时钟/RAM的读/写数据以一个字节或多达31个字节的字符组方式通信。DS1302工作时功耗很低,保持数据和时钟信息时功率小于1mW。DS1302是由DS1202改进而来,增加了以下的特性:双电源引脚用于主电源和备份电源供应,Vcc1为可编程涓流充电电源,附加七个字节存储器。它广泛应用于电话、传真、便携式仪器以及电池供电的仪器仪表等产品领域。下面将主要的性能指标作一综合介绍。 , 实时时钟具有能计算2100年之前的秒、分、时、日、月、年、星期的能力,还有闰年调整的能力 , 31×8位暂存数据存储RAM , 串行I/O口方式使得引脚数量最少 , 宽范围工作电压2.0,5.5V , 工作电流2.0V时,小于300nA , 读/写时钟或RAM数据时有两种传送方式:单字节传送和多字节传送(字符组方式) , 8脚DIP封装或可选的8脚SOIC封装(根据表面装配) , 简单3线接口 , 与TTL兼容(Vcc=5V) , 可选工业级温度范围-40?,+85? , 与DS1202兼容 , 在DS1202基础上增加的功能有: —对Vcc1有可选的涓流充电能力 —双电源引脚用于主电源和备份电源供应 —备份电源引脚可由电池或大容量电容输入 —附加的7字节暂存存储器 2. DS1302的基本组成和工作方式 DS1302的引脚排列如图3-10及所示。引脚描述如下: X1、X2:32.768KHz 晶振引脚 GND:地 RST;复位脚 I/O:数据输入/输出引脚 SCLK;串行时钟 图3-10 DS1302引脚图 第3章 HD44780液晶控制器显示系统设计 109 Vcc1、Vcc2:电源供电引脚 3. DS1302 的控制命令及内部寄存器 (1)命令字节 命令字节用以启动每个数据的传输。DS1302只有一个字节的控制命令格式,如表3-4所示。 表3-4 DS1302的控制命令格式 7 6 5 4 3 2 1 0 RAM RD 1 A4 A3 A2 A1 A0 WR CK 最高位(Bit 7)必须是1,如果是0,不能对DS1302进行写操作。第6位为0,指定为时钟或日历数据,如果是1则指定为RAM数据。第1,5位指定输入、输出数据的寄存器地址。最低位(Bit 0)为0则指定写操作,为1则指定读操作。命令字节最低位先被传送。表3-5是对时钟/日历数据进行读写的控制命令及数据格式对照表。 表3-5 控制命令与数据格式对照表 以表中第一行为例,81H为控制命令字节,表示要从DS1302秒寄存器中读取当前秒数据,数据格式最高位CH=0为振荡器工作允许,CH=1为振荡器停止,BIT4,BIT6为秒数据的十位(BCD码,最大为101),BIT0,BIT3为秒数据的个位(BCD码,最大为1001)。当控制命令为80H时,表示从单片机向DS1302的寄存器中写入秒数据。无论读或写,先传送控制命令,紧接着传送数据,并且都从低位开始传送。表3-5中的以下几行分别为分、时、日、月、星期、年、写保护及涓流充电设置的控制命令及数据格式,请读者自行分析。 图3-11(a)和图3-11(b)分别是数据读、写时序图。 从图中可以看出,在数据读写期间,DS1302的使能端CE必须为高电平,命令字节先从低位开始传送,时钟上升沿有效;数据字节也先从低字节开始传送,不同的是,读作操时,时钟下降沿有效,写操作时,时钟上升沿有效。 Proteus显示控制系统设计与实例 110 (a) DS1302的读操作时序 (b) DS1302的写操作时序 图3-11 DS1302的读、写操作时序 以上时序为单节字数据读写方式,DS1302还支持多字节读写方式。对时钟多字节读、写的控制命令分别为BFH、BEH,对RAM多字节读、写的控制命令分别为FFH、FEH。在读写时序上,传送完控制命令字节后,从地址0的第0位顺序传送数据字节,直到指定的地址中的数据传送完毕为止。 4. DS1302与AT89C51的接口 图3-9中,DS1302的Vcc2端为主电源,接+5V直流源,Vcc1端为后备电源,可以接100uF的电容。X1和X2端接32.768KHz晶振。复位端、串行时钟和命令、数据输入端分别接AT89C51的P3.4、P3.5和P3.6端,并且通过上拉电阻与电源相连接。 3.3.2 系统软件设计 系统软件仍然采取模块化设计,由主程序调用各子程序来完成以下功能:每隔40ms判断开关P1.1的状态,来决定显示初始化字符串“DS1302 RealClock”和“Please Select! ”或显示实时时钟。当选择为实时时钟模式时,首先通过程序向DS1302写入一个指定的初始时间和日期并显示出来。以后,DS1302以此初始时间开始计时,每隔1秒钟从DS1302中读出实时时间并在LM016L上分行显示出来。 1. 主程序流程设计 主程序流程如图3-12所示。 第3章 HD44780液晶控制器显示系统设计 111 宏指令 YP1.1=1? N 显示Time和Date显示初始化字符串 调显示“-”子程序结束 赋初始时间和日期 调向DS1302写初始 时间、日期子程序 调从DS1302读实时 时间、日期子程序 调实时时间、日期 显示子程序 25?R3 定时器T0初始化 N计数值=40ms? Y 重值计数初值 YP1.1=1? N NR3=25? Y调从DS1302读实时 时间、日期子程序 调实时时间、日期 显示子程序 25?R3 图3-12 主程序流程图 在主程序中,主要调用了字符串显示子程序、向DS1302写入初始时间、日期 子程序、从DS1302读实时时间、日期子程序以及实时时间、日期显示子程序。字 符串显示子程序在3.2节中的例子中已经介绍了,这里不再讲述。下面详细介绍其 它几个子程序的流程设计。 2. 子程序流程设计 Proteus显示控制系统设计与实例 112 (1)向DS1302写入初始时间、日期子程序 先把初始时间、日期写入单片机指定内存中去,然后调用子程序SETDS1302,即把初始数据从指定内存中写入到DS1302中去。请参考程序LLOOP5部分。 SETDS1302子程序流程如图3-13所示。共分三部分:第一部分是先使DS1302的写保护关闭,即先送出写保护设置控制字8EH,再送出关闭写保护数据00H,允许写入DS1302。 第二部分为连续写入七个字节的初始时间和日期,即秒、分、时、日、月、年、星期。把写命令控制字放入R1中,每次写命令加2,正好写完秒、写分„„依次类推。把写数据放入R0中,七个数据字节数放入R7中,每次先写入写数据控制字,接着写入初始化数据,通过判断R7决定是否继续写下一组控制命令和数据。 第三部分是已经完成了初始数据的写入,需要使DS1302写保护生效,所以,再次向DS1302写入写保护控制字8EH,不过紧接着写入的写保护数据为80H而不是00H,80H即为写保护有效。 清复位清复位清复位 清时钟清时钟清时钟 置复位置复位置复位 送出设置写保护控送出R1中的写命令送出设置写保护控制字8EH控制字?B制字8EH 调向DS1302写入一调向DS1302写入一调向DS1302写入一字节数据子程序字节数据子程序字节数据子程序 送出R0中的初始设送出开写保护数据送出关闭写保护数置数据?B80H据00H 调向DS1302写入一调向DS1302写入一调向DS1302写入一字节数据子程序字节数据子程序字节数据子程序 R0+1?R0置时钟清时钟 R1+2?R1清复位清复位 置时钟返回秒初始值?R0 清复位写秒控制字?R1 NR7-1=0,写入字节数7?R7 Y 图3-13 向DS1302设置初始时间和日期子程序流程图 在SETDS1302子程序中,又调用了一个向DS1302写入一个字节数据子程序 第3章 HD44780液晶控制器显示系统设计 113 INPUTBYTE,接下来介绍DS1302的基本读、写子程序OUTPUTBYTE和INPUTBYTE。 (2)DS1302基本读、写子程序 因为DS1302与单片机之间通信是串行数据输入、输出方式,按照图3-11的时序,我们可以把一个字节的数据或命令按照一定的次序一位一位地通过DS1302的数据线I/O进行传输。图3-14(a)和(b)分别是单片机对DS1302的读、写子程序流程。 清A8?R4 清CB?A 8?R4A右移一位 T_I/O?CA?B A右移一位C?T_I/O 置时钟置时钟 清时钟清时钟 NNR4-1=0,R4-1=0,YY 返回返回 (a)读DS1302子程序 (b)写DS1302子程序 图3-14 DS1302基本读、写子程序流程图 (3)读DS1302实时数据子程序 读DS1302实时数据子程序和向DS1302中写初始数据子程序有非常相似的地方,都是设置七个字节数据,不同的是,一个是写,一个是读。无论是读或是写,都无需知道数据放到DS1302中哪里或从DS1302中哪里去读,只需发出读命令或者是写命令,写入一个写命令后紧跟着写入一个字节的数据,而写入读命令后紧跟着读出一个字节数据,准备好要存放或读出数据的地址即可。读S1302实时数据子程序分别读出实时秒、分、时、日、月、年、星期,并存入单片机指定地址以供LCD显示调用,程序流程图如图3-15所示,请读者结合子程序GET1302自行分析。 (4)显示DS1302实时数据子程序 前面几个子程序介绍的都是单片机对DS1302的操作,显示DS1302实时数据子程序是单片机对LM016L的操作。因为实时数据已经读出,分别放在了单片机的内存单元中,只需要把它们调出送到LCD指定显存中去即可。按照实时数据在LM016L上设定的显示位置,根据LM016L的显存地址分配,可以推算出这些实时数据应 Proteus显示控制系统设计与实例 114 秒地址?R0 送出秒个位显存地址读秒控制字?R1 读字节数7?R7调写命令子程序 送秒数据?A清复位 清时钟取出低四位(秒个位) 置复位加显示转换代码30H R1?B调写数据子程序 调写DS1302子程序送出秒十位显存地址 调读DS1302子程序调写命令子程序 读出数据?@R0 送秒数据?AR0+1?R0 交换A中高低四位R1+2?R1 取出低四位(秒十位)清时钟 加显示转换代码30H清复位 调写数据子程序NR7-1=0,Y 返回返回 图3-15 读DS1302实时数据子程序流程图 图3-16 实时秒数据显示子程序流程图 该存放的显存地址分别如表3-6所示: 表3-6 LM016L显示地址分配 80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F 时 时 — 分 分 — 秒 秒 T i m e : 十 个 十 个 十 个 位 位 位 位 位 位 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF 年 年 — 月 月 — 日 日 星 D a t e : 十 个 十 个 十 个 期 位 位 位 位 位 位 几 图3-16只给出了秒实时数据显示子程序流程图,根据表3-6所示的显示存地址, 分别修改图3-16中的显示存地址和实时数据存放地址,即可得到分、时、年、月、 日、星期的实时数据显示子程序流程。需要说明的是,LM016L无论在显示字母或 第3章 HD44780液晶控制器显示系统设计 115 数据时,一般都不会通过查表3-3中的显示代码的方式来得到显示数据,只有个别特殊字符才查表。因为显示固定内容时,可以使用字符串形式,而显示实时数据时,无需知道是什么数据,只要把它从固定地址中取出,转换为八位十进制BCD码,再加上数字显示转换代码30H即可得到显示数据。这一点需要特别说明,从表3-3中我们观察到,数字0~9的显示代码低四位正好是它们对应的BCD码,而高四位都为0011,故数字的BCD码加30H正好是HD44780 CGROM中的数字的显示代码。如数字2的显示代码通过查表得32H,而它的BCD码为00000010,加上30H即00110000,正好是32H。请参看子程序DISPLAY。 1VSS2VDD3. 系统仿真结果 3VEE 4RS5在Proteus中进行软、硬件交互仿真,得到如图3-17所示的仿真结果。 RW6LCD1ELM016L7D08D19D210D311D412D513D614D7 图3-17 Proteus 仿真结果 4. 源程序(汇编语言) T_RST Bit P3.3 ;DS1302复位线引脚 T_CLK Bit P3.4 ;DS1302时钟线引脚 T_IO Bit P3.5 ;DS1302数据线引脚 SECOND EQU 30H ;秒存储单元 MINUTE EQU 31H ;分存储单元 HOUR EQU 32H ;时存储单元 DAY EQU 33H ;日存储单元 MONTH EQU 34H ;月存储单元 WEEK EQU 35H ;周存储单元 YEAR EQU 36H ;年存储单元 LCD_X EQU 2FH ;LCD地址变量 LCD_RS EQU P2.0 LCD_RW EQU P2.1 LCD_EN EQU P2.2 ;*********************************************************************/ Proteus显示控制系统设计与实例 116 ORG 0000H LJMP START ORG 0060H START: MOV SP,#60H ;修改堆栈 LCALL INIT_LCD ;调LCD初始化子程序 JNB P1.1,LLOOP2 ;P1.1为零,不显示时钟,显示字符串 MOV DPTR,#LMESS1 ;把DB块(Time:)1的地址给数据指针 MOV A,#1 ;第一行显示标志1给A CALL LCD_PRINT ;调连续字符串显示子程序 MOV DPTR,#LMESS2 ;把DB块(Date:)2的地址给数据指针 MOV A,#2 ;第二行显示标志1给A CALL LCD_PRINT ;调连续字符串显示子程序 LJMP LLOOP5 LLOOP2: ;显示DS1302 RealClock和Please Select!程序 MOV DPTR,#LMESS3 ;把DB块3的地址给数据指针 MOV A,#1 ;第一行显示标志1给A CALL LCD_PRINT ;调连续字符串显示子程序 MOV DPTR,#LMESS4 ;把DB块4的地址给数据指针 MOV A,#2 ;第二行显示标志1给A CALL LCD_PRINT AJMP LLOOP3 ;结束程序 LLOOP5: LCALL DISPLAY1 ;调显示间隔符"-"子程序 MOV SECOND,#00H ;赋初始时间 MOV MINUTE,#51H MOV HOUR,#21H MOV DAY,#07H MOV MONTH,#04H MOV WEEK,#04H MOV YEAR,#10H LCALL SETDS1302 ;把初始时间写到DS1302中去 LCALL GET1302 ;从DS1302中读出实时时间 LCALL DISPLAY ;调实时时间显示子程序 MAIN: MOV R3,#25 ;计数器,40ms×25=1s 第3章 HD44780液晶控制器显示系统设计 117 MOV TMOD,#01H MOV TH0,#70H ;置定时器初值(定时40ms) MOV TL0,#00H SETB TR0 ;启动定时器T0 LP1: JBC TF0,LP2 ;查询计数溢出 SJMP LP1 ;未到40 ms继续计数 LP2: MOV TH0,#0B8H ;重新置定时器初值 MOV TL0,#00H JNB P1.1,LLOOP2 ;每40mS判断一次开关状态 DJNZ R3,LP1 ;未到1S继续循环 LCALL GET1302 ;每过1s从DS1302读取一次时间 LCALL DISPLAY ;每过1s把DS1302读取最新时间显示刷新一次 MOV R3,#25 SJMP LP1 ;************************************************************* INIT_LCD: ;LCD初始化子程序 CLR LCD_EN ;清使能端 MOV A,#38H ;双行显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#0EH CALL WCOM CALL DELAY1 MOV A,#38H CALL WCOM CALL DELAY1 MOV A,#0CH ;开显示,显示光标,光标不闪烁 CALL WCOM CALL DELAY1 MOV A,#01H ;清除 LCD 显示屏 CALL WCOM CALL DELAY1 RET WCOM: ;以8位控制方式将命令写至LCD MOV P0,A ;写入命令 Proteus显示控制系统设计与实例 118 CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲 CLR LCD_RW SETB LCD_EN ACALL DELAY1 CLR LCD_EN RET DE: MOV R7,#250 DJNZ R7,$ RET DELAY1: ;延时5MS MOV R6,#25 DL2: MOV R7,#100 DJNZ R7,$ DJNZ R6,DL2 RET WDATA: ;以8位控制方式将数据写至LCD MOV P0,A ;写入数据 SETB LCD_RS CLR LCD_RW SETB LCD_EN CALL DE CLR LCD_EN CALL DE RET ;LCD显示子程序 DISPLAY1: ;显示第一行和第二行中的四个“-” MOV A,#88H LCALL WCOM MOV A,#2DH LCALL WDATA MOV A,#8BH LCALL WCOM MOV A,#2DH 第3章 HD44780液晶控制器显示系统设计 119 LCALL WDATA MOV A,#0C8H LCALL WCOM MOV A,#2DH LCALL WDATA MOV A,#0CBH LCALL WCOM MOV A,#2DH LCALL WDATA RET DISPLAY: ;******************************************* ;显示秒 MOV A,#8DH ;送出秒个位的显示存地址 LCALL WCOM ;调写命令子程序 MOV A,SECOND ;把秒数据送入A ANL A,#0FH ;取出低四位即BCD码秒个位 ADD A,#30H ;0~9任意数字加30H后方可在LM016L上正确显示出来 LCALL WDATA ;调数据显示子程序 MOV A,#8CH ;送出秒十位的显示存地址 LCALL WCOM ;调写命令子程序 MOV A,SECOND ;把秒数据送入A SWAP A ;A中高四位和低四位交换 ANL A,#07H ;取出低四位即BCD码秒十位 ADD A,#30H ;把秒十位变成可显示的数据 LCALL WDATA ;调数据显示子程序 ;******************************************* ;显示分 MOV A,#8AH LCALL WCOM MOV A,MINUTE ANL A,#0FH ADD A,#30H LCALL WDATA MOV A,#89H Proteus显示控制系统设计与实例 120 LCALL WCOM MOV A,MINUTE SWAP A ANL A,#07H ADD A,#30H LCALL WDATA ;******************************************* ;显示小时 MOV A,#87H LCALL WCOM MOV A,HOUR ANL A,#0FH ADD A,#30H LCALL WDATA MOV A,#86H LCALL WCOM MOV A,HOUR SWAP A ANL A,#03H ADD A,#30H LCALL WDATA ;******************************************* ;显示日 MOV A,#0CDH LCALL WCOM MOV A,DAY ANL A,#0FH ADD A,#30H LCALL WDATA MOV A,#0CCH LCALL WCOM MOV A,DAY SWAP A ANL A,#03H ADD A,#30H LCALL WDATA 第3章 HD44780液晶控制器显示系统设计 121 ;******************************************* ;显示月 MOV A,#0CAH LCALL WCOM MOV A,MONTH ANL A,#0FH ADD A,#30H LCALL WDATA MOV A,#0C9H LCALL WCOM MOV A,MONTH SWAP A ANL A,#01H ADD A,#30H LCALL WDATA ;******************************************* ;显示年 MOV A,#0C7H LCALL WCOM MOV A,YEAR ANL A,#0FH ADD A,#30H LCALL WDATA MOV A,#0C6H LCALL WCOM MOV A,YEAR SWAP A ANL A,#0FH ADD A,#30H LCALL WDATA ;******************************************* ;显示周 MOV A,#0CFH LCALL WCOM MOV A,WEEK ANL A,#07H Proteus显示控制系统设计与实例 122 ADD A,#30H LCALL WDATA RET ;******************************************* ;显示延时5ms子程序 DIS_DELAY: PUSH PSW MOV R7,#10 D1: MOV R6,#248 D2: DJNZ R6,$ DJNZ R7,D1 POP PSW RET ;******************************************* SETDS1302: ;设置DS1302初始时间,并启动计时 CLR T_RST NOP CLR T_CLK NOP SETB T_RST NOP MOV B,#8EH ;写控制命令字 LCALL INPUTBYTE MOV B,#00H ;写保护关闭,可以写 LCALL INPUTBYTE SETB T_CLK NOP CLR T_RST MOV R0,#SECOND ;单片机内存中的秒地址 MOV R1,#80H ;把向DS1302写秒数据命令字节送R1 MOV R7,#7 ;字节数(秒、分、时、日、月、天、年) SETLOOP: CLR T_RST NOP CLR T_CLK NOP 第3章 HD44780液晶控制器显示系统设计 123 SETB T_RST NOP MOV B,R1 ;向DS1302中写入命令字 LCALL INPUTBYTE MOV A,@R0 ;设置时间 MOV B,A LCALL INPUTBYTE INC R0 ;单片机内存中的初始时间、日期地址加1 INC R1 ;命令字加1 INC R1 ;命令字再加1 SETB T_CLK NOP CLR T_RST NOP DJNZ R7,SETLOOP ;把七个时间地址和七个时间初始值全部写入DS1302 CLR T_RST NOP CLR T_CLK NOP SETB T_RST NOP MOV B,#8EH ;发写保护否控制命令 LCALL INPUTBYTE MOV B,#80H ;开写保护,不允许向DS1302中写数据 LCALL INPUTBYTE SETB T_CLK NOP CLR T_RST NOP RET ;******************************************* GET1302: ;从DS1302读取时间 MOV R0,#SECOND MOV R1,#81H ;读秒控制字送R1 MOV R7,#7 GETLOOP: Proteus显示控制系统设计与实例 124 CLR T_RST NOP CLR T_CLK NOP SETB T_RST NOP MOV B,R1 LCALL INPUTBYTE ;写入读命令字 LCALL OUTPUTBYTE ;读出一个实时时间或日期 MOV @R0,A ;将从DS1302中读取的时间或日期从内存中保存 INC R0 ;修改地址指针 INC R1 INC R1 ;下一个读命令 SETB T_CLK NOP CLR T_RST NOP DJNZ R7,GETLOOP ;读完七个实时时间和日期结束,否则转GETLOOP RET ;******************************************* INPUTBYTE: ;向DS1302写一个字节 MOV R4,#8 INPUTLOOP: MOV A,B RRC A MOV B,A MOV T_IO,C SETB T_CLK NOP CLR T_CLK DJNZ R4,INPUTLOOP RET ;******************************************* ;从DS1302读一个字节 OUTPUTBYTE: CLR A 第3章 HD44780液晶控制器显示系统设计 125 CLR C MOV R4,#8 OUTPUTLOOP: NOP MOV C,T_IO RRC A SETB T_CLK NOP CLR T_CLK DJNZ R4,OUTPUTLOOP RET ;******************************************* LCD_PRINT: ;显示Time:和Date: 程序 CJNE A,#1,LINE2 LINE1:MOV A,#80H CALL WCOM JMP FILL LINE2:MOV A,#0C0H CALL WCOM FILL:CLR A MOVC A, @A+DPTR CJNE A,#0,L1 RET L1: CALL WDATA INC DPTR JMP FILL RET ;************************* ;显示数据块 LMESS1:DB "Time:",0 LMESS2:DB "Date:",0 LMESS3:DB "DS1302 RealClock",0 LMESS4:DB "Please Select! ",0 LLOOP3:NOP END Proteus显示控制系统设计与实例 126 3.4 基于1602C和DS18B20的多点温度监测系统设计 本节要讨论的多点温度监测控制系统是采用多个单总线数字温度传感器DS18B20作为温度采集单元、字符液晶显示器1602C作为温度监测显示单元、单片机AT89C51作为控制中心的一个综合控制系统,主要应用于测温点多、温度范围分布广或空间较大的场合。 本设计要求: (1)系统测量精度0.1?,报警上、下限分别为80?(正值)和20?(正、负均可),温度数据实时刷新。测量的温度点数为4个,采用2×2矩阵键盘进行监测选择,以和实际单片机系统配置相一致。 (2)采用一片1602C作为系统显示,显示内容分为三个部分: , 系统检测到DS18B20不存在,分两行显示以下字符: DS18B20 ERROR TEMP: ――――? , 系统运行正常,无键盘操作,分两行显示以下字符: ZHU Qing Hui Nan Yang Li Gong , 系统运行正常,有键盘操作,分两行显示以下内容(以健盘1为例): ZHU Qing Hui TEMP1:―15.3? H”。 3.4.1 系统硬件设计 根据设计要求,画出系统硬件结构框图如图3-18所示。 系统控制核心部件采用AT89C51单片机,温度传感器采用四个一线式数字温度传感器DS18B20,液晶显示器采用两行共32个字符的1602C(在Proteus中仿真时使用LM016L,控制器为HD44780),四个温度测量和显示选择按键采用2×2矩阵键盘(虽然并不节省单片机的I/O口,但主要目的是为了在实际电路制作时,能够直接利用标配的单片机开发板而不用因此再修改程序)。根据系统硬件框图,在Proteus中设计出系统电路原理图如图3-19所示。 第3章 HD44780液晶控制器显示系统设计 127 LCD温度传感器 温度传感器 单片机温度传感器 温度传感器 2×2键盘1VSS2 VDD3VEE4 图3-18 系统硬件结构框图 RS5RW6ELCD1LM016L7D08D19D210RP1D311RESPACK-8D412D5131D614D723456789U51939XTAL1P0.0/AD038P0.1/AD137P0.2/AD21836XTAL2P0.3/AD335P0.4/AD434P0.5/AD533P0.6/AD6932RSTP0.7/AD721P2.0/A822P2.1/A923P2.2/A102924PSENP2.3/A11A123025ALEP2.4/A123126EAP2.5/A1327P2.6/A14284P2.7/A15BDS18B203U11103P1.0P3.0/RXDVCC211-1.821P1.1P3.1/TXDDQ3121P1.2P3.2/INT0GND413P1.3P3.3/INT1514P1.4P3.4/T0DS18B20U26152P1.5P3.5/T13716VCCP1.6P3.6/WR112.52817DQP1.7P3.7/RD1GNDAT89C51R9R1010k10kDS18B20U33VCC20.02DQ1GND DS18B20U43VCC41.92DQ1GND 图3-19 Proteus中系统电路原理图 Proteus显示控制系统设计与实例 128 图3-19中,液晶显示器LM016L以及与单片机的连接在前面的例子中我们已经非常熟悉了,故不再介绍。主要介绍矩阵键盘和DS18B20的相关内容。 1. Proteus中2×2矩阵键盘的制作 在Proteus中,用户可以根据自己的需要制作特殊键盘,下面我们来制作一个2×2矩阵键盘,读者可以按照此法制作自己需要的任何键盘。 (1)利用二维绘图工具,画出如图3-20(a)所示的键盘。 (2)在图3-20(a)中放置键盘引脚。点击鼠标右键,选择【Place】?【Device Pin】?【DEFAULT】,放置四个引脚,注意引脚的方向,带“×”一端朝外,如图3-20(b)所示。 A1212 4B343 1 2 (a) (b) 图3-20 键盘外观及引脚图 (3)在图2-30(b)中,放置元件引脚时必须同时命名,按照规定,水平放置的引脚必须命名为A、B、C、D„„,垂直放置的引脚必须命名为1、2、3、4„„。命名后,引脚名自动出现在元件内侧。放置引脚后,双击引脚线,即出现如图3-21所示的元件属性对话框。在“Pin Name”一栏对元件进行命名,其它不用改变。 图3-21 引脚命名 (4)重新定位坐标原点并放置坐标原点标记。 第3章 HD44780液晶控制器显示系统设计 129 大家注意到,在图3-20(b)中,键盘外边框左上角多了一个符号,即坐标原点标记,这是必须的一步,通过点击鼠标右键,选择【Place】?【Maker】?【ORIGIN】来放置。放置了坐标原点标记并不等于这一点是真正的坐标原点,还要设置该点为假想坐标原点。点击主菜单下方主工具栏中的放置坐标原点符号(两个符号一样,但操作效果不一样),如图3-22所示,然后在图3-20(b)中键盘边框左上角位置点一下,即设置该点坐标为(0,0),可以观察编辑区右下角的坐标显示。 图3-22 设置坐标原点命令 (5)记下四个按键的中心点坐标及边长。这一步非常关键,如有一点差错,制作的键盘将不能用。拿来纸和笔,先把坐标值记下,在下面的步骤中,对键盘参数进行设置时会用到。把鼠标指向第一个按键的中心位置,读出Proteus编辑区右下方坐标显示数据,可以调整背景格点密度来准确读数,也可以通过计算得到。得到第一个按键的坐标值为350,-350;第二个按键的坐标值为750,-350;第三个按键的坐标值为350,-750;第四个按键的坐标值为750,-750;边长300。 (6)下面的步骤把二维图形合成一个整体元件,赋参数、仿真模型并存入元件库。先圈选所画的矩阵键盘,在主菜单中进行以下操作:【Library】?【Make Device】,出现如图3-23所示的元件制作对话框。在Device Name中对元件进行命名,其它照图填写。点击“Next”,出现下如图3-24所示的对话框,不指定元件封装,直接点击“Next”。 图3-23 元件命名 图3-24 指定元件封装 Proteus显示控制系统设计与实例 130 (7)紧接着图3-24后出现的是设置键盘坐标值对话框,如图3-25所示。要分别对PRIMITIVE、MODDLL、A1、A2、A3、A4及PACKAGE七个方面的参数进行设置。其中A1、A2、A3、A4是四个按键名,其它三个参数是必须要设置的。在图3-25中按左边的“NEW”键,出现如图3-26所示的设置项目列表。 图3-25 按键参数设置 图3-26 设置项目选择 先选中“PRIMITIVE”项,右边是参数设置,其它参数不变,只在下方的“Default Value”项中把“None”改成“DIGITAL”。按“Next”,现出下一个对话框,再按“Back”回到图3-27所示的对话框,继续进行下一项设置。 点击“New”按键,选择“MODDLL”项,照图3-28进行各项参数设置。 图3-27 PRIMITIVE项参数设置 图3-28 MODDLL项参数设置 第3章 HD44780液晶控制器显示系统设计 131 设置完成后,按“New”进行四个按键坐标的设置,选择“Black Item”,出现如图3-29所示的对话框,按图进行各项参数设置。把前面记下的第一个按键的坐标填入相应栏中,格式为(半角):SQUARE:350,-350,300(方形:横坐标,纵坐标,边长)。按照此方法,依次把A2、B1、B2三个键设置完毕。最后设置PACKAGE项,如图3-30所示。 图3-29 按键参数设置 图3-30 PACKAGE项参数设置 图3-31 按键参数设置 图3-32 PACKAGE项参数设置 继续按“Next”键,在最后两个对话框中,按图3-31和图3-32进行参数设置,最后按“Ok”键,在随后可能出现的对话框中回答“Yes”,即完成了整个键盘的制作。 此2×2键盘存在了Proutes元件库的Switches & Relays大类中的KeyPads子类中,可按类查询,或直接输入元件名2×2 KEYPAD调用即可。 Proteus显示控制系统设计与实例 132 使用该元件时,一定要从元件库中再次调出方可使用,不能直接使用编辑区制作完成的元件。按照图3-19来完成连线,电阻是必须要加的。 2. DS18B20及其与单片机的连接 DS18B20是达拉斯半导体公司生产的可编程分辨率的单总线数字温度计,常用封装如图3-33所示。 图3-33 DS18B20正视图及俯视图 图3-33中,VDD为直流电源端,GND为接地端,DQ为数据I/O端。 DS18B20具有以下特点: , 独特的单线接口只需l个接口引脚即可通信。 , 每个器件有唯一的64位序列号存在内部存储器中。 , 简单的分布式多点测温应用。 , 无需外部器件。 , 可通过数据线供电,供电范围为3.0V,5.5V。 , 测温范围为-55?至+125?。 , 温度计分辨率9,12位可选择。 , 最多在750ms内将温度转换为12位数字。 , 用户可定义的非易失性温度报警设置。 , 有11条指令来完成各种功能。 四个DS18B20与AT89C51的连接如图3-19所示。需要说明的是,在实物连接时,单总线与电源之间要接4.7kΩ的电阻。DS18B20在使用时,必需对其使用 手册 华为质量管理手册 下载焊接手册下载团建手册下载团建手册下载ld手册下载 作详细的阅读和分析才能进行软件编辑,具体功能在软件设计部分中涉及到哪方面内容,我们再详细讲解。 3.4.2 读DS18B20 ROM序列号电路设计 每个实际的DS18B20器件都有一个独特的64位ROM序列号,而这个序列号在产品上或产品说明书上是无法找到的,它存于器件内部存储器中,必须通过电路 第3章 HD44780液晶控制器显示系统设计 133 把它读出来才能使用。读ROM序列号也可以直接按图3-19的电路,通过软件编程来实现,但由于软件编程的工作量太大,算法及其复杂,一般不采用单总线上挂多个DS18B20进行读ROM序列号的方法。下面我们介绍一种非常方便实用的读DS18B20 ROM序列号的电路及软件。 1. 电路原理图 在图3-34所示的电路中,通过四位开关分别把四个DS18B20与单总线接通,然后启动按钮,发光二极光每亮一次读出一个字节的十六制数并记录下来,图中读数应为28H,为ROM序列号8个字节中的最高位字节。在向DS18B20中写序列号匹配ROM时,应先送出最高位字节,即28H。 U51939XTAL1P0.0/AD038P0.1/AD137P0.2/AD21836XTAL2P0.3/AD335P0.4/AD434P0.5/AD533P0.6/AD6932RSTP0.7/AD7 21P2.0/A822P2.1/A9U1233P2.2/A10VCC292427.02PSENP2.3/A11DQ30251ALEP2.4/A12GND3126EAP2.5/A13273P2.6/A14VCCU22827.02P2.7/A15DQ1GND110P1.0P3.0/RXD2113P1.1P3.1/TXDVCCU331227.02P1.2P3.2/INT0DQ4131P1.3P3.3/INT1GND514P1.4P3.4/T06153P1.5P3.5/T1VCCU471627.02P1.6P3.6/WRDQ8171P1.7P3.7/RDGND AT89C51 图3-34 读DS18B20 ROM序列号电路 2. Proteus中DS18B20的参数设置 在温度控制系统仿真进行前,必须在Proteus中对DS18B20进行参数设置,即精度设置和ROM序列号设置两项。双击图3-34中的U1,打开如图3-35所示的元件属性对话框。 在“Granularity”一栏中,把1改成0.1,即测量温度的精确度由1?改成了0.1?。 在“ROM Serial Number”一栏,有三个字节的十六进制数,是ROM序列号的第五、六、七字节,我们只能对这三个字节进行更改,四个DS18B20的ROM序列 Proteus显示控制系统设计与实例 134 号只要不一样就行。其它五个字节是系统设置好的,看不到,能通过软件编程读出来,最高位字节固定为28H。 图3-35 DS18B20元件属性对话框 我们把Proteus中四个DS18B20的十六进制ROM序列号分别设为: U1:39C524;U2:B8C530;U3:B8C531;U4:B8C532 3. 读ROM 序列号软件流程设计 读DS18B20序列号的程序并不复杂,主程序流程如图3-36所示。首先对单片机的P2口和P3.0进行清零,然后查询读ROM序列号开关是否闭合,不闭合则等待,闭合则往下执行。先调一个对DS18B20进行初始化的子程序,然后写入读ROM序列号命令33H,该命令只对单总线上挂一个DS18B20进行操作,调写命令子程序。接下来调从DS18B20读取一个字节数据的子程序,把读出来的一个字节数据存入40H,最先读出的是ROM中64位序列号的高八位, 28H。继续进行数据读操作,顺序把读出的其余七个字节分别存入单片机的41H,47H。 然后是按从高到低字节顺序把8个字节的ROM序列号输出给P2口的十六进制数码管进行显示。8个字节显示完毕后,程序再回去判断启动开关的状态,继续进行下一个DS18B20的ROM序列号读取和显示。 子程序比较简单,不再介绍,请读者直接参看源程序。 在操作时,要保证在每次灯亮时读数。 读出的四个DS18B20的ROM序列号(由高到低)分别为: U1:28H 24H C5H 39H 00H 00H 00H 5FH U2:28H 30H C5H B8H 00H 00H 00H 8EH U3:28H 31H C5H B8H 00H 00H 00H B9H U4:28H 32H C5H B8H 00H 00H 00H E0H 第3章 HD44780液晶控制器显示系统设计 135 I/O口初始化40H?P2 显示最高位数 N指示灯亮P1.7=0?Y调延时子程序调DS18B20初始化子程序 指示灯灭写入读ROM序列号命令调延时子程序调从DS18B20读一个字节数据子程序41H?P2 显示次高位数 指示灯亮读取的第一字节?40H 调延时子程序调从DS18B20读一个字节数据子程序指示灯灭 读取的第二字节?41H调延时子程序 调从DS18B20读一个字节42H?P2 数据子程序 指示灯亮读取的第三字节?42H 调延时子程序调从DS18B20读一个字节数据子程序指示灯灭 读取的第四字节?43H调延时子程序 调从DS18B20读一个字节43H?P2 数据子程序指示灯亮读取的第五字节?44H调延时子程序调从DS18B20读一个字节指示灯灭数据子程序 调延时子程序读取的第六字节?45H...调从DS18B20读一个字节47H?P2 显示最低位数数据子程序 指示灯亮读取的第七字节?46H 调延时子程序调从DS18B20读一个字节数据子程序指示灯灭 读取的第八字节?47H调延时子程序 图3-36 读DS18B20 ROM序列号主程序流程图 4. 读ROM序列号源程序(汇编语言) ORG 0000H DQ BIT P1.0 FLAG BIT 00H ;器件是否存在的标志位,器件存在由软件置1,否则清0 AJMP MAIN ORG 0020H Proteus显示控制系统设计与实例 136 MAIN: CLR P3.0 MOV P2,#00H LOOP: JB P1.7,$ ;启动开关,低电平有效 LCALL INT ;调DS18B20初始化子程序 MOV A,#33H LCALL WRITE ;写入读取ROM命令 LCALL READ ;调读命令子程序 MOV 40H,A ;读取的第一个字节送40H LCALL READ MOV 41H,A LCALL READ MOV 42H,A LCALL READ MOV 43H,A LCALL READ MOV 44H,A LCALL READ MOV 45H,A LCALL READ MOV 46H,A LCALL READ MOV 47H,A ;读取的第八个字节送47H MOV P2,40H ;第八个字节(ROM序列号最低位)送P2 SETB P3.0 ;字节间隔辨识指示灯亮 LCALL DELAY1 ;调延时子程序 CLR P3.0 ;指示灯灭 LCALL DELAY ;调延时子程序 MOV P2,41H SETB P3.0 LCALL DELAY1 CLR P3.0 LCALL DELAY 第3章 HD44780液晶控制器显示系统设计 137 MOV P2,42H SETB P3.0 LCALL DELAY1 CLR P3.0 LCALL DELAY MOV P2,43H SETB P3.0 LCALL DELAY1 CLR P3.0 LCALL DELAY MOV P2,44H SETB P3.0 LCALL DELAY1 CLR P3.0 LCALL DELAY MOV P2,45H SETB P3.0 LCALL DELAY1 CLR P3.0 LCALL DELAY MOV P2,46H SETB P3.0 LCALL DELAY1 CLR P3.0 LCALL DELAY MOV P2,47H SETB P3.0 LCALL DELAY1 LCALL DELAY LJMP LOOP ;重新等待启动开关,读下一个ROM序列号 Proteus显示控制系统设计与实例 138 INT: ;DS18B20初始化子程序 L0: CLR DQ MOV R2,#200 L1: CLR DQ DJNZ R2,L1 SETB DQ MOV R2,#30 L4: DJNZ R2,L4 CLR C ORL C,DQ JC L0 MOV R6,#80 L5: ORL C, DQ JC L3 DJNZ R6,L5 SJMP L0 L3: MOV R2,#240 L2: DJNZ R2,L2 RET WRITE: ;向DS18B20写一个字节数据子程序 MOV R3,#8 WR1: SETB DQ MOV R4,#8 RRC A CLR DQ WR2: DJNZ R4,WR2 MOV DQ,C MOV R4,#20 第3章 HD44780液晶控制器显示系统设计 139 WR3: DJNZ R4,WR3 DJNZ R3,WR1 SETB DQ RET READ: ;从DS18B20读一个字节数据子程序 MOV R6,#8 RE1: CLR DQ MOV R4,#4 NOP SETB DQ RE2: DJNZ R4,RE2 MOV C,DQ RRC A MOV R5,#30 RE3: DJNZ R5,RE3 DJNZ R6,RE1 SETB DQ RET ;两个延时子程序DELAY和DELAY1 DELAY: MOV R1,#20 DEL1: MOV R0,#250 DEL2: MOV 30H,#250 DEL3: DJNZ 30H,DEL3 DJNZ R0,DEL2 DJNZ R1,DEL1 RET DELAY1: Proteus显示控制系统设计与实例 140 MOV 32H,#10 DEL11: MOV 33H,#250 DEL12: MOV 34H,#250 DEL13: DJNZ 34H,DEL13 DJNZ 33H,DEL12 DJNZ 32H,DEL11 RET END 3.4.3 4-DS18B20 温度检测系统软件设计 前面我们已经设计出了四个DS18B20温度监测系统电路原理图,又读出了每个DS18B20的ROM序列号,下面要进行的就是系统软件设计工作了。为了使程序结构清晰,便于读阅读,程序设计采取模块化,由主程序调用各子程序。 1. 主程序流程设计 根据设计任务要求,设计系统主程序流程如下: 首先是系统初始化,包括宏指令(对单片机内存及I/O定义,以增加程序的可读性)、堆栈指针设置、内存各单元清零、设置温度报警上、下限值、LCD初始化(包括将自定义字符温度单位?中的?写入CGRAM)。 接下来调DS18B20初始化子程序。DS18B20初始化执行完毕后,判断单总线11VSSVSS22上DS18B20是否存在,如不存在,调系统出错显示子程序,显示结果如图3-37所VDDVDD33VEEVEE示,然后结束。如DS18B20存在,调系统正常显示子程序,显示结果如图3-38所44RSRS55RWRW示。把温度上、限值拷贝到DS18B20存暂器,调DS18B20复位子程序。 66EELCD1LCD1LM016LLM016L77D0D088D1D199D2D21010D3D31111D4D41212D5D51313D6D61414D7D7 图3-37 系统正常显示 图3-38 系统出错显示 再次判断单总线上DS18B20是否存在,不存在仍然转到系统出错显示。DS18B20存在,由单片机向DS18B20发送跳过ROM匹配命令,即接下来的一条命 第3章 HD44780液晶控制器显示系统设计 141 令是对单总线上所有DS18B20有效,而不用匹配ROM序列号。单片机向所有DS18B20发出温度转换命令,四个温度传感器同时开始温度转换,调1秒温度转换延时(DS18B20最长750ms即可将传感器的温度转换成12位数字量温度值)。 接下来的程序是把四个DS18B20把转换好的温度值,按照顺序读入单片机内存中存储。共四段程序,每一段程序结构完全一样,不一样的是ROM序列号及内存单元。由主机向DS18B20发出匹配ROM序列号命令,接下来发送第一个DS18B20即U1的64位ROM序列号,由高到低,一个字节一个字节地写入,共八个字节。发送完64位ROM序列号,再发送允许主机读该温度传感器温度数据命令,接着调读DS18B20温度数据子程序。在子程序中,读到的两个字节十六进制温度数据分别存在了TEMPL和TEMPH中。把TEMPL和TEMPH中读到的第一个传感器温度数值分别存入74H和75H中去。再次调DS18B20复位子程序。即完成了第一个DS18B20的温度数据读出任务。 下面的三段程序分别送出U2、U3和U4的ROM序列号,并分别把读出的温度数据存入76H和77H、78H和79H、7AH和7BH,以备后面的程序使用,对这些温度数据进行处理和显示。 接下来的部分是矩阵键盘查询和处理部分。因为设计任务要求必须有相应键按下,才转去显示相应温度传感器的数据。 判断是否有键按下,如果没有,继续查询。如有键按下,则先对LCD第二行进行清屏,因为温度数据要显示在LCD的第二行。系统初始显示时,LCD第二行有字符,如果不清屏,温度数据显示没有占用的位置就会显示原来的字符内容。调延时去抖动程序,再次判断是否有键按下,没有继续等待;有键按下,先判断是否一号键按下,如不是,判断是否二号键按下,如仍然不是,判断是否三号键按下,不是,则判断是否四号键按下。 有键按下,先置按键标志位,FLAG6、FLAG7、FLAG8、FLAG9分别为一号、二号、三号和四号键按下标志位。无论四个按键中哪个按键按下,都执行一样的程序体。即先在LCD的第二行初始位置开始显示“TEMP:”,把读到的双字节温度初始数据送TEMPL和TEMPH,调温度转换子程序、调把温度转换成可显示的BCD码子程序、调显示温度数据子程序、调显示温度比较及结果符号显示子程序、调摄氏温度单位显示子程序。 然后,再回到程序初始化之后,调DS18B20复位子程序、判断DS18B20是否存在以及发送ROM序列号、读温度值等。程序这样转的目的是,保证温度值的实时采样和刷新。 系统主程序流程如图3-39所示。 Proteus显示控制系统设计与实例 142 初始化 调DS18B20初始化子程序 NNDS18B20存在吗,是否有键按下,YY调正常显示字符串子程序调出错显示字符串子程序先对LCD第二行清屏 温度报警上、限值拷贝到延时调显示“?”子程序暂存器N结束有键按下吗,调DS18B20复位子程序YNNN#1键按下了吗,#2键按下了吗,#3键按下了吗,#4键按下了吗,NDS18B20存在吗,YYYYY置标志位FLAG6=1置标志位FLAG7=1置标志位FLAG8=1置标志位FLAG9=1写跳过ROM匹配命令 写启动温度转换命令在LCD第二行显示“TEMP:”调1秒温度转换延时子程序把读出的温度数据送至..写匹配ROM序列号命令TEMPL和TEMPH.发送第八个DS18B20的64发送第一个DS18B20的64调温度转换、显示位ROM 序列号位ROM 序列号子程序 发送允许主机读DS18B20发送允许主机读DS18B20显示温度比较结果的16位温度数据命令的16位温度数据命令“>”、“<”、“!” 调读DS18B20温度子程序调读DS18B20温度子程序调显示温度单位“?”子程序温度数据低八位?7AH温度数据低八位?74H 温度数据高八位?7BH温度数据高八位?75H 调DS18B20复位子程序调DS18B20复位子程序 图3-37 系统主程序流程图 2. 子程序流程设计 在主程序中,系统初始化、判断DS18B20是否存在、启动温度转换、发送四个ROM序列号、存温度转换值、按键判断及各字符显示DB块为非模块化编程,除此之外,全部调用子程序。主程序按照顺序主要调用了以下各子程序: RE_18B20: DS18B20初始化子程序 SET_LCD: LCD初始化子程序 STORE_DATA: 向LCD的CGRAM写入自字义自符“?”子程序 MENU_ERROR: DS18B20不存在,系统非正常字符串显示子程序 MENU_OK: 系统正常字符串显示子程序 RESET: DS18B20复位子程序 WRITE: 向DS18B20写一字节数据子程序 READ: 从DS18B20读两个字节温度数据子程序 CONVTEMP: 温度数据处理子程序 DISPBCD: 把处理后的温度数据转换成可供LCD显示的BCD码子程序 LCD_DISP: 温度数据显示子程序 TEMP_COMP: 实时温度与报警上、下限值比较并显示结果子程序 第3章 HD44780液晶控制器显示系统设计 143 TEMP_BJ: 显示摄氏温度单位子程序 在这些子程序中,基本子程序是LCD及DS18B20初始化、复位及各自的读、写子程序等,流程设计主要来源于这两个器件的操作手册,根据各自的功能及要求即可完成。重要的子程序是在按键后进入的功能子程序,即温度数据处理子程序CONVTEMP、BCD码转换子程序DISPBCD、温度数据显示子程序LCD_DISP和温度数据比较及显示子程序TEMP_COMP。 下面介绍几个基本子程序的流程设计或程序,然后再重点介绍以上四个功能子程序。 (1)LCD初始化子程序 LCD初始化子程序共包括两部分,第一部分是调用LCD初始化子程序INIT_LCD,第二部分是调用CGRAM自定义自符子程序STORE_DATA。程序如下所示: SET_LCD: CLR LCD_EN CALL INIT_LCD ;初始化 LCD CALL STORE_DATA ;将自定义字符存入LCD的CGRAM RET 其中INIT_LCD子程序如下: INIT_LCD: ;8位I/O控制 LCD 接口初始化 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 ;调用5ms延时子程序 MOV A,#0EH ;设置光标显示方式 CALL WCOM CALL DELAY1 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#0CH ;开显示,显示光标,光标不闪烁 CALL WCOM CALL DELAY1 MOV A,#01H ;清除 LCD 显示屏 CALL WCOM CALL DELAY1 RET 在前几节的例子中,对LCD的初始化是先把所有初始化命令全部写入之后,调 Proteus显示控制系统设计与实例 144 一个15ms的延时子程序,以等初始化的完成。在上面这段程序中,使用了每条初始化指令后加5ms延时的方法,总时间超过15ms,确保了初始化的完成。不过,仍然推荐使用调一个15ms延时子程序,这样程序更简洁。 下面来看如何向LM016L的CGRAM写入一个自定义字符。因为在LM016L的CGROM中,没有摄氏温度单位符号“?”,所以考虑分两个8×8点阵来显示?,先显示一个“?”,再显示一个“C”。而LM016L的CGROM中也没有“?”这个符号,所以要用户自定义,再使用。图3-38是我们画出的8×8点阵中符号“?”的点阵图及应写入CGRAM的字节。 图3-38 “?”的8×8点阵及对应字节 根据自定义符号“?”的点阵图,设计出STROE_ DATA子程序如下: STORE_DATA: MOV A,#40H ;把CGRAM首地址40H送累加器 CALL WCOM ;向LCD写入命令子程序 MOV R2,#08H ;共写入8个字节 MOV DPTR,#D_DATA ;字节数据块首地址送数据指针 MOV R3,#00H ;数据指针的相应地址清零 S_DATA: MOV A,R3 MOVC A,@A+DPTR ;取出数据块中一个字节 CALL WDATA ;向LCD写入数据子程序 INC R3 DJNZ R2,S_DATA ;直把8个字节写完为止 RET 在系统主程序中,一定要放置数据块如下: D_DATA: DB 0CH,12H,12H,0CH,00H,00H,00H,00H (2)显示温度单位“?”子程序 TEMP_BJ是把两个8×8点阵字符“?”和“C”显示在LM016L第二行指定 第3章 HD44780液晶控制器显示系统设计 145 位置的子程序。程序如下: TEMP_BJ: MOV A,#0CBH ;发出从CGRAM读数据命令 CALL WCOM MOV DPTR,#BJ1 ;指针指到数据块首地址 MOV R1,#0 ;设数据块偏址指针为0 MOV R0,#2 ;设读取字节个数为2 BBJJ1: MOV A,R1 MOVC A,@A+DPTR ;取出数据块中的一个数据 CALL WDATA ;调向写LCD子程序 INC R1 ;偏址加1 DJNZ R0,BBJJ1 ;直到读完两个字节为止 RET 在系统主程序中要放置如下数据块: BJ1: DB 00H,"C" 其中,数据块中第一个00H是CGRAM中自定义字符的显示代码(前面已经介 绍,8个自定义字符的代码分别为00~07H),第二个用字符串表示,来自于CGROM。 (3)DS18B20初始化及复位子程序 RE_18B20: JB FLAG1,RE_18B20A ;判断标志位,如果DS18B20存在则调初始化子程序 RET RE_18B20A: CALL RESET ;先调DS18B20复位子程序 MOV A,#0CCH ;跳过ROM匹配,即以下四条命令对所以DS18B20有效 LCALL WRITE MOV A,#4EH ;写暂存寄存器 LCALL WRITE MOV A,TEMP_TH ;写入报警上限值 LCALL WRITE MOV A,TEMP_TL ;写入报警下限值 LCALL WRITE MOV A,#7FH ;设温度数据为12位 LCALL WRITE RET Proteus显示控制系统设计与实例 146 在上段程序中,把DS18B20转换完成的温度设置成为12位,其实DS18B20的数字温度可以设置成9、10、11和12位四种,其中一位为符号位。位数越多,精度或分辨率越高。当温度设置为9、10、11和12位时,温度的精确度分别为0.5?、0.25?、0.125?和0.0625?。在本设计中,要求温度显示精度为0.1?,所以只能选择使用12位温度设置才符合要求。图3-39是12位温度数据格式。 3210-1-2-3-4低位字节: 2 2 2 2 2 2 2 2 654高位字节: S S S S S 2 2 2 图3-39 12位温度数据格式 从图3-39看出,高八位温度数据的前五位S是符号位,S=1为负温度,后面的数据以补码形式存放。S=0为正温度。要想把温度数据以正确的形式显示出来,首先要判断符号位,如果是正温度,则要把有效温度数据11位进行拆分,把四位小数折分成一个字节,把七位整数部分折分成一个字节,然后再分别把整数或小数部分乘以适当的转换倍率,再进行BCD码转换,即可进行显示。如果是负温度,先进行取反加1,把11位有效温度数据取反加1,还原成绝对值。然后像正温度数据一样进行一系列变换。显示时,前面加“,”号即可。 接下来看看DS18B20的复位子程序。DS18B20的复位子程序在主程序中要调用多次,可以参看主程序流程图,所有的通讯都要先使DS18B20复位。要想编好这段程序,首先要对DS18B20的复位时序非常了解。通过查看DS18B20的使用手册,我们找到了它的复位时序,如图3-40所示。 在复位时序中,主机先通过单总线发出复位脉冲即低电平,最短保持480μs。然后主机释放总线,变为接收模式。当总线释放后,5kΩ的上拉电阻(Proteus仿真中不用,实际电路必须加,加在单总线和5V电源之间)把单总线拉高。当DS18B20检测到上升沿时,等待15~60μs,然后把单总线拉低60~240μs。 图3-40 DS18B20复位时序 第3章 HD44780液晶控制器显示系统设计 147 根据图3-40,编制DS18B20复位子程序如下: RESET: SETB DATE_LINE ;拉高单总线 NOP CLR DATE_LINE ;复位单总线 MOV R0,#6BH ;延时480μs以上 MOV R1,#04H TSR1: DJNZ R0,$ MOV R0,#6BH DJNZ R1,TSR1 SETB DATE_LINE ;然后拉高数据线(主机强制拉高) NOP NOP NOP MOV R0,#32H ;调整延时间常数,使延时为60μs TSR2: JNB DATE_LINE,TSR3 ;等待DS18B20回应,单总线为低转TSR3 DJNZ R0,TSR2 ;60μs未到,继续等待 JMP TSR4 ;延时60μs到时,未接到DS18B20回应,转TSR4 TSR3: SETB FLAG1 ;置标志位,表示DS1820存在 JMP TSR5 ;转TSR5 TSR4: CLR FLAG1 ;清标志位,表示DS1820不存在 JMP TSR7 ;转TSR7 TSR5: MOV R0,#06BH ;延时60~240μs TSR6: DJNZ R0,$ ;延时到,转TSR7 TSR7: SETB DATE_LINE ;拉高单总线,返回 RET (4)向DS18B20写一字节数据子程序 DS18B20的写时序分为两部分:写1时序和写0时序。总线控制器通过写1时 序写逻辑1到DS18B20,通过写0时序写逻辑0到DS18B20。所有写时序必须最少 Proteus显示控制系统设计与实例 148 持续60μs,包括两个写周期之间至少有1μs的恢复时间。当总线控制器把总线从逻辑高电平拉到逻辑低电平的时候,写时序开始。如图3-41所示。 图3-41 DS18B20的读、写时序 总线控制器要产生一个写时序,必须把总线拉到低电平然后释放,在写时序开始后的15μs释放总线。当总线被释放的时候,5kΩ的上拉电阻将拉高总线。总线要产生一个写0时序,必须把总线拉到低电平并持续保持至少60μs。 总线控制器初始化写时序后,DS18B20在一个15~60μs的时间内对I/O口采样,如果总线上是高电平就写1,如果总线上是低电平就写0。 下面是根据DS18B20的写时序编写的向DS18B20写入一个字节数据或命令子程序。 WRITE: MOV R2,#8 ;一共8位数据 CLR C ;清进位 WR1: CLR DATE_LINE ;开始写入DS18B20总线要处于复位(低)状态 MOV R3,#07 DJNZ R3,$ ;总线复位保持60μs以上 RRC A ;把一个字节分成8个位环移给C MOV DATE_LINE,C ;写入一个位 MOV R3,#3CH DJNZ R3,$ ;等待100μs 第3章 HD44780液晶控制器显示系统设计 149 SETB DATE_LINE ;重新释放总线 NOP DJNZ R2,WR1 ;写入下一个位 SETB DATE_LINE ;拉高总线 RET (5)从DS18B20读两个字节温度数据子程序 总线控制器发起读时序时,DS18B20仅被用来传输数据给控制器。因此,总线控制器在发出读暂存器指令(BEH)或读电源模式指令(B4H)后,必须立刻开始读时序,DS18bB20可以提供请求信息。除此之外,总线控制器在发出温度转换指令(44H)或召回EEPEOM指令(B8H)指令之后读时序。 所有读时序必须最少60μs,包括两个读周期至少1μs的恢复时间。当总线控制器把总线从高电平拉到低电平时,读时序开始,总线必须保持1μs,然后总线被释放,如图3-41所示。在总线控制器发出读时序后,DS18B20通过拉高或拉低总线来传输1或0。当传输逻辑0结束后,总线将被释放,通过上拉电阻回到上升沿状态。从DS18B20读出的数据在读时序的下降沿出现后15μs内有效。因此总线控制器在读时序开始后必须停止把I/O脚驱动为低电平15μs,以读取I/O状态。 下面是根据DS18B20的读时序编写的读温度数据子程序: READ: ;将温度数据低八位、高八位从DS18B20中读出 MOV R4,#2 ;读节数 MOV R1,#TEMPL ;把实时温度低八位存储单元25H给R1 RE00: MOV R2,#8 ;每字节位数 RE01: CLR CY ;清进位 SETB DATE_LINE ;拉高总线 NOP ;延时 NOP CLR DATE_LINE ;读数据前,总线保持为低 NOP ;延时 NOP NOP SETB DATE_LINE ;开始读,总线释放 MOV R3,#09 ;延时18微妙 DJNZ R3,$ MOV C,DATE_LINE ;从DS18B20总线读一个位 MOV R3,#3CH Proteus显示控制系统设计与实例 150 DJNZ R3,$ ;等待100微妙 RRC A ;把读到的位值环移给A DJNZ R2,RE01 ;读下一个位 MOV @R1,A ;读到一个字节存入R1指定的内存中去 INC R1 ;存储地址加1 DJNZ R4,RE00 ;两个字节读完返回,未读完转RE00 RET 以上简单介绍了系统基本子程序的编程思路和程序,以下面对系统主要的几个子程序进行重点介绍。 在主程序中,温度数据的转换、显示子程序是最关键的部分。大家在阅读后面的系统程序时,会发现有一个子程序START3被反复调用。其实,这个子程序是一个子程序集,只要有键按下,温度就开始转换,然后执行以下部分子程序即可: START3: CALL CONVTEMP ; 温度转换子程序 CALL DISPBCD ;BCD码转换子程序 CALL TEMP_COMP ;温度比较及结果显示子程序 CALL TEMP_BJ ;显示温度标记子程序 CALL LCD_DISP ;显示温度数据子程序 其中,子程序TEMP_BJ前面已经介绍过了,下面着重介绍其它四个子程序。 (1)温度转换子程序CONVTEMP 该子程序对从DS18B20读出的两字节初始温度进行一系列转换,对负温度进行求补转换成绝对值,并设负温度标志位FLAG2为1,然后高、低字节分别存入TEMP_H和TEMP_L。接下来完成以下两项任务:?把两个字节的温度值拆分组合成一个字节的二进制数并存入TEMP_ZH,高位为符号位,其余七位为绝对值,以备在温度比较及结果显示子程序中使用。?把两个字节的温度值拆分组合成两个字节的BCD码,并存入TEMPHC和TEMPLC,TEMPHC中存放的是百位和十位,TEMPLC中存放的是个位和小数位。程序流程如图3-42所示。 整数部分的十六进制(或二进制)转换为BCD码是调用了一个比较简单的子程序HEX2BCD1。把一个字节的二进制数除以100(64H),商为百位上的BCD码;余数除以10(0AH),商为十位上的BCD码,余数为个位上的BCD码。具体程序如下: HEX2BCD1: ;十六进制转BCD码 MOV B,#064H ;100送入B DIV AB ;十六进制温度A?100 MOV R4,A ;商A存入R4,即百位数BCD码 MOV A,#0AH ;10送入A 第3章 HD44780液晶控制器显示系统设计 151 XCH A,B ;A、B交换 DIV AB ;余数?10 SWAP A ;商A的高低四位交换 ORL A,B ;然后和余数相或,即A中高四位为十位BCD码,低四位为个位BCD码 RET N温度值为负值, Y 双字节求补 FLAG2=1 二进制小数转换成 BCD码 取出二进制整数部分 和符号 组合成一个字节并 存入TEMP_ZH 调整数部分BCD码转 换子程序 把百位和十位BCD码 存入TEMPHC 把个位和小数BCD码 存入TEMPLC 返回 图3-42 温度转换子程序流程图 小数部分转换成BCD码是利用查表法得到的,在主程序中放置了一个一位小数BCD码数据块如下: TEMPDOTTAB: DB 00H,00H,01H,01H,02H,03H,03H,04H DB 05H,05H,06H,06H,07H,08H,08H,09H 根据设计任务要求,温度要求精确到0.1?,所以这16个BCD码是小数点后的第一位,分别对应于四位二进制小数的0000~1111。因为系统选择为12位温度数 -4-1值,温度分辨率0001对应于2?,即0.0625?,四位二进制小数的权值分别为2 -2-3-4(0.5)、2(0.25)、2(0.125)和2(0.0625)。根据二进制转换成十进制的权值相加方法,求出0000~1111所对应的十进制数,然后取小数点后第一位数,舍去后面三位,即为以上数据块中的数据。这里没有采取四舍五入法。 Proteus显示控制系统设计与实例 152 具体转换如表3-6所示。 表3-6 小数二进制转换成BCD码对照表 二制制 十进制 小数位 ,,,,12242 2 2 2 0.5 0.25 0.125 0.0625 0 0 0 0 0 0 0 0 0 1 0.0625 0 0 0 1 0 0.125 1 0 0 1 1 0.1875 1 0 1 0 0 0.25 2 0 1 0 1 0.3125 3 0 1 1 0 0.375 3 0 1 1 1 0.4375 4 1 0 0 0 0.5 5 1 0 0 1 0.5625 5 1 0 1 0 0.625 6 1 0 1 1 0.6875 6 1 1 0 0 0.75 7 1 1 0 1 0.8125 8 1 1 1 0 0.875 8 1 1 1 1 0.9375 9 (2)BCD码转换子程序DISPBCD BCD转换子程序的任务是把温度转换子程序CONVTEMP中的两个字节组合BCD码,再进一步折分成四个字节的BCD码用于显示调用,分别为百位、十位、个位和小数位,并设灭零显示标志位FLAG3和FLAG4。正温度时,百位为零不显示,但如果百位为零时,十位也为零,则设标志位FLAG4=1,这两位都显示“空格”字符。负数时,因为最低为两位数,故十位上为0时,要和正数相区别,不能显示,即一律灭零,故设标志位FALG3=1。BCD码转换子程序流程序图如图3-43所示。 (3)温度比较及结果显示子程序TEMP_COMP 在这个子程序中,主要完成实际温度与程序中设定的上、下限报警温度的比较,并且把比较结果大于上限、小于下限及在上、下限范围内分别用符号“>”、“<”、和“~”表示。这些符号显示在温度数据小数点后第二个位置上。 程序按照报警上限设定值为正,报警下限设定值可为正也可为负的思路来设计。因为在比较实际温度与上、下限温度值时采用SUBB指令,有符号数相减会出错, 第3章 HD44780液晶控制器显示系统设计 153 影响比较结果。所以,用此指令之前,把实际温度和下限值都变成绝对值再执行SUBB指令就不会有差错了。首先在下限温度报警值设定时,采用标志位FLAG5来指明设定的下限报警值是正或是负,当FLAG5=1时,设定的值是负数的绝对值。 TEMPLC?A A“与”0FH,取出小数BCD码 小数BCD码?70H TEMPLC?A 交换A中高、低四位 A“与”0FH,取出个位BCD码 个位BCD码?71H TEMPLC?A A“与”0FH,取出十位BCD码 十位BCD码?72H TEMPLC?A 交换A中高、低四位 A“与”0FH,取出百位BCD码 百位BCD码?73H YFLAG2=1, NY百位=0, NNN十位=0,十位=0,YY FLAG4=1FALG3=1 返回 图3-43 BCD码转换子程序流程图 因为温度报警的上限值我们规定为正,所以可以直接用它减去实际温度就可得出谁大谁小的结论。 在实际温度和下限比较时,先通过判断实际温度为负标志位FLAG2(在温度转换子程序中置位)和负温度报警下限标志位FLAG5的四种状态,可以很方便地得出温度正常或温度小于下限的结论。如果实际温度和下限的符号不同,不用执行SUBB指令可以直接判断出结果;如果实际温度和下限的符号相同,即都为正或都 Proteus显示控制系统设计与实例 154 为负,需要执行SUBB指令。因相减的两个数都是正数,不会发生溢出等错误。如果两者都为负,用实际温度减去下限,有借位反而说明实际温度大于下限。详细的程序流程如图3-44所示。 把单字节符号值温度变为正 上限—实际温度绝对值 Y有借位, NYFLAG2=1, NNYFLAG5=1,FLAG5=1, NY 用实际温度绝对值—下限用实际温度绝对值—下限 NY有借位,有借位, NY 调显示“<”子程序调显示“~”子程序调显示“>”子程序 返回 图3-44温度比较及结果显示子程序流程图 标志位的作用非常大,也为程序设计带来了很大的方便,从这个子程序中可以略见一斑,在前面的灭零显示中我们也看到了灭零标志位的作用。它就像是一个记忆点,可以把前面程序中的各种运算或逻辑关系结果暂时记忆下来,需要时只需判断这个标志位的状态即可。大大简化了编程工作,使许多不能完成或非常复杂的程序得以实现和简化。 (4)显示温度数据子程序LCD_DISP 最后,我们介绍显示温度数据子程序LCD_DISP,这个子程序的功能是把温度数据的百位、十位、个位、小数点、小数点后的一位小数以及负号分别显示在LM016L的指定位置上。我们前面对LM016L的显示控制已经比较熟悉,按说编这个程序并不难,但由于要显示负号、还要进行灭零显示,所以程序还是稍有些复杂。不过在前面的子程序中,负温度及需要灭零显示的标志位都已设好。 关键的一点是,LM016L对动态数据的显示需要进行转换,即把要显示的BCD码加上30H后才能正常显示该数。这在3.3节中我们已经介绍过,在这里再强调一下,以便读者在阅读程序时加以注意。 温度数据在LM016L上的显示位置如图3-46所示。各位对应的LCD显存地址如表3-8所示。 第3章 HD44780液晶控制器显示系统设计 155 表3-8 温度数据的显存地址分配 百位或负号 十位 个位 小数点 小数 C6H C7H C8H C9H CAH 因为温度数据显示在LM016L的第二行,第二行首列的显存地址为C0H,程序 采用显存地址变量LCD_X来寻址,分别取6、7、8、9、A几个值,然后与C0H相 加得到百位、十位、个位、小数点及小数位的显存地址,然后把该显示的数据送入 即可。 该子程序的流程图如图3-45所示。 取出百位BCD码 LCD_X?6 YFLAG2=1, NY百位=0, N 在百位显示空格“ ”百位BCD码加#30H 百位送显存0C6H显示 取出十位BCD码 YFLAG3=1, NYFLAG4=1,N 十位BCD码加#30H在十位显示空格“ ” 十位送显存0C7H显示 取出个位BCD码 个位BCD码加#30H 个位送显存0C8H显示 小数点送0C9H显示 取出小数位BCD码 小数位BCD码加#30H 小数位送0CAH显示 FLAG2、3、4=0 返回 图3-45显示温度数据子程序流程图 Proteus显示控制系统设计与实例 156 4. 系统仿真结果 根据软件设计流程,结合DS18B20使用手册,在Keil中使用汇编语言进行系统编程及调试,最后生成正确的“*.hex”文件。在Proteus中,双击图3-19中的单片机AT89C51,把编译后的软件导入,运行仿真。先出现如图3-37所示的画面,表示DS18B20存在,系统正常运行。 停止仿真,断开单总线,再次运行仿真,出现如图3-38所示的画面,表示DS18B20不存在。 停止仿真,接好单总线,并按照前面介绍的方法把四个DS18B20的精度和ROM序列号设置好,再次运行仿真,重新出现如图3-37所示的画面。用鼠标调节四个DS18B20的温度,使有正有负,有超上限的,有超下限的。然后分别点击按键1、2、11VSSVSS22VDDVDD3和4,出现如图3-46所示的显示效果。 33VEEVEE在运行状态下,选中一个按键后,随意调节对应温度传感器的值,可以看到显44RSRS55RWRW示数据跟随变化。 66EELCD1LCD1LM016LLM016L77D0D088D1D199D2D21010D3D3111111D4D4VSSVSS121222D5D5VDDVDD131333D6D6VEEVEE1414D7D744RSRS55RWRW 66EELCD1LCD1LM016LLM016L77D0D088D1D199D2D21010D3D31111D4D41212D5D51313D6D61414D7D7 图3-46系统仿真结果 5. 源程序(汇编语言) TEMP_ZH DATA 24H ;处理后的八位符号值温度度存放单元 TEMPL DATA 25H ;实时温度低八位存放单元 TEMPH DATA 26H ;实时温度高八位存放单元 TEMP_TH DATA 27H ;高温报警值存放单元 TEMP_TL DATA 28H ;低温报警值存放单元 TEMPHC DATA 29H ;百位和十位BCD码存放单元 TEMPLC DATA 2AH ;个位和小数BCD码存放单元 第3章 HD44780液晶控制器显示系统设计 157 LCD_X EQU 2FH ;LCD 地址变量 LCD_RS EQU P1.0 ;LCD RS端 LCD_RW EQU P1.1 ;LCD RW端 LCD_EN EQU P1.2 ;LCD EN端 FLAG1 EQU 20H.0 ;DS18B20存在标志位 FLAG2 EQU 20H.2 ;负数标志位 FLAG3 EQU 20H.3 ;负数时,十位为零(灭0显示标志位) FLAG4 EQU 20H.4 ;正数时,百位、十位均为零(灭0显示标志位) FLAG5 EQU 20H.1 ;负温度下限标志位 FLAG6 EQU 21H.0 ;按键1操作标志位 FLAG7 EQU 21H.1 ;按键2操作标志位 FLAG8 EQU 21H.2 ;按键3操作标志位 FLAG9 EQU 21H.3 ;按键4操作标志位 DATE_LINE EQU P3.7 ;DS18B20总线 ;***************************************************** ORG 0000H JMP MAIN MAIN: MOV SP,#60H MOV A,#00H MOV R0,#20H ;将 20H-2FH 单元清零 MOV R1,#10H CLEAR: MOV @R0,A INC R0 DJNZ R1,CLEAR CALL SET_LCD CALL RE_18B20 MOV TEMP_TH,#50H ;设置温度上限报警值为80度 MOV TEMP_TL,#14H ;设置温度下限报警值为20度 SETB FLAG5 ;FLAG5=0正温度下限,FLAG5=1负温度下限 Proteus显示控制系统设计与实例 158 START: CALL RESET ;18B20复位子程序 JNB FLAG1,START1 ;DS1820不存在 CALL MENU_OK CALL READ_E2 ;温度报警值拷贝到暂存器 JMP START2 START1: CALL MENU_ERROR CALL TEMP_BJ ;显示温度标记 JMP $ START2: CALL RESET JNB FLAG1,START1 ;DS1820不存在 MOV A,#0CCH ;跳过ROM匹配 CALL WRITE MOV A,#44H ;发出温度转换命令 CALL WRITE ;************************************************ ;由单片机向单总线发送四个DS18B20的ROM序列号 CALL DELAY ;调延时子程序 LCALL RESET ;调DS18B20复位子程序 MOV A,#55H ;发出匹配ROM指令 LCALL WRITE ;设写命令子程序 MOV A,#28H ;由高到低向DS18B20送入64位序列号 LCALL WRITE MOV A,#24H LCALL WRITE MOV A,#0C5H LCALL WRITE MOV A,#39H LCALL WRITE MOV A,#00H 第3章 HD44780液晶控制器显示系统设计 159 LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#05FH LCALL WRITE MOV A,#0BEH ;发出读温度数据命令 LCALL WRITE LCALL READ ;读DS18B20的双字节温度 MOV 74H,TEMPL ;低字节存入74H MOV 75H,TEMPH ;高字节上入75H LCALL RESET ;调DS18B20复位子程序 MOV A,#55H LCALL WRITE MOV A,#28H LCALL WRITE MOV A,#30H LCALL WRITE MOV A,#0C5H LCALL WRITE MOV A,#0B8H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#08EH LCALL WRITE MOV A,#0BEH LCALL WRITE LCALL READ Proteus显示控制系统设计与实例 160 MOV 76H,TEMPL MOV 77H,TEMPH LCALL RESET MOV A,#55H LCALL WRITE MOV A,#28H LCALL WRITE MOV A,#31H LCALL WRITE MOV A,#0C5H LCALL WRITE MOV A,#0B8H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#0B9H LCALL WRITE MOV A,#0BEH LCALL WRITE LCALL READ MOV 78H,TEMPL MOV 79H,TEMPH LCALL RESET MOV A,#55H LCALL WRITE MOV A,#28H LCALL WRITE MOV A,#32H 第3章 HD44780液晶控制器显示系统设计 161 LCALL WRITE MOV A,#0C5H LCALL WRITE MOV A,#0B8H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#00H LCALL WRITE MOV A,#0E0H LCALL WRITE MOV A,#0BEH LCALL WRITE LCALL READ MOV 7AH,TEMPL MOV 7BH,TEMPH LCALL RESET ;***************************** ;2*2键盘查询和标志位设定 ;***************************** SMKEY: MOV P2,#030H MOV A,P2 ANL A,#0F0H CJNE A,#030H,HKEY SJMP J_00 HKEY: CALL CLR_2LINE ;先对LCD第二行进行清屏 LCALL DELAY10 MOV A,P2 ANL A,#0F0H MOV B,A Proteus显示控制系统设计与实例 162 CJNE A,#030H,WKEY SJMP J_00 WKEY: MOV P2,#03H MOV A,P2 ANL A,#0FH ORL A,B JB ACC.0,BANWE4 JMP BANWE5 BANWE4: JB ACC.4,XUANZE4 JMP XUANZE3 BANWE5: JB ACC.5, XUANZE1 JMP XUANZE2 ;*************************** JMP J_00 XUANZE1: ;#1键按下 SETB FLAG6 CLR FLAG7 CLR FLAG8 CLR FLAG9 JMP J_00 XUANZE2: ;#2键按下 SETB FLAG7 CLR FLAG6 CLR FLAG8 CLR FLAG9 JMP J_00 XUANZE3: ;#3键按下 第3章 HD44780液晶控制器显示系统设计 163 SETB FLAG8 CLR FLAG7 CLR FLAG6 CLR FLAG9 JMP J_00 XUANZE4: ;#4键按下 SETB FLAG9 CLR FLAG7 CLR FLAG8 CLR FLAG6 J_00:NOP JB FLAG6 ,TEMPH11 JB FLAG7 ,TEMPH22 JB FLAG8 ,TEMPH33 JB FLAG9 ,TEMPH44 JMP ST_00 ;************************************ TEMPH11: MOV DPTR,#T_1 ;指针指到显示消息“TEMP:” MOV A,#2 ;显示在第二行 CALL LCD_PRINT ;调字符串显示子程序 MOV TEMPL,74H ;把从DS18B20读出的初始温度低八位送TEMPL MOV TEMPH,75H ;把从DS18B20读出的初始温度高八位送TEMPH LCALL START3 ;调温度转换、显示子程序 JMP ST_00 ;回到START2,重新发出温度转换命令 TEMPH22: MOV DPTR,#T_2 ;指针指到显示消息“TEMP:” MOV A,#2 ;显示在第二行 CALL LCD_PRINT MOV TEMPL,76H MOV TEMPH,77H LCALL START3 JMP ST_00 Proteus显示控制系统设计与实例 164 TEMPH33: MOV DPTR,#T_3 ;指针指到显示消息“TEMP:” MOV A,#2 ;显示在第二行 CALL LCD_PRINT MOV TEMPL,78H MOV TEMPH,79H LCALL START3 JMP ST_00 TEMPH44: MOV DPTR,#T_4 ;指针指到显示消息“TEMP:” MOV A,#2 ;显示在第二行 CALL LCD_PRINT MOV TEMPL,7AH MOV TEMPH,7BH LCALL START3 JMP ST_00 ST_00: JMP START2 ;**************************温度处理、转换、比较、显示 START3: CALL CONVTEMP ;把从DS18B20读到的初始温度转换组合成两个字节的BCD码 CALL DISPBCD ;把温度折分成单个BCD码并设灭零显示标志位 CALL TEMP_COMP ;显示温度比较结果符号 CALL TEMP_BJ ;显示温度标记 CALL LCD_DISP ;显示温度百位、十位、个位、小数点及小数位还有符号 RET ;***************************************; SET_LCD: ;对 LCD 做初始化设置及测试 CLR LCD_EN CALL INIT_LCD ;初始化 LCD 第3章 HD44780液晶控制器显示系统设计 165 CALL STORE_DATA ;将自定义字符存入LCD的CGRAM RET INIT_LCD: ;8位I/O控制 LCD 接口初始化 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#0EH CALL WCOM CALL DELAY1 MOV A,#38H ;双列显示,字形5*7点阵 CALL WCOM CALL DELAY1 MOV A,#0CH ;开显示,显示光标,光标不闪烁 CALL WCOM CALL DELAY1 MOV A,#01H ;清除 LCD 显示屏 CALL WCOM CALL DELAY1 RET ;**************************************************** WCOM: ;以8位控制方式将命令写至LCD MOV P0,A ;写入命令 CLR LCD_RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲 CLR LCD_RW SETB LCD_EN ACALL DELAY1 CLR LCD_EN RET ;**************************************************** WDATA: ;以8位控制方式将数据写至LCD MOV P0,A ;写入数据 SETB LCD_RS CLR LCD_RW Proteus显示控制系统设计与实例 166 SETB LCD_EN CALL DE CLR LCD_EN CALL DE RET DE: MOV R7,#250 DJNZ R7,$ RET ;***************************************************** DELAY: MOV R0,#100 DEL2: MOV R1,#100 DEL3: DJNZ R1,DEL3 DJNZ R0,DEL2 RET DELAY10: MOV R6,#20H Q6: MOV R5,#0BBH Q5: DJNZ R5,Q5 DJNZ R6,Q6 RET DELAY1: ;延时5MS MOV R6,#25 DL2:MOV R7,#100 DJNZ R7,$ DJNZ R6,DL2 RET ;**************************************************** STORE_DATA: 第3章 HD44780液晶控制器显示系统设计 167 MOV A,#40H CALL WCOM MOV R2,#08H MOV DPTR,#D_DATA MOV R3,#00H S_DATA: MOV A,R3 MOVC A,@A+DPTR CALL WDATA ;写入数据 INC R3 DJNZ R2,S_DATA RET ;**************************************************** D_DATA: DB 0CH,12H,12H,0CH,00H,00H,00H,00H ;******************************************************** RE_18B20: JB FLAG1,RE_18B20A RET RE_18B20A: CALL RESET MOV A,#0CCH ;跳过ROM匹配 LCALL WRITE MOV A,#4EH ;写暂存寄存器 LCALL WRITE MOV A,TEMP_TH ;TH(报警上限) LCALL WRITE MOV A,TEMP_TL ;TL(报警下限) LCALL WRITE MOV A,#7FH ;12位精确度 LCALL WRITE RET Proteus显示控制系统设计与实例 168 RESET: SETB DATE_LINE NOP CLR DATE_LINE MOV R0,#6BH ;主机发出延时复位低脉冲 MOV R1,#04H TSR1: DJNZ R0,$ MOV R0,#6BH DJNZ R1,TSR1 SETB DATE_LINE ;然后拉高数据线 NOP NOP NOP MOV R0,#32H TSR2: JNB DATE_LINE,TSR3 ;等待DS18B20回应 DJNZ R0,TSR2 JMP TSR4 ;延时 TSR3: SETB FLAG1 ;置标志位,表示DS1820存在 JMP TSR5 TSR4: CLR FLAG1 ;清标志位,表示DS1820不存在 JMP TSR7 TSR5: MOV R0,#06BH TSR6: DJNZ R0,$ ;时序要求延时一段时间 TSR7: SETB DATE_LINE RET ;********************************************************* WRITE: MOV R2,#8 ;一共8位数据 第3章 HD44780液晶控制器显示系统设计 169 CLR C WR1: CLR DATE_LINE ;开始写入DS18B20总线要处于复位(低)状态 MOV R3,#07 DJNZ R3,$ ;总线复位保持16微妙以上 RRC A ;把一个字节DATA 分成8个BIT环移给C MOV DATE_LINE,C ;写入一个BIT MOV R3,#3CH DJNZ R3,$ ;等待100微妙 SETB DATE_LINE ;重新释放总线 NOP DJNZ R2,WR1 ;写入下一个BIT SETB DATE_LINE RET ;********************************************************* READ: MOV R4,#2 ;将温度低位、高位、TH、TL从DS18B20中读出 MOV R1,#TEMPL ;存入25H、26H、27H、28H RE00: MOV R2,#8 RE01: CLR CY SETB DATE_LINE NOP NOP CLR DATE_LINE ;读前总线保持为低 NOP NOP NOP SETB DATE_LINE ;开始读总线释放 MOV R3,#09 ;延时18微妙 DJNZ R3,$ MOV C,DATE_LINE ;从DS18B20总线读得一个BIT MOV R3,#3CH Proteus显示控制系统设计与实例 170 DJNZ R3,$ ;等待100微妙 RRC A ;把读得的位值环移给A DJNZ R2,RE01 ;读下一个BIT MOV @R1,A INC R1 DJNZ R4,RE00 RET ;********************************************************* MENU_OK: MOV DPTR,#M_OK1 ;指针指到显示消息 MOV A,#1 ;显示在第一行 CALL LCD_PRINT MOV DPTR,#M_OK2 ;指针指到显示消息 MOV A,#2 ;显示在第一行 CALL LCD_PRINT RET ;**************************************************** T_1: DB "TEMP1:",0 T_2: DB "TEMP2:",0 T_3: DB "TEMP3:",0 T_4: DB "TEMP4:",0 M_OK1: DB "ZHU Qing Hui ",0 M_OK2: DB "Nan Yang Li Gong",0 M2_LINE: DB " ",0 第3章 HD44780液晶控制器显示系统设计 171 ;***************************************************** CLR_2LINE: ;显示实时温度前,先对第二屏进行清屏 MOV DPTR,#M2_LINE CALL LINE2 RET ;***************************************************** LCD_PRINT: ;在LCD的第一行或第二行显示字符 CJNE A,#1,LINE2 ;判断是否为第一行 LINE1: MOV A,#80H ;设置 LCD 的第一行地址 CALL WCOM ;写入命令 JMP FILL LINE2: MOV A,#0C0H ;设置 LCD 的第二行地址 CALL WCOM FILL:CLR A ;填入字符 MOVC A,@A+DPTR ;由消息区取出字符 CJNE A,#0,LC1 ;判断是否为结束码 RET LC1:CALL WDATA ;写入数据 INC DPTR ;指针加1 JMP FILL ;继续填入字符 RET ;************************************************************* READ_E2: CALL RESET MOV A,#0CCH ;跳过ROM匹配 LCALL WRITE MOV A,#0B8H ;把EEPROM里的温度报警值拷贝回暂存器 CALL WRITE RET ;****************************************************************** Proteus显示控制系统设计与实例 172 TEMP_BJ: MOV A,#0CBH CALL WCOM MOV DPTR,#BJ1 ;指针指到显示消息 MOV R1,#0 MOV R0,#2 BBJJ1: MOV A,R1 MOVC A,@A+DPTR CALL WDATA INC R1 DJNZ R0,BBJJ1 RET ;**************************************************** BJ1: DB 00H,"C" ;******************************************** MENU_ERROR: MOV DPTR,#M_ERROR1 ;指针指到显示消息1 MOV A,#1 ;显示在第一行 CALL LCD_PRINT MOV DPTR,#M_ERROR2 ;指针指到显示消息1 MOV A,#2 ;显示在第一行 CALL LCD_PRINT RET ;**************************************************** M_ERROR1: DB " DS18B20 ERROR ",0 M_ERROR2: DB " TEMP: ---- ",0 第3章 HD44780液晶控制器显示系统设计 173 ;************************************************************* CONVTEMP: MOV A,TEMPH ;判温度是否零下 ANL A,#80H JZ TEMPC11 ;温度零上转TEMPC11 CLR C ;温度零下,清进位 MOV A,TEMPL ;低字节送累加器 CPL A ;取反 ADD A,#01H ;加1 MOV TEMPL,A ;求补后,低字节送入TEMPL MOV A,TEMPH ;高字节送累加器 CPL A ;取反 ADDC A,#00H ;加低字节取反加1后的进位 MOV TEMPH,A ;求补后,高字节存入TEMPH SETB FLAG2 ;负数标志位置1 TEMPC11: ;正、负数公共处理程序 MOV A,TEMPL ;温度值低八位送入累加器 ANL A,#0FH ;屏蔽高四位,只留小数位 MOV DPTR,#TEMPDOTTAB ;小数部分BCD码转换表首地址送数据指针 MOVC A,@A+DPTR ;查表 MOV TEMPLC,A ;TEMPLC的低四位为小数部分转换后的BCD码 MOV A,TEMPL ;温度值低字节送累加器 ANL A,#0F0H ;取出高四位 SWAP A ;把高四位交换到低四位中去 MOV TEMPL,A ;再存入TEMPL MOV A,TEMPH ;温度值高字节送累加器 ANL A,#0FH ;取出低四位 SWAP A ;交换高低四位 ORL A,TEMPL ;重新组合为一个字节带符号的温度值Sxxx,xxxx MOV TEMP_ZH,A ;温度的符号值存入TEMP_ZH LCALL HEX2BCD1 ;调温度的符号值转换成个、十、百位BCD码子程序 MOV TEMPL,A ;把转换后的个位和十位BCD码送入TEMPL ANL A,#0F0H ;取出高四位即十位BCD码 SWAP A ;把十位BCD码交换到低四位 MOV TEMPHC,A ;十位BCD码存入TEMPHC MOV A,TEMPL ;把转换后的个位和十位BCD码送入A Proteus显示控制系统设计与实例 174 ANL A,#0FH ;取出低四位即个位BCD码 SWAP A ;把低四位交换到高四位 ORL A,TEMPLC ;和小数BCD码重新组合成一个字节 MOV TEMPLC,A ;存入TEMPLC MOV A,R4 ;取出百位BCD码 JZ TEMPC12 ;如果A为0,即百位为零,程序返回 ANL A,#0FH ;如果百位不为0,取出百位BCD码 SWAP A ;把百位BCD码交换到A的高四位 MOV R4,A ;转换成xxxx0000后再存入R4 MOV A,TEMPHC ;取出带显示符号的十位BCD码到A ANL A,#0FH ;取出十位BCD码 ORL A,R4 ;和百位BCD码整合成一个字节 MOV TEMPHC,A ;存入TEMPHC TEMPC12: RET ;**************************************************** HEX2BCD1: ;十六进制-> BCD MOV B,#064H ;100送入B DIV AB ;符号值温度A?100 MOV R4,A ;商A存入R4,即百位数BCD码 MOV A,#0AH ;10送入A XCH A,B ;A、B交换 DIV AB ;余数?10 SWAP A ;商A的高低四位交换 ORL A,B ;然后和余数相或,即A中高四位为十位BCD码,低四位为个位BCD码 RET ;**************************************************** ; 小数部分码表 ;**************************************************** TEMPDOTTAB: DB 00H,00H,01H,01H,02H,03H,03H,04H DB 05H,05H,06H,06H,07H,08H,08H,09H 第3章 HD44780液晶控制器显示系统设计 175 ;**************************************************** DISPBCD: ;把温度数据折分成四个BCD码 MOV A,TEMPLC ;把个位和小数位BCD码取出到A ANL A,#0FH ;取出小数BCD码, MOV 70H,A ;把小数BCD码0000xxxx存入70H MOV A,TEMPLC ;把个位和小数位BCD码取出到A SWAP A ;把个位BCD码交换到低四位 ANL A,#0FH ;取出低四位 MOV 71H,A ;把个位BCD码0000xxxx存入71H MOV A,TEMPHC ;取出百位和十位BCD码到A ANL A,#0FH ;取出十位BCD码 MOV 72H,A ;把十位BCD码0000xxxx存入72H MOV A,TEMPHC ;取出百位和十位BCD码到A SWAP A ;把进位BCD码交换到低四位 ANL A,#0FH ;取出百位BCD码 MOV 73H,A ;把百位BCD码0000xxxx存入73H JB FLAG2,DISPBCD1 ;负数标志位为1,转DISPBCD1 MOV A,TEMPHC ;正数,则取出百位和十位到A ANL A,#0F0H ;取出百位 CJNE A,#010H,DISPBCD2;百位不等1(百位只可能为0和1)转DSAPBCD2 JMP DISPBCD0 ;百位为1转DISIPBCD0 DISPBCD1: ;负数时,十位为0设标志位,此0不必显示 MOV A,TEMPHC ;取出百位和十位 ANL A,#0FH ;取出十位 CJNE A,#00H,DISPBCD3 ;判断十位不为0,转DISPBCD3 SETB FLAG3 ;十位为0,设flag3为1(灭零标志位) DISPBCD3: JMP DISPBCD0 ;返回 DISPBCD2: ;百位为零时,判断十位是否也为0,是,则两个0均不必显示 MOV A,TEMPHC ;取出百位和十位 ANL A,#0FH ;取出十位 CJNE A,#00H,DISPBCD0 ;十位不为零,返回 Proteus显示控制系统设计与实例 176 SETB FLAG4 ;十位为零,flag4为1(百位为0十位为0标志位) DISPBCD0: RET ;**************************************************** ; 温度数据送LCD 1602 显示子程序 ;**************************************************** LCD_DISP: MOV A,73H ;取出百位BCD码 MOV LCD_X,#6 ;设LCD显示RAM地址变量为6 JB FLAG2,CON0 ;判断温度为负数,转CON0 CJNE A,#01H,CON1 ;温度为正,则继续判断百位等0,转CON1 JMP CONV2 ;正温度,百位为1转CONV2 CON0: MOV A,#"-" ;送负号到A MOV B,LCD_X ;送LCD显示RAM地址变量到B CALL LCDP2 ;把负号显示到第二行第七列 JMP CONV3 ;跳转到CONV3 CON1: MOV A," " MOV B,LCD_X CALL LCDP2 JMP CONV3 CONV2: CALL SHOW_DIG2 CONV3: INC LCD_X ;LCD显存地址变量加1,指向十位显示位置 MOV A,72H ;取出十位BCD码 JB FLAG3,CON2 ;是负数且十位为零,转CON2 JB FLAG4,CON2 ;是正数且百位和十位皆为0,也转CON2 JMP CONV4 ;是正数,百位和十位不都为0,转CONV4 CON2: MOV A,#" " ;十位显示空格 MOV B,LCD_X CALL LCDP2 第3章 HD44780液晶控制器显示系统设计 177 JMP CONV5 ;转到CONV5 CONV4: CALL SHOW_DIG2 ;调加显示转换代码子程序 CONV5: INC LCD_X ;LCD显存地址变量加1,指向个位显示位置 MOV A,71H ;取出个位BCD码 CALL SHOW_DIG2 ;调加显示转换代码子程序 INC LCD_X ;LCD显存地址变量加1,指向小数点显示位置 MOV A,#"." ;显示小数点 MOV B,LCD_X CALL LCDP2 MOV A,70H ;取出一位小数BCD码 INC LCD_X ;LCD显存地址变量加1,指向小数点后第一位显示位置 CALL SHOW_DIG2 ;调加显示转换代码子程序 CLR FLAG2 ;清负温度标志位 CLR FLAG3 ;清灭零显示标志位 CLR FLAG4 ;清灭零显示标志位 RET ;**************************************************** SHOW_DIG2: ;把要显示的BCD码加显示转换代码30H ADD A,#30H MOV B,LCD_X CALL LCDP2 RET ;**************************************************** LCDP2: ;在LCD的第二行显示字符 PUSH ACC ;把累加器的值压入堆栈保存 MOV A,B ;设置显示地址 ADD A,#0C0H ;设置LCD的第二行地址第X位置 CALL WCOM ;写入显存地址 POP ACC ;由堆栈取出A CALL WDATA ;写入数据A RET ;**************************************************** Proteus显示控制系统设计与实例 178 ;实际温度值与上、下限温度值比较并显示比较结果子程序 ;**************************************************** TEMP_COMP: MOV A,TEMP_ZH ANL A,#7FH MOV TEMP_ZH,A ;把符号值温度的符号去掉 MOV A,TEMP_TH ;温度上限报警值送A CLR C ;清进位 SUBB A,TEMP_ZH ;上限-实际温度 JC CHULI1 ;温度值大于上限,转CHULT1 ;温度值小于等上限,进行如下处理 JB FLAG2,CHULI3 ;实际温度为负,转CHULI3 JB FLAG5,CHULI ;实际温度为正,下限为负,转CHULI JMP CHULI5 ;两者都为正,转CHULI5 CHULI: MOV DPTR,#BJ5 ;温度值在正常范围,则赋数据指针 CALL TEMP_BJ3 ;调显示“~”子程序 CHULI0: RET ;返回 CHULI1: CLR C ;清借位 MOV DPTR,#BJ3 CALL TEMP_BJ3 ;显示”>“ JMP CHULI0 CHULI2: CLR C MOV DPTR,#BJ4 ;显示“<“ CALL TEMP_BJ3 JMP CHULI0 CHULI3: JB FLAG5,CHULI4 ;实际温度和下限都为负,转CHULI4 JMP CHULI2 ;实际温度为负,下限为正,转小于下限CHULI2 CHULI4: ;实际温度和下限都为负 ACALL CHULI6 JC CHULI ;绝对值相减,有借位,说明实际温度高于下限 JMP CHULI2 ;无借位,说明实际温度小于下限 第3章 HD44780液晶控制器显示系统设计 179 CHULI5: ;实际温度和下限都为正 ACALL CHULI6 JC CHULI2 JMP CHULI CHULI6: CLR C MOV A,TEMP_ZH SUBB A,TEMP_TL RET ;**************************************************** TEMP_BJ3: MOV A,#0CEH ;比较结果符号显示位显存地址 CALL WCOM MOV R1,#0 ;偏址指针 MOV R0,#2 ;字符个数 BBJJ3: MOV A,R1 MOVC A,@A+DPTR CALL WDATA ;显示一个符号 INC R1 ;显示第二个符号 DJNZ R0,BBJJ3 RET ;显示完毕,返回 ;**************************************************** BJ3: DB ">H" BJ4: DB "
本文档为【HD44780液晶控制器显示系统设计&#46;doc】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_713593
暂无简介~
格式:doc
大小:559KB
软件:Word
页数:119
分类:生活休闲
上传时间:2017-09-28
浏览量:70