万年历程序和电路图.docx
- 文档编号:28415013
- 上传时间:2023-07-13
- 格式:DOCX
- 页数:52
- 大小:112.20KB
万年历程序和电路图.docx
《万年历程序和电路图.docx》由会员分享,可在线阅读,更多相关《万年历程序和电路图.docx(52页珍藏版)》请在冰豆网上搜索。
万年历程序和电路图
引言
单片机就是微控制器,是面向应用对象设计、突出控制功能的芯片。
单片机接上晶振、复位电路和相应的接口电路,装载软件后就可以构成单片机应用系统。
将它嵌入到形形色色的应用系统中,就构成了众多产品、设备的智能化核心。
本设计就是应用单片机强大的控制功能制作而成的电子万年历,该电子万年历包括三大功能:
实时显示年、月、日、时、分、秒;实现位调;附加播放音乐功能。
本设计是基于AT89C51和LCD1602液晶显示器设计的可调式电子钟。
该单片机采用的MCU51内核,因此具有很好的兼容性,内部带有4KB的ROM,能够存储大量的程序,最突出特点是具有ISP在系统烧写功能,使得烧写程序更加方便。
显示器件采用通用型1602液晶,可显示32个字符,如果使用数码管来做显示器件需消耗大量的系统资源,因此采用低功耗的1602液晶,该液晶显示方便,功能强大,完全能满足数字万年历的显示要求。
通过此次设计能够更加牢固的掌握单片机的应用技术,增强动手能力、硬件设计能力以及软件设计能力。
第一章设计方案
1.1.硬件设计
1.1.1设计要求
实现年月日、时分秒、星期的显示功能,用两个按键来实现日期和时间的调整功能,调整要求星期能自动更新,且能实现位调。
显示格式:
四位年,两位月,两位日,星期字母前三位,两位时,两位分,两位秒。
比如:
YYYY-MM-DDWEEK
HH:
MM:
SS
1.1.2硬件框图
控制芯片
显示器
按键调整
图1-1-硬件框图
日期时间由硬件软件结合产生;按键之间相互配合完成当前日期时间的调整功能。
过程与结果由控制芯片分别输出到显示器上。
本设计附加了播放音乐的功能。
音乐从蜂鸣器产生。
1.1.3硬件选择
1).显示模块
本设计具体选用与实际应用与消耗资源相关。
万年历用到的地方大多都在室内。
现市场上与许多显示器,在日常生活中最常见的有数码管,led点阵屏,lcd液晶显示器等。
八段数码管的优点:
亮度高,显示大。
驱动部份的软件简单;缺点:
与液晶相比,耗电及体积大。
数码管只能单纯的显示数字,不能生动的表达各个参数的信息,消耗电力也比led液晶显示器大。
LCD液晶显示器它是一种专门用来显示字母、数字、符号等的点阵型液晶模块,在单片机系统中应用晶液显示器作为输出器件有以下几个优点:
显示质量高,由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。
因此,液晶显示器画质高且不会闪烁。
数字式接口,液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
体积小、重量轻,液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。
功耗低,相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
Lcd液晶能一屏把本设计所要显示的信息表达完整。
而且lcd耗电小,体积小很适合与室内使用。
本设计的要求日期时间以数字表示、星期用3位英文字符表示共21个字符,lcd1602能显示32个字符,足以完成显示功能。
Lcd1602有16个引脚,各个引脚功能见下表:
引脚号
引脚名
电平
输入/输出
作用
1
VSS
电源地
2
VDD
Vcc
电源(+5v)
3
VEE
对比调整电压
4
RS
0/1
输入
0=输入指令,1=输入数据
5
R/W
0/1
输入
0=向lcd写入数据或指令
1=从lcd读取数据
6
E
1,1->0
输入
使能信号,1=读取信息
1->0(下降沿)执行指令
7
DB0
0/1
输入/输出
数据总线line0
8
DB1
0/1
输入/输出
数据总线line1
9
DB2
0/1
输入/输出
数据总线line2
10
DB3
0/1
输入/输出
数据总线line3
11
DB4
0/1
输入/输出
数据总线line4
12
DB5
0/1
输入/输出
数据总线line5
13
DB6
0/1
输入/输出
数据总线line6
14
DB7
0/1
输入/输出
数据总线line7
15
A
Vcc
Lcd背光正极
14
K
Lcd背光负极
表1-1lcd1602引脚及功能
2).按键与蜂鸣器
本设计选用轻触按钮,型号为XDJT1102S。
选用压电式蜂鸣器型号PT-1540PRoHS。
3).控制芯片
根据lcd1602液晶显示器与按键的引脚I/O数量以及扩展功能的要求,所选控制芯片至少需要三组I/O口,本设计功能简单,所以程序量较小,AT89C51是一种带4K字节闪存只读存储器的低电压、高性能CMOS8位微处理器。
AT89c51是51系列基本的控制芯片,能满足本设计的要求,性价比也要低于51系列其他的芯片。
4).日期时间生成模块
为了减少成本,使用51的内部定时器中断再配合软件计数的方式来生成一秒的时间。
1.2软件设计
1.2.1编程环境及语言:
本设计的原理图实现是在proteus中实现的,本设计的程序在keilUvision4环境中进行编程与调试的,keilUvision4与proteus联调能有效的对各个设计进行测试。
编程语言51C。
1.2.2程序框图
图1-2程序框图
1).time0中断用于生成时间,具体由程序和硬件共同产生1秒的时间。
2).两个外部中断能进行时间日期的切换,和对时间日期进行调整,播放音乐,能满足对按键设置的要求。
3).主函数能及时在液晶屏上显示默认的时间和调整后的时间。
第二章系统设计
2.1硬件设计
2.1.1振荡电路
本设计51芯片选用内部振荡器方式。
由于本设计的时间由内部定时器中断与软件计数相结合产生的,所以从计算方便以及系统的效率上考虑,本设计选用12MHz频率的晶振,电路原理图如下:
图2-1AT89C51的振荡电路
经厂家推荐稳定电路的电容C1,C2=30pF+-10p(附录资料AT89C51.PDF第4-32页)。
2.1.2复位电路
本设计使用上电复位电路。
单片机晶振为12MHz,起振时间将近1ms,单片机1个机器周期的时间为1us。
单片机每次上电复位所需的最短延时应该不小于treset。
这里,treset等于上电延时与起振延时之和。
从实际上讲,延迟一个treset往往还不够,不能够保障单片机有一个良好的工作开端。
复位电路把单片机锁定在复位状态上并且维持一个延时(记作TRST),以便给予电源电压从上升到稳定的一个等待时间;在电源电压稳定之后,再插入一个延时,给予时钟振荡器从起振到稳定的一个等待时间;在单片机开始进入运行状态之前,还要至少推迟2个机器周期的延时间。
单片机是高电平的时候复位,一般是用电阻和电容组成的,电容充电的时RST复位端为高电平,此时单片机开始复位..电容充电完成,此时单片机复位完成。
由此电容值可取22uf,电阻值取10KΩ。
详细见附录文件(电容充电时间的计算方法.pdf)
图2-2AT89C51上电复位电路
2.1.3按键
选用两个轻触按键与单片机P3^2(int0)、P3^3(int1)两个引脚相接组成的独立按键。
2.1.4lcd显示电路
1).lcd的选用
本设计选用型号为LCD-016M002L显示器。
具体资料见附录文件LCD-016M002L.pdf。
2).lcd与51引脚的连接
Lcd1602引脚
AT89C51引脚
LCD1602引脚
AT89C51引脚
RS
P2^0
DB3
P0^3
R/W
P2^1
DB4
P0^4
E
P2^2
DB5
P0^5
DB0
P0^0
DB6
P0^6
DB1
P0^1
DB7
P0^7
DB2
P0^2
表2-1lcd1602与51的连接
VEE为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
图2-31602液晶与单片机接口电路
2.1.5音乐播放电路
此模块采用蜂鸣器实现,蜂鸣器驱动电流为20mA,单片机的P1口输出电流为26mA能够直接驱动蜂鸣器。
只要编写相应的程序即可实现发出不同频率的声音,蜂鸣器与单片机的接口电路,蜂鸣器接线与单片机P1^7引脚相连。
图2-5蜂鸣器电路
2.1.6P0上拉电阻计算
由于lcd数据口是与51的P0口连接的,在P0口做一般I/O使用时要外接上拉电阻。
根据LCD-016M002L显示器的伏安特性,要保证上拉电阻明显小于lcd的阻抗,以使高电平时输出有效
Lcd工作电压:
+5V
Lcd工作电流:
20mA
lcd阻抗=5v/20mA=2.5kΩ。
上拉电阻值可以取2.2kΩ(详细见附录资料上拉电阻下拉电阻的总结.doc),由于需要八个相同的上拉电阻如图2-6所示,也可用一个排阻。
具体型号见附录表。
图2-6上拉电阻
2.2软件设计
2.2.1程序流程图
图2-6主函数流程图2-7time0中断服务程序流程
图2-8int1中断服务流程
开始
定时器停止工作,调整指针加1。
调状态标志置1,秒清零。
等待按键松开。
判断调整指针是否增到上限值(即调整完毕)
指针复位。
调整状态标志清零,定时器开始工作。
返回
是
否
图2-9int0中断服务流程
2.2.2流程的各个模块设计
全局变量
datetime数组保存日期时间星期的容器。
min[2],hour[2],day[2],mon[2],year[4];调整时候使用的中间变量。
buffer_date[16],buffer_time[16]显示缓冲区。
1).定时器中断服务程序
定时器1计时一秒。
计数初值的计算方法如下:
设晶振频率为f,则定时/计数器计数频率为f/12,定时/计数器的计数总次数T_all在方式1为216=65536,定时间隔为T,计数初值为a,则有a=-T×f/12
将计数初值a分别赋给加1计数器TH0、TL0:
TH0=(T_all-a)/256;
TL0=(T_all-a)%256;
本设计晶振频率为12MHz,定时间隔为50ms,所以
a=-0.05*12000000/12
a=50000
TH0=(65536-50000)/256
TL0=(65536-50000)%256
1s就要计20次,中断服务程序如下:
voidtime0()interrupt1using3
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
if(++count==20)//计时一秒
{
count=0;
DATATIME();//按实际规则日期时间更新
}
}
2).int0中断服务程序
按键1接在了int0对应的引脚P3^2。
按键2接在了int1对应的引脚P3^3。
Int0为电平触发方式,int1为边沿触发方式。
由于按键2是一键多功能,具体功能由状态标志FLAG表明。
所以在int0中断服务程序中要有对FLAG标志的置位及清位的操作。
在调整期间为了时间准确定时器不能工作,为了对日期时间的各位值进行循环调整,设置了一个计数器,它的值表明要调整的是哪位。
终端服务程序如下:
voidint0_K1()interrupt0
{
TR0=0;//定时器停止
cnum++;//计数器加1
FLAG=1;//标志位置位
datetime[0]=0;
while(K1==0);//等待按键松开
if(cnum>12)//调整结束,各个状态还原
{
TR0=1;
cnum=-1;
FLAG=0;
}
}
3).int1中断服务程序
Int1只要判断标志位执行任务就行了,中断服务程序如下:
voidint1_K2()interrupt2
{
if(FLAG==1)//调整状态下则位对应调整位的增值,正常状态则播放音乐
{
EDIT_datetime(cnum);//按计数器的值调整对应位
}
else
{
ShowString(0x00,0,"");//播放音乐是屏幕上的字幕
ShowString(0x00,1,happy);
music();
Delayms(500);
}
}
4).主函数程序
主函数对各个中断及lcd1602初始化后,就一直进行显示工作了,显示的时候判断标志FLAG以区别是正常显示还是闪烁显示。
主程序如下:
voidmain()
{
IE=0X87;//开中断ea=1,et0=1,et1=1,ex0=1
TCON=0X04;//it1为边沿触发,it0电平触发
IP=0X0a;//定时器0,1为高优先级
TMOD=0X01;//设置定时器0方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
Initialize_LCD();//初始化LCD
TR0=1;
while
(1)
{
buffer_value();//设置显示缓存区的内容
if(FLAG)//调整时对应调整位置闪烁
if(++refresh==5)
{
refresh=0;
Flash(cnum);
}
DIS_buffer();//将显示缓冲区的内容输出到lcd上
}
}
5).星期在调整是是自动更新的,这要归功于蔡勒公式。
算法如下(C51表示):
unsignedcharweek()
{
unsignedinty,m,c,s;
y=datetime[5]%100;
c=datetime[5]/100;
if(datetime[4]==1)
{m=13;
y--;
}
if(datetime[4]==2)
{m=14;
y--;
}
s=y+y/4+c/4-2*c+26*(m+1)/10+datetime[3]-1;//蔡勒公式
s=s%7;
returns;
}
函数返回值:
0-星期日,1-星期一……6-星期六
6).闰年是自动判断的,算法:
(year%4==0)&&(year%100!
=0)||year%400==0
函数代码如下:
unsignedcharYnian(unsignedcharyear)
{
if((year%400==0||year%4==0)&&(year%100!
=0))
return1;
else
return0;
}
是闰年返回1,否则返回0
7).月的天数判断,由于1,3,5,7,8,10,12每月有31天;4,6,9,11每月有30天;2月闰年29天,平年28天。
所以只要判断月号是哪一类的,就返回那类的值,2月用闰年判断算法判断。
函数代码如下:
unsignedcharMON(unsignedcharmonth)
{
switch(month)
{
case1:
case3:
case5:
case7:
case8:
case10:
case12:
return31;
case4:
case6:
case9:
case11:
return30;
default:
if(Ynian(datetime[5]))//二月特殊,闰年判断
return29;
else
return28;
}
}
返回各月的天数上限。
8).日期时间更新
按照实际规则更新,60秒一分,60分一时,24小时一日,30日或31日或28日或29日一月,12月一年。
函数代码如下:
voidDATATIME()
{
datetime[0]++;
if(datetime[0]>59)//秒判断
{
datetime[0]=0;
datetime[1]++;
}
if(datetime[1]>59)//分
{
datetime[1]=0;
datetime[2]++;
}
if(datetime[2]>23)//时
{
datetime[2]=0;
datetime[3]++;
}
if(datetime[3]>MON(datetime[4]))//日
{
datetime[3]=1;
datetime[4]++;
}
if(datetime[4]>12)//月
{
datetime[4]=1;
datetime[5]++;//年
}
//时刻为进入调整状态作准备,将当前日期时间值赋给调整时的变量
datetime[6]=week();min[0]=datetime[1]%10;
min[1]=datetime[1]/10;
hour[0]=datetime[2]%10;
hour[1]=datetime[2]/10;
day[0]=datetime[3]%10;
day[1]=datetime[3]/10;
mon[0]=datetime[4]%10;
mon[1]=datetime[4]/10;
year[0]=datetime[5]%10,year[1]=datetime[5]%100/10;
year[2]=datetime[5]%1000/100,year[3]=datetime[5]/1000;
}
9).调整日期时间函数,利用cnum计数器指定当前的调整属性,函数源代码如下:
voidEDIT_datetime(charcnum)
{
switch(cnum)
{
case0:
min[0]++;
if(min[0]>9)//分低位调整限制
min[0]=0;
break;
case1:
min[1]++;
if(min[1]>5)//分高调整限制
min[1]=0;
break;
case2:
hour[0]++;
if(hour[0]>9)//时低位调整限制
hour[0]=0;
break;
case3:
hour[1]++;
if(hour[1]>2)//时高位调整限制
hour[1]=0;
break;
case4:
day[0]++;
if(day[0]>9)//日低位调整限制
day[0]=0;
break;
case5:
day[1]++;
if(day[1]>3)//日高位调整限制
day[1]=0;
break;
case6:
mon[0]++;
if(mon[0]>9)//月低位调整限制
mon[0]=0;
break;
case7:
mon[1]++;
if(mon[1]>1)//月高位调整限制
mon[1]=0;
break;
case8:
year[0]++;//年调整
if(year[0]>9)
year[0]=0;
break;
case9:
year[1]++;
if(year[1]>9)
year[1]=0;
break;
case10:
year[2]++;
if(year[2]>9)
year[2]=0;
break;
case11:
year[3]++;
if(year[3]>9)
year[3]=0;
break;
}
datetime[1]=min[0]+min[1]*10;//调整后将datetime实时更新
datetime[2]=hour[0]+hour[1]*10;
datetime[3]=day[0]+day[1]*10;
datetime[4]=mon[0]+mon[1]*10;
datetime[5]=year[0]+year[1]*10+year[2]*100+year[3]*1000;
}
调整后能及时让datetime更新。
10).将datetime的日期时间星期按照格式放到缓冲区上,格式为:
YYYY-MM-DDweek
HH:
MM:
SS
函数源代码如下:
voidbuffer_value()
{
Format_Datetime(datetime[0],buffer_time+6);//将年月日时分秒星期,
Format_Datetime(datetime[1],buffer_time+3);//放到对应缓冲区的位置上
Format_Datetime(datetime[2],buffer_time+0);//以待显示
Format_Datetime(datetime[3],buffer_date+8);
Format_Datetime(datetime[4],buffer_date+5);
Format_Datetime(datetime[5]%100,buffer_date+2);
Format_Datetime(datetime[5]/100,buffer_date+0);
buffer_date[13]=week1[week()];
buffer_date[14]=week2[week()];
buffer_date[15]=week3[week()];
}
Lcd1602显示的是字符,所以用函数转换。
Format_Datetime(数组1,数组2)
功能:
将数组1的数值转换为字符放到数组2。
11).闪烁显示,在主函数显示配合延时清空,写入缓冲区的内容,达到闪烁效果。
具体哪位闪烁还是有cnum决定。
函数源代码如下:
voidFlash(charn)
{
switch(n)
{
case0:
buffer_clr(0,4);//对应分低位置,清空
break;
case1:
buffer_clr(0,3);
break;
case2:
buffer_clr(0,1);
break;
case3:
buffer_clr(0,0);
break;
case4:
buffer_clr(1,9);
break;
case5:
buffer_clr(1,8);
break;
case6:
buffer
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 万年历 程序 电路图