单片机考试论文Word文档下载推荐.docx
《单片机考试论文Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《单片机考试论文Word文档下载推荐.docx(17页珍藏版)》请在冰豆网上搜索。
控制字节最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。
位6如果为0,则表示存取日历时钏娄据,为1表示存取RAM数据;
位5至位1指示操作单元的地址;
最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
DS1302的复位引脚:
通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;
其次,RST提供了终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中置RST为低电平,则会终止此次数据传送,并且I/O引脚变为高阴态。
上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
DS1302的数据输入与输出:
在控制指令字输入后的下一个SCLK时钟的上升沿时数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0至高位7,数据读写时序如下图:
DS1302寄存器:
DS1302共有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据为BCD码形式。
此外,DS1302还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。
2.2LCD1602
接口信号说明:
基本操作时序:
读状态:
输入:
RS=L,RW=H,E=H输出:
D0~D7=状态字
写指令:
RS=L,RW=L,D0~D7=指令码,E=高脉冲输出:
无
读数据:
输入:
RS=H,RW=H,E=H输出:
D0~D7=数据
写数据:
RS=H,RW=L,D0~D7=数据,E=高脉冲输出:
读操作时序:
写操作时序:
2.3AT89C52
功能特性概述:
AT89C52提供以下标准功能:
8k字节Flash闪速存储器,256字节内部RAM,32个I/O口线,3个16位定时/计数器,一个6向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
同时,AT89C52可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。
空闲方式停止CPU的工作,但通话RAM,定时/计数器,串行通信口及中断系统继续工作。
掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。
引脚功能说明:
Vcc:
电源电压GND:
地
P0口:
P0口是一组8位漏极开中型双向I/O口,也即地址/数据总线复用口。
作为输出口用时,每位能吸收电流的方式驱动8个TTL逻辑门电路,对端口P0写“1”时,可作为高阻抗输入端用。
P1口、P2口、P3口:
是一组带内部上拉电阻的8位双向I/O口,其输出缓冲级可驱动(吸收或输出电流)4个TTL逻辑门电路。
对端口写“1”,通过内部的上拉电阻把端口拉到高电平,此时可作输入口。
作输入口使用时,因为内部存在上拉电阻某个引脚被外部信号拉低时会输出一个电流。
2.4设计方案
以AT89C52为主控芯片,串行时钟芯片DS1302为核心计时芯片,LCD1602为主要显示器件,组成数字时钟电路。
将AT89C52的P0口分别与LCD1602的D0~D7相连,P2.0接DS1302的SCKL引脚,P2.1接DS1302的RST引脚,P2.2接DS1302的I/O引脚,P2.4接LCD1602的使能端E,P2.5接LCD1602的RS引脚,P2.6接LCD1602的RW引脚。
此方案中,由于仿真看不出效果,未在DS1302的备用电源VCC2端接入备用电源。
3.电路
4.程序
#include<
reg52.h>
sbitmode=P1^0;
//功能键
sbitadd=P1^1;
//加键
sbitsub=P1^2;
//减键
sbitSCLK=P2^0;
sbitDAT=P2^2;
sbitRST=P2^1;
sbitlcden=P2^4;
sbitrs=P2^5;
sbitrw=P2^6;
#defineds1302_second_write0x80
#defineds1302_second_read0x81
#defineds1302_minute_write0x82
#defineds1302_minute_read0x83
#defineds1302_hour_write0x84
#defineds1302_hour_read0x85
#defineds1302_date_write0x86
#defineds1302_date_read0x87
#defineds1302_month_write0x88
#defineds1302_month_read0x89
#defineds1302_week_write0x8a
#defineds1302_week_read0x8b
#defineds1302_year_write0x8c
#defineds1302_year_read0x8d
#definelcd1602_year3
#definelcd1602_month6
#definelcd1602_date9
#definelcd1602_week12
#definelcd1602_hour0x40+4
#definelcd1602_minute0x40+7
#definelcd1602_second0x40+10
unsignedintnian;
unsignedchartt,nummode,flag=0;
charhour,minute,second,year,month,date,week;
unsignedcharcodetable1[]="
20--"
;
unsignedcharcodetable2[]="
:
"
unsignedcharcodetable_week[][3]={"
MON"
"
TUE"
WED"
THU"
FRI"
SAT"
SUN"
};
unsignedchardays[]={31,29,31,30,31,30,31,31,30,31,30,31};
//每月天数
voidds1302_init();
//函数声明
voiddelayus(unsignedchartemp);
voiddelayms(unsignedchartemp);
voidds1302_write_byte(unsignedchardat);
unsignedchards1302_read_byte();
voidds1302_write(unsignedcharaddress,unsignedchardat);
unsignedchards1302_read(unsignedcharaddress);
unsignedchards1302_read_data(unsignedcharaddress);
voidlcd1602_write_data(unsignedchardate);
voidlcd1602_write_com(unsignedcharcom);
voidlcd1602_init();
voidlcd1602_write(unsignedcharaddress,chardate);
voidlcd1602_display();
voidinit();
voidkeyscan();
voidrunnian();
voidmain()//主函数
{
init();
while
(1)
{
runnian();
keyscan();
}
}
voidinit()//整体初始化
TMOD=0x01;
TL0=(65536-20000)%256;
TH0=(65536-20000)/256;
EA=1;
ET0=1;
TR0=1;
ds1302_init();
lcd1602_init();
voidds1302_init()//初始化DS1302
ds1302_write(0x8e,0x00);
//关闭写保护
ds1302_write(ds1302_second_write,0x00);
//初始化时间
ds1302_write(ds1302_minute_write,0x23);
ds1302_write(ds1302_hour_write,0x21);
ds1302_write(ds1302_date_write,0x04);
ds1302_write(ds1302_month_write,0x06);
ds1302_write(ds1302_week_write,0x01);
ds1302_write(ds1302_year_write,0x12);
voidlcd1602_init()//初始化lcd1602
unsignedcharn=0;
lcden=0;
lcd1602_write_com(0x38);
lcd1602_write_com(0x0c);
lcd1602_write_com(0x06);
lcd1602_write_com(0x01);
//清屏
lcd1602_write_com(0x80);
delayms(10);
for(n=0;
n<
10;
n++)//初始化显示格式
lcd1602_write_data(table1[n]);
delayus(5);
}
lcd1602_write_com(0xc0);
n++)
lcd1602_write_data(table2[n]);
voiddelayus(unsignedchartemp)//延时微秒
for(;
temp>
0;
temp--);
voiddelayms(unsignedchartemp)//延时毫秒
unsignedchari,j;
for(i=0;
i<
temp;
i++)
for(j=0;
j<
120;
j++);
voidds1302_write_byte(unsignedchardat)//向ds1302写一个字节
unsignedcharn;
delayus
(2);
8;
SCLK=0;
DAT=dat&
0x01;
//从低位开始写入
delayus
(2);
SCLK=1;
//产生上升延
dat>
>
=1;
}
unsignedchards1302_read_byte()//从ds1302读一个字节
unsignedcharn,dat=0;
SCLK=1;
//从低位开始
//产生下降沿
if(DAT==1)dat|=0x80;
returndat;
voidds1302_write(unsignedcharaddress,unsignedchardat)
{//向ds1302指定地址寄存器写入数据
RST=0;
SCLK=0;
RST=1;
ds1302_write_byte(address);
ds1302_write_byte(dat);
unsignedchards1302_read(unsignedcharaddress)
{//从ds1302指定地址寄存器读出数据
unsignedchardat;
dat=ds1302_read_byte();
unsignedchards1302_read_data(unsignedcharaddress)
{//将二进制BCD码转成十进制
unsignedchardat,x;
dat=ds1302_read(address);
x=((dat&
0xf0)>
4)*10+(dat&
0x0f);
returnx;
voidlcd1602_write_data(unsignedchardate)//向lcd1602写数据
rs=1;
rw=0;
P0=date;
lcden=1;
delayus(5);
voidlcd1602_write_com(unsignedcharcom)//向lcd1602写指令
rs=0;
P0=com;
voidlcd1602_write(unsignedcharaddress,chardate)
{//在lcd1602指定位置写数据
charshiwei,gewei;
lcd1602_write_com(0x80+address);
shiwei=date/10;
gewei=date%10;
lcd1602_write_data(0x30+shiwei);
lcd1602_write_data(0x30+gewei);
voidlcd1602_write_week(charweek)//lcd1602显示星期
lcd1602_write_com(0x80+lcd1602_week);
3;
n++)lcd1602_write_data(table_week[week-1][n]);
voidlcd1602_display()//lcd1602刷新数据
hour=ds1302_read_data(ds1302_hour_read);
minute=ds1302_read_data(ds1302_minute_read);
second=ds1302_read_data(ds1302_second_read);
week=ds1302_read_data(ds1302_week_read);
year=ds1302_read_data(ds1302_year_read);
date=ds1302_read_data(ds1302_date_read);
month=ds1302_read_data(ds1302_month_read);
lcd1602_write(lcd1602_year,year);
lcd1602_write(lcd1602_month,month);
lcd1602_write(lcd1602_date,date);
lcd1602_write_week(week);
lcd1602_write(lcd1602_hour,hour);
lcd1602_write(lcd1602_minute,minute);
lcd1602_write(lcd1602_second,second);
voidrunnian()//处理闰年二月天数
nian=2000+year;
if(((nian%4==0)&
&
(nian%100!
=0))||((nian%100==0)&
(nian/100%4==0)))days[1]=29;
elsedays[1]=28;
voidtimer0()interrupt1//定时器0中断函数
if(nummode==0)lcd1602_display();
voidkeyscan()//按键扫描
if(mode==0)
delayms(10);
//消抖
if(mode==0)
{
while(mode==0);
//等待按键松开
nummode++;
if(nummode==8)
{
ds1302_write(ds1302_second_write,((second/10)<
<
4)|(second%10));
//取消DS1302暂停,进入正常工作
nummode=0;
}
}
switch(nummode)
case0:
break;
//不显示光标
case1:
ds1302_write(ds1302_second_write,((second/10)<
4)|(second%10)|0x80);
lcd1602_write_com(0x80+lcd1602_year-2);
//定位到年
lcd1602_write_com(0x0f);
case2:
lcd1602_write_com(0x80+lcd1602_month);
//定位到月
case3:
lcd1602_write_com(0x80+lcd1602_date);
//定位到日
case4:
lcd1602_write_com(0x80+lcd1602_week);
//定位到星期
case5:
lcd1602_write_com(0x80+lcd1602_hour);
//定位到时
case6:
lcd1602_write_com(0x80+lcd1602_minute);
//定位到分
case7:
lcd1602_write_com(0x80+lcd1602_second);
//定位到秒
if(nummode&
add==0)
if(add==0)
while(add==0);
switch(nummode)
case1:
year++;
if(year==99)year=0;
lcd1602_write(lcd1602_year,year);
ds1302_write(ds1302_year_write,((year/10)<