单片机原理及应用实验报告时钟设计.docx
《单片机原理及应用实验报告时钟设计.docx》由会员分享,可在线阅读,更多相关《单片机原理及应用实验报告时钟设计.docx(18页珍藏版)》请在冰点文库上搜索。
![单片机原理及应用实验报告时钟设计.docx](https://file1.bingdoc.com/fileroot1/2023-5/17/1112f4bd-26bd-4276-b680-d3f320ea0415/1112f4bd-26bd-4276-b680-d3f320ea04151.gif)
单片机原理及应用实验报告时钟设计
单片机原理及应用实验报告
班级:
测控0X-X学号:
090340101XX姓名:
CHNlyt成绩:
数字时钟设计
一、实验目的:
1.进一步掌握8255A编程原理、掌握解键盘电路的工作原理、掌握键盘接口电路的编程方法。
2.进一步掌握定时器的使用和编程方法。
掌握七段数码显示数字的原理。
掌握用一个段锁存器,一个位锁存器同时显示多位数字的技术。
3.掌握电子时钟的设计方法。
二、实验设备:
计算机、proteus软件。
三、实验内容:
使用8051制作数字电子时钟,这个时钟使用键盘和6个共阳七段显示器组成。
键盘按键用来设置时间,6个七段显示器则用来显示时间。
一下为数字时钟的基本功能;
1、6个七段显示器用来显示时分秒,每个占2位。
2、用户可以设置数字时钟的时间。
设置时间必须单击模式选择键,进入时间调整模式,然后单击确定按键进入正确的时间。
3、数字时钟只有两种模式,分别是显示时间和调整时间模式。
四、实验原理
(一)键盘扫描原理
1、识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如所读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
本实验例程采用的是行反转法。
行反转法识别键闭合时,要将行线接一并行口,先让它工作于输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口往各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上的输入值,那么,在闭合键所在的行线上的值必定为0。
这样,当一个键被按下时,必定可以读得一对唯一的行线值和列线值。
2、程序设计时,要学会灵活地对8255A的各端口进行方式设置。
3、程序设计时,可将各键对应的键值(行线值、列线值)放在一个表中,将要显示的0~F字符放在另一个表中,通过查表来确定按下的是哪一个键并正确显示出来。
(二)数码管显示原理
1、利用实验箱上的8255A可编程并行接口芯片和矩阵键盘,编写程序,做到在键盘上每按一个时间数字,用发光二极管将该代码显示出来。
2、本试验采用动态显示。
动态显示就是一位一位地轮流点亮显示器的各个位(扫描)。
将80C52CPU的P1口当作一个位锁存器使用,74LS273作为段锁存器。
五、程序框图
六、程序清单
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitdula=P2^6;
sbitwela=P2^7;
sbitset=P3^6;
sbitbeep=P2^3;
ucharcodetable[]=
{0X3f,0X06,0X5b,0X4f,
0X66,0X6d,0X7d,0X07,
0X7f,0X6f,0x40
};
ucharhourH,hourL,minuteH,minuteL,secondH,secondL;
ucharkey,count;
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
//结构体变量
structtime
{
unsignedcharsecond1;
unsignedcharsecond2;
unsignedcharminute1;
unsignedcharminute2;
unsignedcharhour1;
unsignedcharhour2;
}time1;
voiddisplay(secondL,secondH,minuteL,minuteH,hourL,hourH)
{
dula=1;
P0=table[hourH];
dula=0;
P0=0xff;
wela=1;
P0=0xfe;
wela=0;
delay
(1);
dula=1;
P0=table[hourL];
dula=0;
P0=0xff;
wela=1;
P0=0xfd;
wela=0;
delay
(1);
dula=1;
P0=table[minuteH];
dula=0;
P0=0xff;
wela=1;
P0=0xfb;
wela=0;
delay
(1);
dula=1;
P0=table[minuteL];
dula=0;
P0=0xff;
wela=1;
P0=0xf7;
wela=0;
delay
(1);
dula=1;
P0=table[secondH];
dula=0;
P0=0xff;
wela=1;
P0=0xef;
wela=0;
delay
(1);
dula=1;
P0=table[secondL];
dula=0;
P0=0xff;
wela=1;
P0=0xdf;
wela=0;
delay
(1);
}
voidinit()
{
wela=0;
dula=0;
count=0;
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
}
unsignedcharkeyscan()
{uchartemp;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xee:
key=0;
break;
case0xde:
key=1;
break;
case0xbe:
key=2;
break;
case0x7e:
key=3;
break;
}
while(temp!
=0xf0)
{
temp=P3;
temp=temp&0xf0;
beep=0;
}
beep=1;
}
}
P3=0Xfd;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xed:
key=4;
break;
case0xdd:
key=5;
break;
case0xbd:
key=6;
break;
case0x7d:
key=7;
}
while(temp!
=0xf0)
{
temp=P3;
temp=temp&0xf0;
beep=0;
}
beep=1;
}
}
P3=0XFB;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xeb:
key=8;
break;
case0xdb:
key=9;
break;
case0xbb:
key=10;
break;
}
while(temp!
=0xf0)
{
temp=P3;
temp=temp&0xf0;
beep=0;
}
beep=1;
}
}
returnkey;
}
voidtimer0()interrupt1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20)
{
count=0;
time1.second1++;
if(time1.second1>9)
{
time1.second1=0;
time1.second2++;
if(time1.second2>=6)
{
time1.second2=0;
time1.minute1++;
if(time1.minute1>9)
{
time1.minute1=0;
time1.minute2++;
if(time1.minute2>=6)
{
time1.minute2=0;
time1.hour1++;
if(time1.hour1>9)
{
time1.hour1=0;
time1.hour2++;}
else
{if(time1.hour1>=3&time1.hour2>=2)
{time1.hour1=0;
time1.hour2=0;
}
}
}
}
}
}
}
}
voidmain()
{ucharFlag;
init();
while
(1)
{
if(set==0)//设置标志位Flag
{
delay(50);
if(set==0)
{beep=0;
TR0=0;
Flag++;
if(Flag>6)//0:
显示时间,1:
小时调整,2:
分钟调整,3:
秒调整
Flag=0;
}
while(set==0)
beep=1;
}
switch(Flag)
{
case0:
TR0=1;
display(time1.second1,time1.second2,time1.minute1,time1.minute2,time1.hour1,time1.hour2);
break;
case1:
time1.hour2=keyscan();
if(time1.hour2>=2)
time1.hour2=2;
display(10,10,10,10,10,time1.hour2);
break;
case2:
//时钟小时调整
TR0=0;
time1.hour1=keyscan();
if(time1.hour2>=2&time1.hour1>=3)
time1.hour1=3;
display(10,10,10,10,time1.hour1,time1.hour2);
break;
case3:
//时钟分钟调整
time1.minute2=keyscan();
if(time1.minute2>=6)
time1.minute2=5;
display(10,10,10,time1.minute2,time1.hour1,time1.hour2);
break;
case4:
//时钟分钟调整
time1.minute1=keyscan();
display(10,10,time1.minute1,time1.minute2,time1.hour1,time1.hour2);
break;
case5:
//时钟秒调整
time1.second2=keyscan();
if(time1.second2>=6)
time1.second2=5;
display(10,time1.second2,time1.minute1,time1.minute2,time1.hour1,time1.hour2);
break;
case6:
//时钟秒调整
time1.second1=keyscan();
display(time1.second1,time1.second2,time1.minute1,time1.minute2,time1.hour1,time1.hour2);
break;
default:
break;
}
}
}
七、实验电路图
8、实验总结及心得:
经试验测试的该电路已经基本实现了计时、显示精度到秒、校时功能,整点报时、闹钟功能,当然电路仍有不足之处和需要改进之处,已经在分析各单元电路时进行了详细的分析。
在未能仿真之前,我先用数电理论知识设计一个理论上可行的计数电路,让思路更明显些。
仿真时才发现理论有时和仿真是两码事,比如用74160设计六十进制计数器时,中间要加反相器,仿真时就不用加,实在想不通咋回事。
设计时除了会用用中规模集成电路之外,还需学会用组合电路搭配出自己想要的电路。
比如说对“十”、“分”的选择调节,许多资料说用三个开关,通过计数器和数据选择器可以实现两个开关像电子表那样的调节。
对于整点报时电路,理论上计数到零时用来屏蔽计数脉冲但由于器件的传输时间未能完全屏蔽,减到零时还得来个置数回到计数初始值。
对闹钟电路,其实这是个笨方法,闹钟电路加上计数脉冲就成另一个计数钟了,以后可以尝试用随机存储器构建多闹钟电路。
仿真是理论学习的一个上升高度,是为进行实物获取的一个提前预测。
通过这实验可以感到除了对理论掌握之外对软件的学习是非常重要的,比如要是不会用总线就会扯很多线,电路就很复杂;如果把电路放在一个页内的,电路就会启动很慢,放在多页中建成子电路可以是层次模块更加明显。
由于以前对软件不熟悉,仿真走了许多弯路,其实数字钟还有很多扩展功能,如秒表,倒计时,十二和二十四制转换,星期,显示日期时间等。
通过这次仿真设计感到自己学习的还不够,虽然能设计出来但有些设计的电路很复杂,也许在实物制造方面是不可取的,以后更要加强对理论知识的学习,搭建出更加简洁的电路。