基于AT89C51单片机的电子时钟设计毕业设计.docx
《基于AT89C51单片机的电子时钟设计毕业设计.docx》由会员分享,可在线阅读,更多相关《基于AT89C51单片机的电子时钟设计毕业设计.docx(28页珍藏版)》请在冰豆网上搜索。
基于AT89C51单片机的电子时钟设计毕业设计
基于AT89C51单片机的电子时钟设计
摘要:
本文介绍了AT89C51单片机控制162液晶显示屏的工作原理以及设计方法,利用ds1302芯片和162液晶屏以51单片机为主控芯片设计一个时钟电路,分为硬件设计与软件设计两个部分。
硬件设计主要是单片机、液晶和ds1302的接口设计;软件设计的主要部分是:
单片机的端口初始化以及ds1302初始化,液晶显示屏的初始化,单片机驱动液晶屏的显示。
关键词:
AT89C51单片机;162液晶显示屏;ds1302;LCD
1引言
液晶显示器以其微功耗、体积小、显示内容丰富、超薄轻巧等许多优点,在袖珍式仪表和低功耗应用系统中得到越来越广泛的应用。
本文中详细介绍了基于AT89C51单片机控制下的162液晶屏显示设计,此设计基于da1302的时钟电路方便实用,电路设计简单。
2硬件介绍
2.1、AT89C51简介
AT89C51是一种带4K字节FLASH存储器(FPEROM—FlashProgrammableandErasableReadOnlyMemory)的低电压、高性能CMOS8位微处理器,俗称单片机。
AT89C2051是一种带2K字节闪存可编程可擦除只读存储器的单片机。
单片机的可擦除只读存储器可以反复擦除1000次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C2051是它的一种精简版本。
AT89C单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
AT89C51提供以下标准功能:
4k字节Flash闪速存储器,128字节内部RAM,32个I/O口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。
空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。
掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
·与MCS-51兼容
·4K字节可编程闪烁存储器
寿命:
1000写/擦循环
数据保留时间:
10年
·全静态工作:
0Hz-24Hz
·三级程序存储器锁定
·128*8位内部RAM
·32可编程I/O线
·两个16位定时器/计数器
·5个中断源
·可编程串行通道
·低功耗的闲置和掉电模式
·片内振荡器和时钟电路
2.2162液晶显示屏介绍
HS162-4液晶模块是一种用5x7点阵图形来显示字符的液晶显示器,根据显示的容量可以分为1行16个字、2行16个字等。
2.2.1162液晶屏显示屏的引脚定义
首先,我们来看162的引脚定义,162的引脚是很整齐的SIP单列直插封装。
表1.2.1是液晶屏的引脚定义。
表2.2.1接口信号说明表
编号
符号
引脚说明
编号
符号
引脚说明
1
VSS
电源地
9
D2
Data1/0
2
VDD
电源正极
10
D3
Data1/0
3
VO
液晶显示偏压信号
11
D4
Data1/0
4
RS
数据命令/选择端(H/L)
12
D5
Data1/0
5
R/W
读/写信号(H/L)
13
D6
Data1/0
6
E
使能信号
14
D7
Data1/0
7
D0
Data1/0
15
LEDA
背光源正极
8
D1
Data1/0
16
LEDK
背光源
HS162-4采用标准的16脚接口,我们只需要关注一下几个管脚:
3脚:
VO,液晶屏显示偏压信号,用于调整液晶屏的显示对比度,一般会外界电位器用以调整偏压信号,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“阴影”,使用时可以通过一个10K的电位器调整对比度。
4脚:
RS,数据/命令选择端,即对寄存器进行选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
5脚:
R/W,读写选择端,高电平时进行读操作,低电平时进行写操作。
6脚:
E,使能信号,其实时162的逐句控制时钟信号,利用该信号的上升沿实现对液晶屏的数据传输。
7~14脚:
8位双向数据线。
2.2.2162液晶显示屏的指令说明
162液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。
(说明:
1为高电平、0为低电平)。
162液晶屏内部模块共有11条控制指令,如表2.2.2所示。
表2.2.2控制命令表
序号
指令
RS
R/W
D7
D6
D5
D4
D3
D2
D1
D0
1
清屏
0
0
0
0
0
0
0
0
0
1
2
光标返回
0
0
0
0
0
0
0
0
1
*
3
输入方式
0
0
0
0
0
0
0
1
I/D
S
4
显示开关
0
0
0
0
0
0
1
D
C
B
5
移位
0
0
0
0
0
1
S/C
R/L
*
*
6
功能设置
0
0
0
0
1
DL
N
F
*
*
7
CGRAM地址设置
0
0
0
1
A5A4A3A2A1A0
8
DDRAM地址设置
0
0
1
A6A5A4A3A2A1A0
9
忙标志/读地址计数器
0
1
BF
AC6AC5AC4AC3AC2AC1AC0
10
CGRAM/DDRAM数据写
1
0
写数据
11
CGRAM/DDRAM数据读
1
1
读数据
指令1:
清显示,指令码01H,光标复位到地址00H位置
指令2:
光标复位,光标返回到地址00H
指令3:
光标和显示模式设置
I/D:
光标移动方向,高电平右移,低电平左移
S:
屏幕上所有文字是否左移或者右移。
高电平表示有效,低电平则无效
指令4:
显示开关控制。
D:
控制整体显示的开与关,高电平表示开显示,低电平表示关显示
C:
控制光标的开与关,高电平表示有光标,低电平表示无光标
B:
控制光标是否闪烁,高电平闪烁,低电平不闪烁
指令5:
光标或显示移位S/C:
高电平时移动显示的文字,低电平时移动光标
指令6:
功能设置命令
DL:
高电平时为4位总线,低电平时为8位总线
N:
低电平时为单行显示,高电平时双行显示
F:
低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符
指令7:
字符发生器RAM地址设置
指令8:
DDRAM地址设置
指令9:
读忙信号和光标地址BF:
忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。
指令10:
写数据
指令11:
读数据
2.2.3162液晶显示屏的时序
操作液晶屏,我们得对它的工作时序图熟悉,这里我们介绍的是162液晶显示屏的两个写时序:
写指令和写入数据。
写指令,即设置162液晶显示屏的工作方式:
需要把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入。
写数据,即在液晶屏上实现显示时:
需要把RS置为低电平,RW置为低电平,然后将数据送到D0~D7,最后E引脚一个高脉冲将数据写入。
RSDATA数据准备好
RWRS
CMD命令准备好RW
ENEN
(1)写命令时序图
(2)写数据时序图
图1-2-3162液晶显示屏时序图
值得注意的是,162液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。
当然,162提供了读忙信号的方法:
当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号。
2.2.4162液晶屏的RAM地址映射及标准字库表
HS162-4液晶模块内部的字符发生存储器(CGROM)已经存储了128个不同的点阵字符图形,这些字符有:
阿拉伯数字、英文字母的大小写和常用的符号等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符。
液晶屏第一行的首地址是80H,第二行的首地址是C0H。
表1.2.4是液晶屏的GROM中的字符代码与图形对应关系。
表2.2.4字符代码与图形对应表
高位
低位
0000
0010
0011
0100
0101
0110
0111
0000
GRAM
0
@
P
\
p
0001
!
1
A
Q
a
Q
0010
”
2
B
R
b
R
0011
#
3
C
S
c
S
0100
$
4
D
T
d
t
0101
%
5
E
U
e
u
0110
&
6
F
V
f
v
0111
’
7
G
W
g
w
1000
(
8
H
X
h
x
1001
)
9
I
Y
i
y
1010
*
:
J
Z
j
Z
1011
+
;
K
[
k
{
1100
<
L
¥
l
|
1101
-
=
M
]
m
}
1110
.
>
N
^
n
→
1111
/
?
O
_
o
←
2.3、ds1302芯片介绍
DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。
实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。
工作电压宽达2.5~5.5V。
采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。
DS1302的外部引脚分配如图1所示及内部结构如图2所示。
DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。
各引脚的功能为:
Vcc1:
主电源;Vcc2:
备份电源。
当Vcc2>Vcc1+0.2V时,由Vcc2向DS1302供电,当Vcc2SCLK:
串行时钟,输入,控制数据的输入与输出;
I/O:
三线接口时的双向数据线;
CE:
输入信号,在读、写数据期间,必须为高。
该引脚有两个功能:
第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。
DS1302有下列几组寄存器:
①DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h~8Dh,写时80h~8Ch),存放的数据格式为BCD码形式,如图3所示。
小时寄存器(85h、84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。
当为高时,选择12小时模式。
在12小时模式时,位5是,当为1时,表示PM。
在24小时模式时,位5是第二个10小时位。
秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。
当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位置为0时,时钟开始运行。
控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置为0。
在任何的对时钟和RAM的写操作之前,WP位必须为0。
当WP位为1时,写保护位防止对任一寄存器的写操作。
②DS1302有关RAM的地址
DS1302中附加31字节静态RAM的地址如图4所示。
③DS1302的工作模式寄存器
所谓突发模式是指一次传送多个字节的时钟信号和RAM数据。
突发模式寄存器如图5所示。
④此外,DS1302还有充电寄存器等。
2读写时序说明
DS1302是SPI总线驱动方式。
它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。
要想与DS1302通信,首先要先了解DS1302的控制字。
DS1302的控制字如图6。
控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6:
如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1(A4~A0):
指示操作单元的地址;位0(最低有效位):
如为0,表示要进行写操作,为1表示进行读操作。
控制字总是从最低位开始输出。
在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。
同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。
数据读写时序如图7。
3硬件设计
硬件电路设计主要是AT89C51单片机、ds1302时钟芯片与162液晶显示屏的接口设计。
硬件电路如图所示,单片机的p2.0、p2.1、p2.2分别连接液晶的寄存器选择、读写选择、使能端这三个端口;单片机的p0口的8位分别连接液晶的8个数据端口;单片机的p1端口作为输入端,ds1302芯片,整个系统采用5V的电源。
4软件设计
在前面几节中,我们了解了AT89C51单片机、162液晶显示屏与ds1302的接口设计以及液晶屏的时序,那么这部分阐述的是单片机对液晶屏显示和ds1302的驱动控制。
软件工作流程如下:
液晶屏的初始化根据它的时序来及表2.2.2的控制命令表对其进行初始化。
Ds1302初始化是根据图3、4、5、6中对相应的寄存器操作来进行的初始化。
5结束语
晶液显示器作为输出器件有以下几个优点:
1.显示质量高:
由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。
因此,液晶显示器画质高且不会闪烁。
2.数字式接口:
液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
3.体积小、重量轻:
液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。
4.功耗低:
相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
DS1302高性能,低功耗带RAM实时时钟芯片简介:
1.可对秒、分、时、日、周、月以及带润年补偿的年进行计数,有效至2100年。
2.用于高速数据暂存31字节非易失性RAM.
3.宽工作电源电压范围:
2.0V~5.5V。
4.用于(时鈡)或RAM数据读/写的单字节或多字节数据传送方式。
5.简单的3线接口与单片机通信。
6.TTL兼容(VCC=5V)
7.可选的工业温度范围:
-40C。
~+85C。
参考文献:
[1]HS162-4液晶显示使用说明资料.
[2]DS1302使用说明资料.
[3]贺敬凯,刘德新,管明祥.单片机系统设计、仿真与应用。
西安电子科技大学出版社,2011.
附件:
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharcount_10ms;//定义10ms计数器
sbitreset=P1^5;
sbitsclk=P1^6;
sbitio=P1^7;
sbitLCD_RS=P2^0;
sbitLCD_RW=P2^1;
sbitLCD_EN=P2^2;
ucharcodeline1_data[]={"Date:
1"};//定义第1行显示的字符
ucharcodeline2_data[]={"Time:
"};//定义第2行显示的字符
uchardisp_buf[8]={0x00};
uchardisp_buf1[8]={0x00};//定义显示缓冲区
uchartime_buf[7]={0,0,0x12,0,0,0,0};//DS1302时间缓冲区,存放秒、分、时、日、月、星期、年
/********以下是函数声明********/
voidDelay_ms(uintxms);
bitlcd_busy();
voidlcd_wcmd(ucharcmd);
voidlcd_wdat(uchardat);
voidlcd_clr();
voidlcd_init();
voidwrite_byte(ucharinbyte);//写一字节数据函数声明
ucharread_byte();//读一字节数据函数声明
voidwrite_ds1302(ucharcmd,ucharindata);//写DS1302函数声明
ucharread_ds1302(ucharaddr);//读DS1302函数声明
voidset_ds1302(ucharaddr,uchar*p,ucharn);//设置DS1302初始时间函数声明
voidget_ds1302(ucharaddr,uchar*p,ucharn);//读当前时间函数声明
voidinit_ds1302();//DS1302初始化函数声明
/********以下是延时函数********/
voidDelay_ms(uintxms)
{
uinti,j;
for(i=xms;i>0;i--)//i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
/********以下是LCD忙碌检查函数********/
bitlcd_busy()
{
bitresult;
LCD_RS=0;
LCD_RW=1;
LCD_EN=1;
_nop_();
_nop_();
_nop_();
_nop_();
//result=(bit)(P0&0x80);
LCD_EN=0;
returnresult;
}
/********以下是写指令寄存器IR函数********/
voidlcd_wcmd(ucharcmd)
{
while(lcd_busy());
LCD_RS=0;
LCD_RW=0;
LCD_EN=0;
_nop_();
_nop_();
P0=cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN=1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN=0;
}
/********以下是写寄存器DR函数********/
voidlcd_wdat(uchardat)
{
while(lcd_busy());
LCD_RS=1;
LCD_RW=0;
LCD_EN=0;
P0=dat;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN=1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN=0;
}
/********以下是LCD清屏函数********/
voidlcd_clr()
{
lcd_wcmd(0x01);//清除LCD的显示内容
Delay_ms(5);
}
/********以下是LCD初始化函数********/
voidlcd_init()
{
Delay_ms(15);//等待LCD电源稳定
lcd_wcmd(0x38);//16*2显示,5*7点阵,8位数据
Delay_ms(5);
lcd_wcmd(0x38);
Delay_ms(5);
lcd_wcmd(0x38);
Delay_ms(5);
lcd_wcmd(0x0c);//显示开,关光标
Delay_ms(5);
lcd_wcmd(0x06);//移动光标
Delay_ms(5);
lcd_wcmd(0x01);//清除LCD的显示内容
Delay_ms(5);
}
/********以下是写一字节数据函数********/
voidwrite_byte(ucharinbyte)
{
uchari;
for(i=0;i<8;i++)
{
sclk=0;//写时低电平改变数据
if(inbyte&0x01)
io=1;
else
io=0;
sclk=1;//高电平把数据写入DS1302
_nop_();
inbyte=inbyte>>1;
}
}
/********以下是读一字节数据函数********/
ucharread_byte()
{
uchari,temp=0;
io=1;
for(i=0;i<7;i++)
{
sclk=0;
if(io==1)
temp=temp|0x80;
else
temp=temp&0x7f;
sclk=1;//产生下跳沿
temp=temp>>1;
}
return(temp);
}
/********写DS1302函数,往DS1302的某个地址写入数据********/
voidwrite_ds1302(ucharcmd,ucharindata)
{
sclk=0;
reset=1;
write_byte(cmd);
write_byte(indata);
sclk=0;
reset=0;
}
/********读DS1302函数,读DS1302某地址的的数据********/
ucharread_ds1302(ucharaddr)
{
ucharbackdata;
sclk=0;
reset=1;
write_byte(addr);//先写地址
backdata=read_byte();//然后读数据
sclk=0;
reset=0;
return(backdata);
}
/