基于51单片机和DS1302的万年历的设计说明文档格式.docx
《基于51单片机和DS1302的万年历的设计说明文档格式.docx》由会员分享,可在线阅读,更多相关《基于51单片机和DS1302的万年历的设计说明文档格式.docx(25页珍藏版)》请在冰豆网上搜索。
在Flash编程时,P0口接收指令字节,而在程序校验时,输出指令字节,校验时要求外接上拉电阻。
●P1口:
P1口是一个带部上拉电阻的8位双向I/O,P1的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
对端口写“1”,通过部的上拉电阻把端口拉到高电平,此时可作输入口。
作输入口使用时,因为部存在上拉电阻,某个引脚被外部信号拉低时会输出一个电流。
Flash编程和程序校验期间,P1接收低8位地址。
●P2口:
P2口是一个带部上拉电阻的8位双向I/O,P2的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
在访问外部程序存储器或16位地址的外部数据存储器(例如执行MOVXDPTR指令)时,P2口送出高8位地址数据。
在访问8位地址的外部数据存储器(MOVXRi指令)时,P2口线上的容(也即特殊功能寄存器(SFR)区中P2寄存器的容),在整个访问期间不改变。
Flash编程和程序校验期间,P2亦接收低高位地址和其他控制信号。
●P3口:
P3口是一组带部上拉电阻的8位双向I/O,P3的输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
对P3口写入“1”时,它们被部的上拉电阻拉高并可作为输入端口。
作输入端时,被外部拉低的P3口将用上拉电阻输出电流。
P3口除了作为一般的I/O口线外,更重要的用途是它的第二功能,见表3-1所示:
P3口还接收一些用于Flash闪速存储器编程和程序校验的控制信号。
表3-1P3口的第二功能图
端口引脚
第二功能
P3.0
RXD(串行输入口)
P3.1
TXD(串行输出口)
P3.2
INT0(外中断0)
P3.3
INT1(外中断1)
P3.4
T0(定时/计时器0外部输入)
P3.5
T1(定时/计时器1外部输入)
P3.6
WR(外部数据存储器写选通)
P3.7
RD(外部数据存储器读选通)
●RST:
复位输入。
当振荡器工作时,RST引脚出现两个机器周期以上高电平将使单片机复位。
WDT溢出将使引脚输出高电平,设置SFRAUXR的DISRT0(地址8EH)可打开或关闭该功能。
DISRT0位缺省为RESET输出高电平打开状态。
●ALE/PROG:
当访问外部程序存储器或数据存储器时,ALE(地址锁存器允许)输出脉冲用于锁存地址的低8位字节。
即使不访问外部存储器,ALE仍以时钟振荡频率的1/6输出固定的正脉冲信号,因此它可对外输出时钟或用于定时目的。
要注意的是:
每当访问外部数据存储器时将跳过一个ALE脉冲。
对Flash存储器编程期间,该引脚还用于输入编程脉冲(PROG)。
如有必要,可通过多特殊功能寄存器(SFR)区中的8EH单元的D0位置,可禁止ALE操作。
该位置后,只有一条MOVX和MOVC指令ALE才会被激活。
另外,该引脚会被微弱拉高,单片机执行外部程序时,应设置ALE无效。
●PSEN:
程序存储允许(PSEN)输出是外部程序存储器的读选通信号,当AT89C51由外部程序存储器取指令(或数据)时,每个机器周期两次PSEN有效,即输出两个脉冲。
当访问外部数据存储器,没有两次有效的PSEN信号。
●EA/VPP:
外部访问允许。
欲使CPU仅访问外部程序存储器(地址为0000H—FFFFH),EA端必须保持低电平(接地)。
需要注意的是:
如果加密位LB1被编程,复位时部会锁存EA端状态。
如EA端为高电平(接Vcc端),CPU则执行部程序存储器中的指令。
Flash存储器编程时,该引脚加上+12V的变成电压Vpp.
●XTAL1:
振荡器反相放大器与部时钟发生器的输入端。
●XTAL2:
振荡器反相放大器的输出端。
AT89C51单片机部结构
2.AT89C51单片机与MCS-51完全兼容
●看门狗(WDT):
WDT是一种需要软件控制的复位方式。
WDT由13位计数器和特殊功能寄存器中的看门狗定时器复位存储器(WDTRST)构成。
WDT在默认情况下无法工作;
为了激活WDT,用户必须往WDTRST寄存器(地址:
0A6H)中依次写入01EH和0E1H。
当WDT激活后,晶振工作,WDT在每个机器周期都会增加。
WDT计时周期依赖于外部时钟频率。
除了复位(硬件复位或WDT溢出复位),没有办法停止WDT工作。
当WDT溢出,它将驱动RSR引脚输出一个高电平。
●可编程串口(UART)在AT89C51中,UART的操作与AT89C51和AT89C52一样。
AT89C51系列单片机的串行通信口可以工作于同步和异步通信方式。
当工作于异步方式时,它具有全双工的操作功能,也就是说,它可以同时进行数据的发送和接收。
串行口的接收器采用的是双缓冲结构,能够在接收到的第一个字节从接收寄存器读走之前就开始接收第二个字节(当然,如果第二个字节接收完毕,而第一个字节仍然没有被读走,那将会丢掉一个字节)。
串行口的发送和接收操作都是通过特殊功能寄存器中的数据缓冲寄存器SBUF进行的,但在SBUF的部,接收寄存器和发送寄存器在物理结构上是完全独立的。
如果将数据写入SBUF,数据会被送入发送寄存器准备发送。
如果执行SBUF指令,则读出的数据一定来自接收缓存器。
因此,CPU对SBUF的读写,实际上是分别访问2个不同的寄存器。
这2个寄存器的功能决不能混淆。
●振荡电路:
AT89C51系列单片机的部振荡器,由一个单极反相器组成。
XTAL1反相器的输入,XTAL2为反相器的输出。
可以利用它部的振荡器产生时钟,只要XTAL1和XTAL2引脚上一个晶体与电容组成的并联谐振电路,便构成一个完整的振荡信号发生器,此方式称为部方式。
另一种方式由外部时钟源提供一个时钟信号到XTAL1端输入,而XTAL2端浮空。
在组成一个单片机应用系统时,多数采用这种方式,这种方式结构紧凑,成本低廉,可靠性高。
在电路中,对电容C1和C2的值要求不是很严格,如果使用高质的晶振,则不管频率为多少,C1、C2通常都选择30pF。
●定时/计数器:
AT89C51单片机含有2个16位的定时器/计数器。
当用于定时器方式时,定时器的输入来自部时钟发生电路,每过一个机器周期,定时器加1,而一个机器周期包含有12个振荡周期,所以,定时器的技术频率为晶振频率的1/12,而计数频率最高为晶振频率的1/24。
为了实现定时和计数功能,定时器中含有3种基本的寄存器:
控制寄存器、方式寄存器和定时器/计数器。
控制寄存器是一个8位的寄存器,用于控制定时器的工作状态,方式寄存器是一个8位的寄存器,用于确定定时器的工作方式,定时器/计数器是16位的计数器,分为高字节和低字节两部分。
●RAM:
高于7FH部数据存储器的地址是8位的,也就是说其地址空间只有256字节,但部RAM的寻址方式实际上可提供384字节。
的直接地址访问同一个存储空间,高于7FH的间接地址访问另一个存储空间。
这样,虽然高128字节区分与专用寄器,即特殊功能寄存器区的地址是重合的,但实际上它们是分开的。
究竟访问哪一区,存是通过不同的寻址方式加以区分的。
●SFR:
SFR是具有特殊功能的所有寄存器的集合,共含有22个不同寄存器,它们的地址分配在80H~FFH中。
虽然如此,不是所有的单元都被特殊功能寄存器占用,未被占用的单元,其容是不确定的。
如对这些单元进行读操作,得到的是一些随机数,而写入则无效,所以在编程时不应该将数据写入这些未确定的地址单元中,特殊功能寄存器主要有累加器ACC、B寄存器、程序状态字寄存器PSW、堆栈指针SP、数据指针DPTR、I/O端口、串行口数据缓冲器SBUF、定时器寄存器、捕捉寄存器、控制寄存器。
●中断系统:
AT89C51单片机有6个中断源,中断系统主要由中断允许寄存器IE、中断优先级寄存器IP、优先级结构和一些逻辑门组成。
IE寄存器用于允许或禁止中断;
IP寄存器用于确定中断源的优先级别;
优先级结构用于执行中断源的优先排序;
有关逻辑门用于输入中断请求信号。
在整个中断响应过程中CPU所执行的操作步骤如下:
(1)完成当前指令的操作
(2)将PC容压入堆栈
(3)保存当前的中断状态
(4)阻止同级的中断请求
(5)将中断程序入口地址送PC寄存器
(6)执行中断服务程序
DS1302实时时钟:
1时钟芯片DS1302的工作原理:
DS1302在每次进行读、写程序前都必须初始化,先把SCLK端置“0”,接着把RST端置“1”,最后才给予SCLK脉冲;
读/写时序如下图所示。
为DS1302的控制字,此控制字的位7必须置1,若为0则不能把对DS1302进行读写数据。
对于位6,若对程序进行读/写时RAM=1,对时间进行读/写时,CK=0。
位1至位5指操作单元的地址。
位0是读/写操作位,进行读操作时,该位为1;
该位为0则表示进行的是写操作。
控制字节总是从最低位开始输入/输出的。
表6为DS1302的日历、时间寄存器容:
“CH”是时钟暂停标志位,当该位为1时,时钟振荡器停止,DS1302处于低功耗状态;
当该位为0时,时钟开始运行。
“WP”是写保护位,在任何的对时钟和RAM的写操作之前,WP必须为0。
当“WP”为1时,写保护位防止对任一寄存器的写操作。
2DS1302的控制字节:
DS1302的控制字如表-1所示。
控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;
位5至位1指示操作单元的地址;
最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
表-1DS1302的控制字格式
RAMRD
1A4A3A2A1A0
/CK/WR
3数据输入输出(I/O):
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如下图所示:
图1DS1302读/写时序图
4DS1302的寄存器:
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器与其控制字。
此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器与与RAM相关的寄存器等。
时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器容。
DS1302与RAM相关的寄存器分为两类:
一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;
另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
实时时钟电路设计:
DS1302与单片机的连接,其中Vcc1为后备电源,Vcc2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768KHz晶振。
DS1302时钟程序流程:
流程图分析:
DS1302开始计时时,首先进行初始化,当有中断信号时,读取时钟芯片的时间数据送入液晶显示。
这时若有设置键按下,进行时间修改,完成后将时间数据送入1302芯片,若没有按键按下,直接送入EPROM中,送入液晶显示。
LCD显示程序流程:
流程图分析如下:
首先对1602显示屏进行初始化(初始化大约持续10ms),然后检查忙信号,若BF=0,则获得显示RAM地址,写入相应的数据显示。
若BF=1,则代表模块正在进行部操作,不接受任何外部指令和数据,直到BF=0为止。
Proteus电路图:
Proteus运行图:
源程序:
#include<
reg51.h>
#defineuintunsignedint
#defineucharunsignedchar
uchara,miao,shi,fen,ri,yue,nian,week,key1n,temp;
#defineyh0x80
#defineer0x80+0x40
sbitrs=P2^6;
sbiten=P2^7;
sbitrw=P2^5;
sbitIO=P3^4;
sbitSCLK=P3^6;
sbitRST=P3^5;
sbitACC0=ACC^0;
sbitACC7=ACC^7;
sbitkey1=P2^0;
sbitkey2=P2^1;
sbitkey3=P2^2;
ucharcodetab1[]={"
20--"
};
ucharcodetab2[]={"
:
"
voiddelay(uintxms)
{
uintx,y;
for(x=xms;
x>
0;
x--)
for(y=120;
y>
y--);
}
voidwrite_1602com(uchar)
rs=0;
rw=0;
P0=;
delay
(1);
en=1;
en=0;
voidwrite_1602dat(uchardat)
rs=1;
P0=dat;
voidlcd_init()
write_1602com(0x38);
write_1602com(0x0c);
write_1602com(0x06);
write_1602com(0x01);
write_1602com(yh+1);
for(a=0;
a<
14;
a++)
write_1602dat(tab1[a]);
//delay(3);
write_1602com(er+2);
8;
write_1602dat(tab2[a]);
voidwrite_byte(uchardat)
ACC=dat;
RST=1;
for(a=8;
a>
a--)
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>
>
1;
ucharread_byte()
ACC7=IO;
return(ACC);
voidwrite_1302(ucharadd,uchardat)
RST=0;
RST=1;
write_byte(add);
write_byte(dat);
ucharread_1302(ucharadd)
uchartemp;
temp=read_byte();
return(temp);
ucharBCD_Decimal(ucharbcd)
ucharDecimal;
Decimal=bcd>
4;
return(Decimal=Decimal*10+(bcd&
=0x0F));
voidds1302_init()
write_1302(0x8e,0x00);
write_1302(0x80,0x00);
write_1302(0x82,0x00);
write_1302(0x84,0x12);
write_1302(0x8a,0x02);
write_1302(0x86,0x11);
write_1302(0x88,0x06);
write_1302(0x8c,0x13);
write_1302(0x8e,0x80);
voidwrite_sfm(ucharadd,uchardat)
uchargw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(er+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
voidwrite_nyr(ucharadd,uchardat)
write_1602com(yh+add);
voidwrite_week(ucharweek)
write_1602com(yh+0x0c);
switch(week)
case1:
write_1602dat('
M'
);
write_1602dat('
O'
N'
break;
case2:
T'
U'
E'
case3:
W'
D'
case4:
H'
case5:
F'
R'
I'
case6:
S'
A'
case7:
voidkeyscan()
if(key1==0)
delay(9);
while(!
key1);
key1n++;
if(key1n==9)
key1n=1;
switch(key1n)
case1:
TR0=0;
//TR1=0;
write_1602com(er+0x09);
write_1602com(0x0f);
temp=(miao)/10*16+(miao)%10;
write_1302(0x80,0x80|temp);
case2:
write_1602com(er+6);
//按2次fen位置显示光标
//write_1602com(0x0f);
case3:
write_1602com(er+3);
//按动3次,shi
case4:
write_1602com(yh+0x0e);
//按动4次,week
case5:
write_1602com(yh+0x0a);
//按动5次,ri
case6:
write_1602com(yh+0x07);
//按动6次,yue
case7:
write_1602com(yh+0x04);
//按动7次,nian
case8:
write_1602com(0x0c);
//按动到第8次,设置光标不闪烁
TR0=1;
//打开定时器
write_1302(0x80,0x00|temp);
//miao数据写入DS1302
if(key1n!
=0)
if(key2==0)
delay(10);
if(key2==0)
key2);
miao++;
if(miao==60)
miao=0;