基于单片机的万年历的液晶显示Word文件下载.docx
《基于单片机的万年历的液晶显示Word文件下载.docx》由会员分享,可在线阅读,更多相关《基于单片机的万年历的液晶显示Word文件下载.docx(23页珍藏版)》请在冰豆网上搜索。
这个并联谐振电路加到一个负反馈电路中就可以构成正弦波振荡电路,由于晶振等效为电感的频率范围很窄,所以即使其他元件的参数变化很大,这个振荡器的频率也不会有很大的变化。
晶振有一个重要的参数,那就是负载电容值,选择与负载电容值相等的并联电容,就可以得到晶振标称的谐振频率。
晶振电路由石英晶振并联2个电容,2个电容的容值为30PF,作用是让工作在并联谐振状态。
晶振电路分别接在单片机的18,19脚。
3STC89C545单片机:
STC89C54可以代替AT系列,功能更强,速度更快,寿命更长,价格更低。
外型:
40个引脚,双列直插DIP-40。
STC89C54可以完成ISP在线编程功能。
在这个设计中,利用定时器来进行计时,定时器中断一次,为50MS,中断20次就为1S,这是做万年历最基本的思路。
得到一秒,然后计时,60进位,分加一,分到了60,时加一,以此类推。
这样就实现了内部的计时。
41602液晶显示:
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:
阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
1602识别的是ASCII码,试验可以用ASCII码直接赋值。
1
VSS
一般接地
2
VDD
接电源(+5V)
3
V0
液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。
4
RS
RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。
5
R/W
R/W为读写信号线,高电平
(1)时进行读操作,低电平(0)时进行写操作。
6
E
E(或EN)端为使能(enable)端,下降沿使能。
7
DB0
底4位三态、双向数据总线0位(最低位)
8
DB1
底4位三态、双向数据总线1位
9
DB2
底4位三态、双向数据总线2位
10
DB3
底4位三态、双向数据总线3位
11
DB4
高4位三态、双向数据总线4位
12
DB5
高4位三态、双向数据总线5位
13
DB6
高4位三态、双向数据总线6位
14
DB7
高4位三态、双向数据总线7位(最高位)(也是busyflag)
15
BLA
背光电源正极
16
BLK
背光电源负极
1602通过D0~D7的8位数据端传输数据和指令。
显示模式设置:
00110000[0x38]设置16×
2显示,5×
7点阵,8位数据接口;
显示开关及光标设置:
00001DCBD显示(1有效)、C光标显示(1有效)、B光标闪烁(1有效)000001NSN=1(读或写一个字符后地址指针加1&
光标加1),N=0(读或写一个字符后地址指针减1&
光标减1),S=1且N=1(当写一个字符后,整屏显示左移),S=0当写一个字符后,整屏显示不移动数据指针设置:
数据首地址为80H,所以数据地址为80H+地址码(0-27H,40-67H),其他设置:
01H(显示清屏,数据指针=0,所有显示=0);
02H(显示回车,数据指针=0)。
写指令08H是关闭显示,写指令01H显示清屏,写指令06H光标移动设置,写指令0cH显示开及光标设置。
5发声电路:
蜂鸣器采用ULN2003驱动,ULN2003的每一对都串联一个2.7K的基极电阻,在5V的工作电压下它能与TTL和CMOS电路直接相连,可以直接处理原先需要标准逻辑缓冲器来处理的数据。
ULN2003工作电压高,工作电流大,灌电流可达500mA,并且能够在关态时承受50V的电压,输出还可以在高负载电流并行运行。
ULN2003内部还集成了一个消线圈反电动势的二极管,可用来驱动继电器。
它是双列16脚封装,NPN晶体管矩阵,最大驱动电压=50V,电流=500mA,输入电压=5V,适用于TTLCOMS,由达林顿管组成驱动电路。
ULN是集成达林顿管IC,内部还集成了一个消线圈反电动势的二极管,它的输出端允许通过电流为200mA,饱和压降VCE约1V左右,耐压BVCEO约为36V。
用户输出口的外接负载可根据以上参数估算。
采用集电极开路输出,输出电流大,故可直接驱动继电器或固体继电器,也可直接驱动低压灯泡。
通常单片机驱动ULN2003时,上拉2K的电阻较为合适,同时,COM引脚应该悬空或接电源。
ULN2003是一个非门电路,包含7个单元,单独每个单元驱动电流最大可达350mA,9脚可以悬空。
当1脚输入高电平,16脚输出为低电平。
蜂鸣器发声。
6按键电路
本设计一共有3个按钮,分别为K1,K2,K3,按键的设置用来调整时间,一共三个按键,按键K1用来选择要调的对象,比如时分秒,每按一次K2,所选择的对象加一,每按一次K3,所选择的对象加减一。
在进行调试的时候,单片机的中断停止,时间是不会计时的,光标闪烁。
四电路原理图
5软件设计
中断程序interrupt1就是计时程序。
在MAIN函数中,通过不断查询keyscan函数;
来判断是否有键按下,如果K1键按下,进入keyscan函数,次是中断关闭,每按一次则计数加1,每次加一则选择不同的对象,递推,一个周期,中断打开,时间正常运行,在调时期间,K2为加1功能,K3为减1功能。
六总结
通过一个月的努力,在老师与同学们的指导帮助下,本次的设计顺利的完成了。
这次做论文的经历也会使我终身受益,我感受到做论文是要真真正正用心去做的一件事情,是真正的自己学习的过程和研究的过程,没有学习就不可能有研究的能力,没有自己的研究,就不会有所突破。
希望这次的经历能让我在以后学习中激励我继续进步。
不积跬步何以至千里,本设计能够顺利的完成,也归功于导师的认真负责,使我能够很好的掌握和运用专业知识,并在设计中得以体现。
正是有了他们的悉心帮助和支持,才使我的毕业论文工作顺利完成。
附录
#include"
reg52.h"
#defineucharunsignedchar
#defineuintunsignedint
ucharcodetable[]="
0000-00-00000"
;
//初始化日期和星期
ucharcodetable1[]="
00:
00:
00"
;
//初始化时间
ucharcodetable2[][3]={"
MOD"
"
TUE"
WED"
THU"
FRI"
SAT"
SUN"
};
//定义星期数组
uintcodetable3[]={31,31,28,31,30,31,30,31,31,30,31,30,31};
//定义月数组
//以下三个是定义LCD的引脚
sbitlcden=P2^6;
sbitlcdwrite=P2^5;
sbitlcdrs=P2^4;
//定义四个功能开关
sbits1=P1^1;
sbits2=P1^2;
sbits3=P1^3;
sbits=P1^7;
sbitlb=P1^4;
//定义时间、时、分、秒、年、月、日等变量
uchartime;
charhour,min,sec,day,mon,year1,year2,xingqi,num;
//延时程序
voiddelay(uintz)
{
uintx,y;
for(x=z;
x>
0;
x--)
for(y=110;
y>
y--);
}
//lcd的写指令
voidwrite_com(ucharcom)
lcdrs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
//lcd的写数据
voidwrite_date(uchardate)
lcdrs=1;
P0=date;
voidinit()
ucharnum;
lcdwrite=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;
num<
15;
num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
12;
write_date(table1[num]);
TMOD=0x11;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
TH1=(65536-500)/256;
TL1=(65536-500)%256;
ET1=1;
//时间走动的显示
write_hms(ucharadd,ucharda)
ucharshi,ge;
shi=da/10;
ge=da%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}//日期走动的显示
write_ymd(ucharadd,ucharda)
write_com(0x80+add);
//星期走动的显示
voidwrite_xingqi(charxingqi)
charnum;
write_com(0x80+12);
for(num=0;
3;
num++)
write_date(table2[xingqi][num]);
//键盘扫描
voidkeyscan()
s=0;
if(s1==0)//如果S1按下去,执行相应的操作
{
//消除抖动
if(s1==0)
num++;
while(!
s1);
if(num==1)
TR0=0;
//关定时器
write_com(0x80+0x40+11);
//选定秒
write_com(0x0f);
}
}
if(num==2)//选定分
write_com(0x80+0x40+8);
if(num==3)//选定时
write_com(0x80+0x40+5);
if(num==4)//选定星期
write_com(0x80+12);
if(num==5)//选定日
write_com(0x80+10);
if(num==6)//选定月
write_com(0x80+7);
if(num==7)//选定年后两位
write_com(0x80+4);
if(num==8)//选定年前两位
write_com(0x80+2);
if(num==9)//恢复
num=0;
//重复开定时器
if(num!
=0)
if(s2==0)//如果s2按下调理参数
if(s2==0)
s2);
sec++;
//调秒并显示加1
if(sec==60)
sec=0;
write_hms(10,sec);
if(num==2)//调分并显示加1
min++;
if(min==60)
min=0;
write_hms(7,min);
if(num==3)//调时并显示加1
hour++;
if(hour==24)
hour=0;
write_hms(4,hour);
if(num==4)//调星期并显示加1
xingqi++;
if(xingqi==7)
xingqi=0;
write_xingqi(xingqi);
write_com(0x80+14);
if(num==5)
day++;
//调日并显示加1
if(day==table3[mon]+1)
day=1;
write_ymd(9,day);
if(num==6)//调月并显示加1
mon++;
if(mon==13)
mon=1;
write_ymd(6,mon);
if(num==7)//调年前位并显示加1
year1++;
if(year1==100)
year1=0;
write_ymd(3,year1);
if(num==8)//调年后位并显示加1
year2++;
if(year2==100)
year2=0;
write_ymd(1,year2);
if(s3==0)
s3);
if(num==1)//调秒并显示减1
sec--;
if(sec==-1)
sec=59;
if(num==2)//调分并显示减1
min--;
if(min==-1)
min=59;
if(num==3)//调时并显示减1
hour--;
if(hour==-1)
hour=23;
if(num==4)//调星期并显示减1
xingqi--;
if(xingqi==-1)
xingqi=6;
if(num==5)//调日并显示减1
day--;
if(day==0)
day=table3[mon];
if(num==6)//调月并显示减1
mon--;
if(mon==0)
mon=12;
if(num==7)//调年前两拉并显示减1
year1--;
if(year1==-1)
if(num==8)//调年后两拉并显示减1
year2--;
if(year2==-1)//减1到0重设为0
//主函数
voidmain()
init();
while
(1)
{if(min==1)
{TR1=1;
if(min==2)
{TR1=0;
keyscan();
voidtimer1()interrupt3
{TL1=(65536-500)%256;
lb=~lb;
//中断定时
voidtimer0()interrupt1
//定时50ms
time++;
if(time==20)//1s定时到
time=0;
//秒加1
//分钟加1
//小时加1
//日期的日加1
//星期加1
//月加1
if(mon==13)//加到13重设为1
if(year1==100)//年前两位加到100重设为0
//年后两位加1
if(year2==100)//年后两位加到100重设为0
if(xingqi==7)//如果星期到七就设为0