电子钟设计Word文档下载推荐.docx
《电子钟设计Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《电子钟设计Word文档下载推荐.docx(20页珍藏版)》请在冰豆网上搜索。
在内部的各种功能部件不能满足应用的需求时,均可在外部进行扩展,与许多通用的微机接口芯片兼容,给应用系统设计带来了很大的方便。
2.1.289C51单片机介绍
VCC:
电源。
GND:
接地。
P0口:
P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:
P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:
P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
89C51单片机
P3口:
P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。
当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。
作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。
P3口也可作为AT89C51的一些特殊功能口,如下表所示:
口管脚备选功能
P3.0RXD(串行输入口)
P3.1TXD(串行输出口)
P3.2/INT0(外部中断0)
P3.3/INT1(外部中断1)
P3.4T0(记时器0外部输入)
P3.5T1(记时器1外部输入)
P3.6/WR(外部数据存储器写选通)
P3.7/RD(外部数据存储器读选通)
P3口同时为闪烁编程和编程校验接收一些控制信号。
RST:
复位输入。
当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:
当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的地位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。
在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。
因此它可用作对外部输出的脉冲或用于定时目的。
然而要注意的是:
每当用作外部数据存储器时,将跳过一个ALE脉冲。
如想禁止ALE的输出可在SFR8EH地址上置0。
此时,ALE只有在执行MOVX,MOVC指令是ALE才起作用。
另外,该引脚被略微拉高。
如果微处理器在外部执行状态ALE禁止,置位无效。
PSEN:
外部程序存储器的选通信号。
在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。
但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
EA/VPP:
当/EA保持低电平时,则在此期间外部程序存储(0000H-FFFFH),不管是否有内部程序存储器。
注意加密方式1时,/EA将内部锁定为RESET;
当/EA端保持高电平时,此间内部程序存储器。
在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
2.3晶振电路
每个单片机系统里都有晶振,全程是叫晶体震荡器,在单片机系统里晶振的作用非常大,他结合单片机内部的电路,产生单片机所必须的时钟频率,单片机的一切指令的执行都是建立在这个基础上的,晶振的提供的时钟频率越高,那单片机的运行速度也就越快。
晶振用一种能把电能和机械能相互转化的晶体在共振的状态下工作,以提供稳定,精确的单频振荡。
在通常工作条件下,普通的晶振频率绝对精度可达百万分之五十。
高级的精度更高。
有些晶振还可以由外加电压在一定范围内调整频率,称为压控振荡器(VCO)。
晶振的作用是为系统提供基本的时钟信号。
通常一个系统共用一个晶振,便于各部分保持同步。
有些通讯系统的基频和射频使用不同的晶振,而通过电子调整频率的方法保持同步。
晶振通常与锁相环电路配合使用,以提供系统所需的时钟频率。
如果不同子系统需要不同频率的时钟信号,可以用与同一个晶振相连的不同锁相环来提供。
图晶振电路
2.4、定时器/计数器T0中断服务程序
T0用于计时,选中方式一,重复定时,定时时间设为50ms,定时时间到则中断,在中断服务程序中用一个计数器对50ms计数,计20次则对秒单元加一。
秒单元加到60则对分单元加一,同时秒单元清0;
分单元加到60则对时单元加一,同时分单元清0;
时单元加到24则对时单元清0,标
志一天时间计满。
在对各单元计数的同时,把他们的值放到存储器单元的指定位置。
2.5按键处理模块
时间按键设置:
如果按下K1键,则为当前时间,此时按下K2,则进入调时间分状态,时钟停止走动,依次按下K2可分别对年-月-星期-天-时-分-的调整,按K+和K-按键可以进行加一和减一操作;
继续按K3键启动计时,即为当前调整的时间。
第三章软件仿真
3.1protues软件
3.1.1protues软件简介
ProteusISIS是英国Labcenter公司开发的电路分析与实物仿真软件。
它运行于Windows操作系统上,可以仿真、分析(SPICE)各种模拟器件和集成电路,该软件的特点是:
①实现了单片机仿真和SPICE电路仿真相结合。
具有模拟电路仿真、数字电路仿真、单片机及其外围电路组成的系统的仿真、RS232动态仿真、I2C调试器、SPI调试器、键盘和LCD系统仿真的功能;
有各种虚拟仪器,如示波器、逻辑分析仪、信号发生器等。
②支持主流单片机系统的仿真。
目前支持的单片机类型有:
68000系列、8051系列、AVR系列、PIC12系列、PIC16系列、PIC18系列、Z80系列、HC11系列以及各种外围芯片。
③提供软件调试功能。
在硬件仿真系统中具有全速、单步、设置断点等调试功能,同时可以观察各个变量、寄存器等的当前状态,因此在该软件仿真系统中,也必须具有这些功能;
同时支持第三方的软件编译和调试环境,如KeilC51uVision2等软件。
④具有强大的原理图绘制功能。
总之,该软件是一款集单片机和SPICE分析于一身的仿真软件,功能极其强大。
本章介绍ProteusISIS软件的工作环境和一些基本操作。
3.1.2电路功能仿真
在PROTUES绘制好原理图后,调入已编译好的目标代码文件:
*.HEX,可以在PROTUES的原理图中看到模拟的实物运行状态和过程。
PROTUES是单片机课堂教学的先进助手。
PROTUES不仅可将许多单片机实例功能形象化,也可将许多单片机实例运行过程形象化。
前者可在相当程度上得到实物演示实验的效果,后者则是实物演示实验难以达到的效果。
它的元器件、连接线路等却和传统的单片机实验硬件高度对应。
这在相当程度上替代了传统的单片机实验教学的功能,例:
元器件选择、电路连接、电路检测、电路修改、软件调试、运行结果等。
课程设计、毕业设计是学生走向就业的重要实践环节。
由于PROTUES提供了实验室无法相比的大量的元器件库,提供了修改电路设计的灵活性、提供了实验室在数量、质量上难以相比的虚拟仪器、仪表,因而也提供了培养学生实践精神、创造精神的平台
随着科技的发展,“计算机仿真技术”已成为许多设计部门重要的前期设计手段。
它具有设计灵活,结果、过程的统一的特点。
可使设计时间大为缩短、耗资大为减少,也可降低工程制造的风险。
相信在单片机开发应用中PROTUES也能茯得愈来愈广泛的应用。
3.2电路原理图
3.3源程序代码
#include<
reg52.h>
string.h>
#defineucharunsignedchar
#defineuintunsignedint
sbitzhuan=P1^5;
//dingyiyinjiao
sbitLED2=P2^6;
sbitLED1=P1^7;
//声音引脚
sbitLED=P2^7;
//时钟引脚
sbitSDA=P1^0;
sbitCLK=P1^1;
sbitRST=P1^2;
//液晶显示屏引脚
yejingpinyinjiao
sbitRS=P2^0;
sbitRW=P2^1;
sbitEN=P2^2;
//K按键
sbitk1=P3^4;
sbitk2=P3^5;
sbitk3=P3^6;
sbitk4=P3^7;
ucharcodedis_alarm0[]="
ALARMDHM"
;
//定义一个字符串
uchardis_alarm1[]="
TM:
00:
00:
00"
;
//56天89时1112分
uchartian=0;
ucharshi=0;
ucharfen=0;
uchartcount=0;
//一年中每个月份天数,二月天数有年份决定
ucharmonthdays[]={0,31,0,31,30,31,30,31,31,30,31,30,31};
uchar*week[]={"
sun"
"
mon"
tus"
wen"
thu"
fri"
sat"
};
//LCDhuanchongxianshi
ucharidatalcd_dis_buffer1[]={"
DT:
2000-00-00"
ucharidatalcd_dis_buffer2[]={"
TM:
uchardatetime[7];
//读取日期时间
uch
aradjust_index=-1;
ucharchange_flag[]="
-MHDM-Y"
//年-月-星期-天-时-分调整
//yanshi
//-----------------------------------------------
voiddelay(uintx)
{
uchari;
while(x--)for(i=0;
i<
120;
i++);
//空语句1us
}
//*************************驱动程序*DS_1302************8
//xieruyigezijieDS1302
voidwrite_to_DS(ucharx)
{
for(i=0;
8;
i++)
SDA=x&
1;
CLK=1;
CLK=0;
x>
>
=1;
}
//-----------------------------------------------------------------
//getabytefromDS1302
ucharget_from_DS()
uchari,b,t;
b>
t=SDA;
b|=t<
<
7;
//BCDmazhuanhuan
returnb/16*10+b%16;
ucharread_data(ucharaddr)
uchardat;
RST=0;
RST=1;
write_to_DS(addr);
dat=get_from_DS();
CLK=1;
RST=0;
returndat;
//xiangDSmouzhidingweizhixierushuju
voidwrite_DS(ucharaddr,uchardat)
CLK=0;
RST=1;
write_to_DS(dat);
//settime
voidset_DS()
write_DS(0x8E,0x00);
//writecontrol,deleteprotete
//fen,shi,ri,yue,nian,yicixieru
for(i=1;
write_DS(0x80+2*i,(datetime[i]/10<
4)|(datetime[i]%10));
}
write_DS(0x8E,0x80);
//addprotect
//readcurrenttime
voidgettime()
uchari;
datetime[i]=read_data(0x81+2*i);
//---------***********DS_驱动结束********-------------------
//LCD控制
//读lcd状态
ucharread_lcd_state()
ucharstate;
RS=0;
RW=1;
EN=1;
delay
(1);
state=P0;
EN=0;
returnstate;
}
//忙等待
voidlcd_busy_wait()
while((read_lcd_state()&
0x80)==0x80);
delay(5);
//向LCD写数据
voidwrite_lcd_data(uchardat)
lcd_busy_wait();
RS=1;
RW=0;
P0=dat;
//向LCD写指令
voidwrite_lcd_cmd(ucharcmd)
{lcd_busy_wait();
P0=cmd;
//LCD初始化
voidInit_lcd()
write_lcd_cmd(0x38);
delay
(1);
write_lcd_cmd(0x01);
write_lcd_cmd(0x06);
write_lcd_cmd(0x0C);
}
//设置液晶显示位置
voidset_lcd_pos(ucharp)
write_lcd_cmd(p|0x80);
//在LCDzhidinghang上显示字符串
voiddis_lcd_string(ucharp,uchar*s)//位置,字符指针
set_lcd_pos(p);
16;
i++)//16*2
write_lcd_data(s[i]);
//LCD驱动结束
//闹钟显示
voidalarm_xs()//将闹钟时间转换成字符串
dis_alarm1[5]=tian/10+'
0'
dis_alarm1[6]=tian%10+'
dis_alarm1[8]=shi/10+'
dis_alarm1[9]=shi%10+'
dis_alarm1[11]=fen/10+'
dis_alarm1[12]=fen%10+'
dis_lcd_string(0x00,dis_alarm0);
//第一行显示字符串
dis_lcd_string(0x40,dis_alarm1);
//第二行显示字符串
}//datetimechangtostring
voidformat_datetime(uchard,uchar*a)
a[0]=d/10+'
a[1]=d%10+'
//-------------------------------------------------------
//瑞年判断
ucharisleapyear(uinty)
return(y%4==0&
&
y%100!
=0||(y%400==0));
//求weekday
voidrefreshweekday()
uinti,d,w=5;
for(i=2000;
2000+datetime[6];
d=isleapyear(i)?
366:
365;
w=(w+d)%7;
d=0;
datetime[4];
d+=monthdays[i];
d+=datetime[3];
datetime[5]=(w+d)%7+1;
//setyearmonthdayhourminscend++/--
voiddatetime_adjust(ucharx)
switch(adjust_index)
case6:
//nian00-99
if(x==1&
datetime[6]<
99)datetime[6]++;
if(x==-1&
datetime[6]>
0)datetime[6]--;
//geteryuetianshu
monthdays[2]=isleapyear(2000+datetime[6])?
29:
28;
if(datetime[3]>
monthdays[datetime[4]])
datetime[3]=monthdays[datetime[4]];
refreshweekday();
//refreshweekday
break;
case4:
//yue01-12
if(x==1&
datetime[4]<
12)datetime[4]++;
datetime[4]>
1)datetime[4]--;
case3:
//ri
monthdays[2]=isleapyear(2000+datetime[6])?
datetime[3]<
monthdays[datetime[4]])datetime[3]++;
if(x==-1&
datetime[3]>
0)datetime[3]--;
refreshweekday();
case2:
//hour
if(x==1&
datetime[2]<
23)datetime[2]++;
datetime[2]>
0)datetime[2]--;
case1:
//minut
datetime[1]<
59)datetime[1]++;
datetime[1]>
0)datetime[1]--;
//--------------------------------------------------------------
//T0per1srefreshtheLCDT0中断
voidT0_int()