数字电子时钟实验报告.docx
《数字电子时钟实验报告.docx》由会员分享,可在线阅读,更多相关《数字电子时钟实验报告.docx(11页珍藏版)》请在冰豆网上搜索。
![数字电子时钟实验报告.docx](https://file1.bdocx.com/fileroot1/2022-12/9/872d8191-af56-4d7e-9dd7-7567b7f9cfac/872d8191-af56-4d7e-9dd7-7567b7f9cfac1.gif)
数字电子时钟实验报告
理工大学
嵌入式接口技术综合实验报告
题目数字时钟程序设计
二级学院计算机科学与工程
专业计算机科学与技术
班级37-3
学生姓名许鸿兴
教师
时间
成绩
、实验名称
、实验目的
二、实验设备与环境
四、实验基本原理
五、实验容(包括主要算法分析与流程图)
六、实验源程序及分析
七、实验运行结果及分析
八、实验心得体会
一、实验名称
数字时钟程序设计
二、实验目的
熟悉单片机数码管、按键等的应用,了解并掌握单片机中断、定时的使用等。
三、实验设备与环境
微机、AT89S52单片机、KeiluVision4软件等。
四、实验基本原理
本实验采用的数码管为共阳极数码管。
数码管是一种把多个LED显
示段集成在一起的显示设备。
有两种类型,一种是共阳型,一种是共阴型。
共阳型就是把多个LED显示段的阳极接在一起,又称为公共端。
共阴型就是把多个LED显示段的阴极接在一起,即为公共端。
阳极即为二极管的正极,又称为正极,阴极即为二极管的负极,又称为负极。
通常的数码管又分为8段,即8个LED显示段,这是为工程应用方便如设计的,分别为A、B、C、D、E、F、G、DP,其中DP是小数点位段。
而多位数码管,除某一位的公共端会连接在一起,不同位的数码管的相同端也会连接在一起。
即,所有的A段都会连在一起,其它的段也是如此,这是实际最常用的用法。
数码管显示方法可分为静态显示和动态显示两种。
动态显示:
所谓动态显示,就是一位一位的轮流点亮各个位,对于
显示器的每一位来说,每隔一段时间点亮一次。
禾I」用人的视觉暂留功能
可以看到整个显示,但必须保证扫描速度足够快,字符才不闪烁。
显示器的亮度既与导通电流有关,也于点亮时间与间隔时间的比例有关。
调整参数可以实现较高稳定度的显示。
动态显示节省了I/O口,降低了能
耗。
五、实验容(包括主要算法分析与流程图)
整个系统采用AT89S52作为时钟控制芯片,利用单片机部的定时器计数器来实现的,它的处理过程如下:
首先设定单片机部的一个定时器计数器工作于定时方式,对机器周期计数形成基准时间,然后用另一个定时器计数器或软件计数的方法对基准时间计数形成秒,秒计60次形
成分,分计60次形成小时,小时计24次则计满一天,再通过判断平年、闰年,计数相应的月份天数以及年份天数。
然后通过数码管把它们的容在相应位置显示出来即可。
数码管显示采用动态显示方法,动态显示方法线路相对简单,但需
动态扫描,扫描频率要大于人眼视觉暂留频率,信息看起来才稳定。
在具体处理时,定时器计数器采用中断方式工作,对时钟的形成在中断服务程序中实现。
在主程序中只需对定时器计数器初始化、调用显示子程序和控制子程序。
另外,为了使用方便,设计了简单的按键,可以通过按键实现时间调整和复位。
函数Jude_Show()进行时间判断并输出显示。
首先使用定时器0方式2进行计时,计时1S后Sec自加,Sec自加至60(60秒)后Min自加并将Sec置零,Min自加至60(60分)后Hour自加,并将Min置零,
Hour自加至24(24小时)Day自加并将Hour清零。
此时进行平年闰年的判断,如果年份为闰年,则2月天数为28天,如果为平年,则2月的天数为29天,其余相同。
当天数记满相应的一个月后,Month自加,
当月数自加至12(12月)后,年份自加。
而后刷新显示缓存输出显示。
主要流程图如下:
1、主流程图:
设置初值
方式二动态扫描
显示
闹钟判断
闹钟
2、万年历:
秒自加
秒=60
rr
分自加
分=60
时自加
时=24
天自加
1
平年闰年判断
天=相应月份天数
相应月份自加
月份=12
年份自加
六、实验源程序及分析
#include
unsignedintYear=0,Month=O,Day=O,Sec=O,Min=0,Hour=0;//初始
显示的时间
unsignedint
Fir_year=0,Fir_month=O,Fir_day=O,Fir_Sec=O,Fir_Min=0,Fir_Hour=0;//
设置闹钟的时间1
unsignedint
Sec_year=0,Sec_month=O,Sec_day=O,Sec_Sec=O,Sec_Min=0,Sec_Hour=0;
//设置闹钟的时间2
unsignedint
Thi_year=0,Thi_month=O,Thi_day=O,Thi_Sec=O,Thi_Min=0,Thi_Hour=0;
//设置闹钟的时间3
unsignedint
Fou_year=O,Fou_month=0,Fou_day=0,Fou_Sec=0,Fou_Min=0,Fou_Hour=0;
//设置闹钟的时间4
unsignedintOs=O;//系统时钟
unsignedintshift=Oxfe,pDG=O;//初始位码以及动态扫描初值
unsignedcharDis[8];//缓存显示码
sbitbeep=P3A7;//蜂鸣器
unsignedcharcodedisplay[]=
{0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xBF};//0-9以及”-”段码
voidFirst_Time()//设置初始显示的时间
Year=2016;
Month=4;
Day=3;
Hour=12;
Min=23;
Sec=35;
}
voidSet_Time()
{
Fir_year=2016;//设置闹钟1时间
Fir_month=4;
Fir_day=3;
Fir_Hour=12;
Fir_Min=23;
Fir_Sec=40;
Sec_year=2016;//设置闹钟2时间
Sec_month=4;
Sec_day=3;
Sec_Hour=12;
Sec_Min=23;
Sec_Sec=45;
Thi_year=2016;//设置闹钟3时间
Thi_month=4;
Thi_day=3;
Thi_Hour=12;
Thi_Min=23;
Thi_Sec=50;
Fou_year=2016;//设置闹钟4时间
Fou_month=4;
Fou_day=3;
Fou_Hour=12;
Fou_Min=23;
Fou_Sec=55;
}
voidJude_Time()//判断时间是否到闹钟时间
{
if(Year==Fir_year&&Month==Fir_month&&Day==Fir_day&&Hour=
=Fir_Hour&&Min==Fir_Min&&Sec<=Fir_Sec+2&&Sec>=Fir_Sec)
beep=!
beep;〃蜂鸣器响3秒else
if(Year==Sec_year&&Month==Sec_month&&Day==Sec_day&&Hour==Sec_Hour&&Min==Sec_Min&&Sec<=Sec_Sec+2&&Sec>=Sec_Sec)
{
beep=!
beep;〃蜂鸣器响3秒
}
else
if(Year==Thi_year&&Month==Thi_month&&Day==Thi_day&&Hour==Thi_
Hour&&Min==Thi_Min&&Sec<=Thi_Sec+2&&Sec>=Thi_Sec)
{
beep=!
beep;〃蜂鸣器响3秒
}
else
if(Year==Fou_year&&Month==Fou_month&&Day==Fou_day&&Hour==Fo
u_Hour&&Min==Fou_Min&&Sec<=Fou_Sec+2&&Sec>=Fou_Sec)
{
beep=!
beep;〃蜂鸣器响3秒
}
}
voidJude_Show()//判断显示
Sec++;
if(Sec==60)
{
Min++;
Sec=0;//秒自加到60自身置零,分+1
if(Min==60)
{
Hour++;
Min=0;//分自加到60自身置零,时+1
if(Hour==24)
{
Day++;
if((Year%400==0)||(Year%4==0)&&(Year%100!
=0))//
判断闰年
{
if(Month==1||Month==3||Month==5||Month==7||Month==8||Month==
10||Month==12)//每个有月31天的月份
if(Day==31)〃天数增至31,月份加1,Day置
Month++;
Day=0;
}
}
else
if(Month==4||Month==6||Month==9||Month==11)〃每个月有30天的月数
{
if(Day==30)〃天数增至30,月份加1,Day置
零
{
Month++;
Day=0;
}
}
else//二月
{
if(Day==28)〃天数增至28,月份加1,Day置
零
{
Month++;
Day=0;
if(Month==12)//月份增至12,年份自加
{
Year++;
}
}
else
//平年
{
if(Month==1||Month==3||Month==5||Month==7||Month==8||Month==
10||Month==12)//每个有月31天的月份
{
if(Day==31)〃天数增至31,月份加1,Day置
零
{
Month++;
Day=0;
}
}
else
if(Month==4||Month==6||Month==9||Month==11)〃每个月有30天的月数
if(Day==30)〃天数增至30,月份加1,Day置
零
{
Month++;
Day=0;
}
}
else//二月
{
if(Day==29)〃天数增至29,月份加1,Day置
零
{
Month++;
Day=0;
}
}
if(Month==12)〃月份增至12,年份自加
{
Year++;
}
}
//刷新显示缓冲区
Dis[6]=display[Hour%10];//时个位显示码
Dis[7]=display[Hour/10];//时十位显示码
Dis[3]=display[Min%10];//分个位显示码
Dis[4]=display[Min/10];//分十位显示码
Dis[0]=display[Sec%10];//秒个位显示码
Dis[1]=display[Sec/10];//秒十位显示码
}
voidTask1ms()
{
P2=0xff;
P0=Dis[pDG];
P2=shift;
shift=(shift<<1)|1;
pDG++;
if(pDG==8)
//初始关闭显示
//送段码
//送位码
//左移一位,修改位码
//循环动态扫描
pDG=0;
shift=Oxfe;
//位码加至8循环至1
}
}
voidintt()〃初始化
{
TMOD=0x02;
THO=TL0=0x1A;
256-(250*11.0592/12)=25.6(D)=1A(H)
TR0=1;
ET0=1;
EA=1;
}
voidmain(void)
{
P0=0xff;
P1=0xff;
P2=0xff;
P3=0xff;
//工作方式2
〃250us定时常数
//开启Timer0中断
//允许Timer。
中断
//允许总中断
//端口初始化
intt();//初始化
Dis[5]=Dis[2]=display[10];//显示"-"
Dis[0]=Dis[1]=Dis[3]=Dis[4]=Dis[6]=Dis[7]=display[0];//显示"0"
First_Time();//设置初始时间
Set_Time();〃设置闹钟时间
while
(1)
{
Jude_Time();
Jude_Show();
}
}
voidTimeO(void)interrupt1//TimeO中断服务子函数(负责计时1s)
{
Os++;
if(0s==4000)
{
Sec++;
Os=0;
}
Task1ms();
}
七、实验运行结果及分析
数码管稳定显示以秒为基本单位的时间显示,到达设定的闹钟时间,蜂鸣器响三秒,部生成万年历。
八、实验心得体会
通过这次试验设计,我更加熟悉、掌握了一定的有关单片机的程序设计
开发,加固了多编写代码的好习惯。