用LCD1602实现简单的数字时钟
摘要:随着科技的发展,单片机的应用正在不断深入,涉及到日常生活的方方面面。本设计是基于单片机89C51为控制核心,以液晶为显示的数字时钟。本数字时钟设计
的原理相对简单,所以硬件电路也相对简单,难点和重点主要放在C语言的编程上,使用到定时器的子程序、延时程序、时分秒的控制程序、液晶模块和单片机模块的初始化程序、液晶显示的程序等,各个函数交叉调用,配合主程序的运行。
关键字:LCD1602 89C51 定时器
一、数字时钟的概述与功能的简介
本设计用到单片机的P0端做数据端,把数据发送到LCD的数据接收端,然后通过利用程序进行对液晶的控制,实现数字的显示。在本设计中,设计了四个功能按键,分别是启动/停止时钟,时、分、秒的加一功能,以此对时间的调整。硬件电路相对简单,所以软件的开销相对增大,特别是对液晶模块的程序设计,也正是设计本数字时钟的目的,希望通过此设计提高自己的软件编程与调试能力。由于个人能力也有限,在短时间内不能编写出用液晶显示年月日的程序,因为代码量确实增大不少。
二、89C51单片机的简介
1. 单片机的概述
所谓单片机,通俗的来讲,就是把中央处理器CPU(Central Processing Unit),存储器(memory),定时器,I/O(Input/Output)接口电路等一些计算机的主要功能部件集成在一块集成电路芯片上的微型计算机。单片机又称为“微控制器MCU”。中文“单片机”的称呼是由英文名称“Single Chip Microcomputer”直接翻译而来的。
2.芯片引脚图的介绍 芯片的引脚图如下:
1
引脚功能: I/O接口
MCS-51是标准的40引脚双列直插式集成电路芯片,引脚分布请参照----单片机引脚图: P0.0~P0.7 P0口8位双向口线(在引脚的39~32号端子)。 P1.0~P1.7 P1口8位双向口线(在引脚的1~8号端子)。 P2.0~P2.7 P2口8位双向口线(在引脚的21~28号端子)。 P3.0~P3.7 P2口8位双向口线(在引脚的10~17号端子)。 P0口有三个功能:
1、外部扩展存储器时,当做数据总线(如图1中的D0~D7为数据总线接口) 2、外部扩展存储器时,当作地址总线(如图1中的A0~A7为地址总线接口)
3、不扩展时,可做一般的I/O使用,但内部无上拉电阻,作为输入或输出时应在外部接上拉电阻。
P1口只做I/O口使用:其内部有上拉电阻。 P2口有两个功能:
1、扩展外部存储器时,当作地址总线使用 2、做一般I/O口使用,其内部有上拉电阻; P3口有两个功能:
除了作为I/O使用外(其内部有上拉电阻),还有一些特殊功能,由特殊寄存器来设置。
ALE/PROG 地址锁存控制信号
在系统扩展时,ALE用于控制把P0口的输出低8位地址送锁存器锁存起来,以实现低位地址和数据的隔离。ALE有可能是高电平也有可能是低电平,当ALE是高电平时,允许地址锁存信号,当访问外部存储器时,ALE信号负跳变(即由正变负)将P0口上低8位地址信号送入锁存器。当ALE是低电平时,P0口上的内容和锁存器输出一致。 在没有访问外部存储器期间,ALE以1/6振荡周期频率输出(即6分频),当访问外部存储器以1/12振荡周期输出(12分频)。
PROG为编程脉冲的输入端
程序通过编程脉冲输入才能写进去的,这个脉冲的输入端口就是PROG。
PSEN为外部程序存储器读选通信号
在读外部ROM时PSEN低电平有效,以实现外部ROM单元的读操作。
RST 复位信号
当输入的信号连续2个机器周期以上高电平时即为有效,用以完成单片机的复位初始化操作,当复位后程序计数器PC=0000H,即复位后将从程序存储器的0000H单元读取第一条指令码。
XTAL1和XTAL2
外接晶振引脚。当使用芯片内部时钟时,此二引脚用于外接石英晶体和微调电容;当使用外部时钟时,用于接外部时钟脉冲信号。
VCC:电源+5V输入
2
VSS:GND接地。
三、89C51单片机结构
1、总体结构
结构框图如下:
中央处理器(CPU)
MCS-51的CPU能处理8位二进制数或代码。CPU是单片机的主要核心部件,在CPU里面包含了运算器、控制器以及若干寄存器等部件给成。
总线
指能为多个部件服务的信息传送线,在微机系统中各个部件通过总线相互通信。
地址总线(AB):地址总线是单向的,用于传送地址信息。地址总线的宽度为16位,因此基外部存储器直接寻址64K,16位地址总线由P0口经地址锁存器提供低8位地址(A0~A7),P2口直接提供高8位地址(A8~A15)。
数据总线(DB):一般为双向,用于CPU与存储器,CPU与外设、或外设与外设之间传送数据信息(包括实际意义的数据和指令码)。数据总线宽度为8位,由P0口提供。
控制总线(CB):是计算机系统中所有控制信号的总称,在控制总线中传送的是控制信息。由P3口的第二功能状态和4根独立的控制总线,RESET、EA、ALE、PSEN组成。
存储器
用来存放计算机中的所有信息:包括程序、原始数据、运算的中间结果及最终结果等。 只读存储器(ROM):
3
只读存储器在使用时,只能读出而不能写入,断电后ROM中的信息不会丢失。因此一般用来存放一些固定程序,如监控程序、子程序、字库及数据表等。内部程序存储器(ROM): MCS-51内部有4KB/8KB字节的ROM(51系列为4KB,51系列为8KB),用于存放程序、原始数据或表格。因此称之为程序存储器,简称内部RAM。地址范围为0000H~FFFFH(64KB)。
随机存储器(RAM):
这种存储器又叫读写存储器。它不仅能读取存放在存储单元中的数据,还能随时写入新的数据,写入后原来的数据就丢失了。断电后RAM中的信息全部丢失。因些,RAM常用于存放经常要改变的程序或中间计算结果等信息。内部数据存储器(RAM):MCS-51单片机芯片共有256个RAM单元,其中后128单元被专用寄存器占用(稍后我们详解),能作为寄存器供用户使用的只是前128单元,用于存放可读写的数据。因此通常所说的内部数据存储器就是指前128单元,简称内部RAM。地址范围为00H~FFH(256B)。是一个多用多功能数据存储器,有数据存储、通用工作寄存器、堆栈、位地址等空间。
定时器/计数器
80C51单片机内部设有两个16位的可编程定时器/计数器。可编程的意思是指其功能(如工作方式、定时时间、量程、启动方式等)均可由指令来确定和改变。在定时器/计数器中除了有两个16位的计数器之外,还有两个特殊功能寄存器(控制寄存器和方式寄存器)。 定时器/计数器的结构:
中断系统
8051单片机的中断系统简单实用,其基本特点是:有5个固定的可屏蔽中断源,3个在片内,2个在片外,它们在程序存储器中各有固定的中断入口地址,由此进入中断服务程序;5个中断源有两级中断优先级,可形成中断嵌套;2个特殊功能寄存器用于中断控制和条件设置的 编程。 中断系统的结构:
5个中断源的符号、名称及产生的条件如下。
INT0:外部中断0,由P3.2端口线引入,低电平或下跳沿引起。 INT1:外部中断1,由P3.3端口线引入,低电平或下跳沿引起。 T0:定时器/计数器0中断,由T0计满回零引起。 T1:定时器/计数器l中断,由T1计满回零引起。
TI/RI:串行I/O中断,串行端口完成一帧字符发送/接收后引起。
2.定时器/计数器中相关寄存器的设置
定时计数器的原理:
16位的定时器/计数器实质上就是一个加1计数器,其控制电路受软件控制、切换。 当定时器/计数器为定时工作方式时,计数器的加1信号由振荡器的12分频信号产生,即每过一个机器周期,计数器加1,直至计满溢出为止。显然,定时器的定时时间与系统的振荡频率有关。因一个机器周期等于12个振荡周期,所以计数频率fcount=1/12osc。
这是最短的定时周期。若要延长定时时间,则需要改变定时器的初值,并要适当选择定
4
时器的长度(如8位、13位、16位等)。
当定时器/计数器为计数工作方式时,通过引脚T0和T1对外部信号计数,外部脉冲的下降沿将触发计数。计数器在每个机器周期的S5P2期间采样引脚输入电平。若一个机器周期采样值为1,下一个机器周期采样值为0,则计数器加1。此后的机器周期S3P1期间,新的计数值装入计数器。所以检测一个由1至0的跳变需要两个机器周期,故外部事年的最高计数频率为振荡频率的1/24。例如,如果选用12MHz晶振,则最高计数频率为0.5MHz。虽然对外部输入信号的占空比无特殊要求,但为了确保某给定电平在变化前至少被采样一次,外部计数脉冲的高电平与低电平保持时间均需在一个机器周期以上。
当CPU用软件给定时器设置了某种工作方式之后,定时器就会按设定的工作方式独立运行,不再占用CPU的操作时间,除非定时器计满溢出,才可能中断CPU当前操作。CPU也可以重新设置定时器工作方式,以改变定时器的操作。由此可见,定时器是单片机中效率高而且工作灵活的部件。
综上所述,我们已知定时器/计数器是一种可编程部件,所以在定时器/计数器开始工作之前,CPU必须将一些命令(称为控制字)写入定时/计数器。将控制字写入定时/计数器的过程叫定时器/计数器初始化。在初始化过程中,要将工作方式控制字写入方式寄存器,工作状态字(或相关位)写入控制寄存器,赋定时/计数初值。下面我们就提出的控制字的格式及各位的主要功能与大家详细的讲解。
控制寄存器 定时器/计数器T0和T1有2个控制寄存器-TMOD和TCON,它们分别用来设置各个定时器/计数器的工作方式,选择定时或计数功能,控制启动运行,以及作为运行状态的标志等。其中,TCON寄存器中另有4位用于中断系统。
定时器/计数器方式寄存器TMOD
定时器方式控制寄存器TMOD在特殊功能寄存器中,字节地址为89H,无位地址。TMOD的格式如下图所示。
由图可见,TMOD的高4位用于T1,低4使用于T0,4种符号的含义如下:
GATE:门控制位。GATE和软件控制位TR、外部引脚信号INT的状态,共同控制定时器/计数器的打开或关闭。
C/T:定时器/计数器选择位。C/T=1,为计数器方式;C/T=0,为定时器方式。
M1M0:工作方式选择位,定时器/计数器的4种工作方式由M1M0设定。定时器/计数器方式控制寄存器TMOD不能进行位寻址,只能用字节传送指令设置定时器工作方式,低半
5
字节定义为定时器0,高半字节定义为定时器1。复位时,TMOD所有位均为0。
定时器/计数器控制寄存器TCON
TCON在特殊功能寄存器中,字节地址为88H,位地址(由低位到高位)为88H一8FH,由于有位地址,十分便于进行位操作。
TCON的作用是控制定时器的启、停,标志定时器溢出和中断情况。
TCON的格式如下图所示。其中,TFl,TRl,TF0和TR0位用于定时器/计数器;IEl,ITl,IE0和IT0位用于中断系统。
各位定义如下:
TF1:定时器1溢出标志位。当字时器1计满溢出时,由硬件使TF1置“1”,并且申请中断。进入中断服务程序后,由硬件自动清“0”,在查询方式下用软件清“0”。
TR1:定时器1运行控制位。由软件清“0”关闭定时器1。当GATE=1,且INT1为高电平时,TR1置“1”启动定时器1;当GATE=0,TR1置“1”启动定时器1。 TF0:定时器0溢出标志。其功能及操作情况同TF1。 TR0:定时器0运行控制位。其功能及操作情况同TR1。 IE1:外部中断1请求标志。
IT1:外部中断1触发方式选择位。 IE0:外部中断0请求标志。
IT0:外部中断0触发方式选择位。
TCON中低4位与中断有关。由于TCON是可以位寻址的,因而如果只清溢出或启动定时器工作,可以用位操作命令。
定时器/计数器的初始化:
由于定时器/计数器的功能是由软件编程确定的,所以一般在使用定时/计数器前都要对其进行初始化,使其按设定的功能工作。初始货的步骤一般如下: 1、确定工作方式(即对TMOD赋值);
2、预置定时或计数的初值(可直接将初值写入TH0、TL0或TH1、TL1); 3、根据需要开放定时器/计数器的中断(直接对IE位赋值);
4、启动定时器/计数器(若已规定用软件启动,则可把TR0或TR1置“1”;若已规定由外中断引脚电平启动,则需给外引脚步加启动电平。当实现了启动要求后,定时器即按规定的工作方式和初值开始计数或定时)。
3、中断系统的控制寄存器的设置
中断允许寄存器IE
在中断源与CPU之间有一级控制,类似开关,其中第一级为一个总开关,第二级为五个分开关,由IE控制。在MCS-51中断系统中,中断的允许或禁止是由片内可进行位寻址的8位中断允许寄存器IE来控制的。见下表
其中EA是总开关,如果它等于0,则所有中断都不允许。
6
ES-串行口中断允许 ET1-定时器1中断允许 EX1-外中断1中断允许。 ET0-定时器0中断允许 EX0-外中断0中断允许。
中断优先级寄存器IP
中断优先原则:(概括为四句话) 1、低级不打断高级 2、高级不睬低级 3、同级不能打断
4、同级、同时中断,事先约定。
四、系统硬件的设计
硬件电路整体说明:P0口做数据端,并接上上拉电阻,把数据直接送到LCD1602的数据接收端。S1为启动/停止计时按键,S2为秒数增加一的按键,S3为分钟数增加一的按键,S4为小时数增加一的按键,S5为复位按键。经典的复位电路与晶振电路的原理不再详细说明了。
LCD1602的说明:
1602LCD分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别,两者尺寸差别如下图10-54所示:
图10-54 1602LCD尺寸图
1602LCD主要技术参数: 显示容量:16×2个字符 芯片工作电压:4.5—5.5V 工作电流:2.0mA(5.0V)
7
模块最佳工作电压:5.0V 字符尺寸:2.95×4.35(W×H)mm 引脚功能说明 1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表10-13所示: 编号 1 2 3 4 5 6 7 8 符号 VSS VDD VL RS R/W E D0 D1 引脚说明 电源地 电源正极 液晶显示偏压 数据/命令选择 读/写选择 使能信号 数据 数据 编号 9 10 11 12 13 14 15 16 符号 D2 D3 D4 D5 D6 D7 BLA BLK 引脚说明 数据 数据 数据 数据 数据 数据 背光源正极 背光源负极 表10-13:引脚接口说明表 第1脚:VSS为地电源。 第2脚:VDD接5V正电源。 第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。 第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。 第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。 第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。 第7~14脚:D0~D7为8位双向数据线。 第15脚:背光源正极。 第16脚:背光源负极。 8
硬件连接原理图如下:
五、系统软件的编程设计
程序运行流程简图
9
开始 初始化 设定初值 定时50ms NO 20次 加一秒 NO
程序代码如下:
#include #define uchar unsigned char #define uint unsigned int uchar hour,min,sec,count,hour1,hour2, sec1,sec2,min1,min2,keystopc,temp; sbit keystop=P1^4; sbit keyh=P1^5; sbit keym=P1^6; sbit keys=P1^7; sbit lcden=P3^4; sbit lcdrs=P3^5; uchar code table[]={ '0','1','2','3','4','5','6','7','8','9',':'}; 60次 加一分钟 60次 NO 加一小时 24次 NO 小时清零 显示时间 结束 10 void init() { count=0; hour=23; min=59; sec=50; TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; ET0=1; EA=1; } void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void write_com(uchar com) { lcdrs=0; P0=com; delay(0); lcden=1; delay(0); lcden=0; } void write_data(uchar date) { lcdrs=1; P0=date; delay(1); lcden=1; delay(1); lcden=0; } void init_1602() { //定时器初始化 //延时程序 //初始化1602 11 lcden=0; write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); write_com(0x80); } void display(uchar hour1,uchar hour2,uchar min1,uchar min2,uchar sec1,uchar sec2) //显示程序 { init_1602(); //write_com_nextl(0x80+0x40+0x03); write_data(table[hour1]); write_data(table[hour2]); write_data(table[0x0a]); write_data(table[min1]); write_data(table[min2]); write_data(table[0x0a]); write_data(table[sec1]); write_data(table[sec2]); } void count0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; count++; if(count==20) { count=0; sec++; if(sec==60) { sec=0; min++; if(min==60) { min=0; hour++; if(hour==24) { hour=0; 12 } } } } } void main() { init(); while(1) { if(keystop==0) //检测是否停止键按下 { delay(10); if(keystop==0) { if(keystopc!=1) keystopc++; //按停止键的次数 else keystopc=0; while(keystop==0); //松手检测 delay(5); while(keystop==0); } switch(keystopc) { case 1:TR0=0;break; // 按键一次就停止计数 case 0:TR0=1;break; default:break; } } if(keyh==0) //实现小时加一 { delay(5); if(keyh==0) { if(hour!=23) hour++; else hour=0; } while(!keyh); 13 delay(5); while(!keyh); hour1=hour/10; //数据分离 hour2=hour%10; min1=min/10; min2=min%10; sec1=sec/10; sec2=sec%10; display(hour1,hour2,min1,min2,sec1,sec2); } if(keym==0) //实现分钟加一 { delay(5); if(keym==0) { if(min!=59) { min++; } else { min=0; } } while(!keym); //松手检测 delay(5); while(!keym); hour1=hour/10; hour2=hour%10; min1=min/10; min2=min%10; sec1=sec/10; sec2=sec%10; display(hour1,hour2,min1,min2,sec1,sec2); } if(keys==0) //实现秒加一 { delay(5); if(keys==0) { if(sec!=59) { 14 sec++; } else { sec=0; } } while(!keys); delay(5); while(!keys); hour1=hour/10; hour2=hour%10; min1=min/10; min2=min%10; sec1=sec/10; sec2=sec%10; display(hour1,hour2,min1,min2,sec1,sec2); } hour1=hour/10; hour2=hour%10; min1=min/10; min2=min%10; sec1=sec/10; sec2=sec%10; display(hour1,hour2,min1,min2,sec1,sec2); //一直显示时钟 } } 运行期间仿真图如下: 15 六、实验总结 通过这次创新设计,我学到了很多书本上没有的实际的知识,熟悉了一些元器件、芯片在工程中的灵活运用。在设计过程中,遇到过一些困难,通过上网和去图书馆查找资料解决。并且在网上搜集到了一些元器件及电路的相关资料对以后的学习及工作是很有帮助的。 其次是进一步熟练地掌握和运用了相关的专业软件,提高了我们自身的专业素质。这也是我们工科学生所必须掌握的基础技能。同时也深深的体会到,我们书本上所学的知识和实际的东西相差甚远,我们所不懂的知识还有很多,因此今后我们要更加注重实际方面的锻炼和运用。 16 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- sceh.cn 版权所有 湘ICP备2023017654号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务