单片机课程设计电子钟.docx

上传人:b****2 文档编号:23473399 上传时间:2023-05-17 格式:DOCX 页数:25 大小:136.87KB
下载 相关 举报
单片机课程设计电子钟.docx_第1页
第1页 / 共25页
单片机课程设计电子钟.docx_第2页
第2页 / 共25页
单片机课程设计电子钟.docx_第3页
第3页 / 共25页
单片机课程设计电子钟.docx_第4页
第4页 / 共25页
单片机课程设计电子钟.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

单片机课程设计电子钟.docx

《单片机课程设计电子钟.docx》由会员分享,可在线阅读,更多相关《单片机课程设计电子钟.docx(25页珍藏版)》请在冰豆网上搜索。

单片机课程设计电子钟.docx

单片机课程设计电子钟

《微型计算机原理与应用》

课程设计报告书

课题名称:

基于51单片机的电子钟设计

姓名:

***

学号:

************

班级:

09卓越一班

指导教师:

***

 

电气工程学院

2012年1月10日

目录:

1、任务书...............................................................................2

2、系统总体设计方案规划与选定.......................................2

3、硬件设计...........................................................................5

4、软件设计...........................................................................6

5、调试...................................................................................8

6、新增功能及实现方法.......................................................8

7、小结与体会.......................................................................9

8、参考文献...........................................................................9

9、附录.................................................................................10

一任务书:

基于大三上学期我们所学过的清华大学出版社出版的《单片机原理,接口与应用》这门课程以及软件Keil—c51语言的学习,在最后的课程设计间断运用学过的基本理论知识,将理论联系实际,在实际的设计过程中体会单片机的真实应用以及用软件进行仿真所带来的方便性。

通过系统构造、流程设计、编程与调试的过程,掌握分析与解决实际问题的方法与手段,提高系统设计、程序编码与调试方面的实际动手能力,做一次实际的系统设计训练,从中体会理论与实践之间的联系与差别。

本次课程设计要完成硬件电路的设计和软件的编程,使设计的数字电子时钟可以完成以下几点功能:

1:

六个LED上实现正常的时间显示,24小时制

2:

实现时间的正确调节

3:

闹钟的定时及到时间之后的音乐响铃

4:

矩阵键盘,0到9键,光标的左移右移键,闹钟调节键,时间调节键,走时键,复位键,停止键等,其中涉及到某些键的复用

5:

实现秒表功能

在设计过程中还用到8255来扩展并行接口,要注意8255的地址问题。

同时在设计过程中还应该注意按键去抖问题,保证正确的读入按键值。

在键盘扫描时要正确的设置扫描频率,使数码管显示正常,人眼可以清晰分辨

二系统总体设计方案规划与选定

针对要实现的功能,拟采用AT89C51单片机进行设计,AT89C51单片机是一款低功耗,高性能CMOS8位单片机,片内含4KB在线可编程(ISP)的可反复擦写1000次的Flash只读程序存储器,器件采用高密度、非易失性存储技术制造,兼容标准MCS-51指令系统及80C51引脚结构[7]。

这样,既能做到经济合理又能实现预期的功能。

在程序方面,采用分块设计的方法,这样既减小了编程难度、使程序易于理解,又能便于添加各项功能。

程序可分为闹钟的音乐程序、时间显示程序、闹钟显示程序、调时显示、定时程序,走时程序,复位的模块化的程序。

硬件接线图如图所示:

对于程序的设计,遵循分块的原则,不同的子程序实现不同的功能,通过函数的调用实现相应的功能

主程序:

执行主程序,按照得到的的10到15键值转到相应的子程序去执行相应的功能。

模块一:

时间显示模块:

用51单片机的6个LED七段数码管,依次分别显示时,分,秒,中间用小数点分开。

正常走时时秒数满60进位,分钟加1,分钟满60小时加1,小时满24清0

模块二:

显示时间调整模块:

当按下键值为10的开关后,进入时间调整程序,对六个数码管相应位的的控制按照我们生活中的正常逻辑进行控制。

进行调整时间

模块三:

闹钟音乐模块:

当按下键值为11的开关后,进入闹钟时间设置状态,设定相应的时间,当到了设定的时间之后,进入产生中断,进入闹钟音乐程序

模块四:

键盘扫描得到按键值函数:

4*4矩阵键盘,用8255的PA口得到行值,p1口得到列值,最后得到按下开关的键值,根据键值转到相应的模块执行相应的功能。

各个模块程序设计好之后,要进行最后的整合,函数的调用参数设置要正确,使程序能够正常的运行,在keil上调试通过之后,检查proteus中硬件连接有没有错误,确定无误后,在proteus中进行模拟实验,最后可以到实验室进行真实元器件的连接,看一看真实电路与模拟电路之间有什么异同之处,比较总结,增加自己的编程与系统实验仿真能力。

三硬件设计

用到的元器件如下:

AT89C51:

该单片机功能强大,不仅能满足设计的需要,也可以在设计要求的基础上进行一些扩展。

单片机的结构如下:

主要应用AT89C51单片机的p1.0到p1.3得到键盘的列值,p1.7通过放大器进行功率放大控制喇叭的响音乐。

同时对单片机的并行接口扩展了一个8255,用p0.0和p0.1作为其地址线,同时用到了89c51的两个十六位定时计数器T0,T1,进行显示时间和闹钟响音乐的中断控制。

8255:

结构如下

8255是一个可编程并行接口芯片,有一个控制口和三个8位数据口,外设通过数据口与单片机进行数据通信,各数据口的工作方式和数据传送方向是通过用户对控制口写控制字控制的。

我们用到了PB,PC口进行对数码显示管的片选和段选,PA口得到按键的行值。

数码管:

数码管结构

 

使用共阴极数码管时将6个数码管按相同功能连接起来,3与8相连,当选通端所接管脚为低电平时该数码管选通。

单片机的P2口作为选通端,连接各数码管的3、8引脚轮流显示,连接时要加7407和上拉电阻。

单片机的P1口作为功能段,通高电平的引脚会使相应段亮起,同样的也要与7407和电阻连接使用。

四软件设计

关于电子钟的功能,划分出主要功能,次要功能。

程序的主要功能是准确的实现走时功能,我们用定时器来准确的设定时间(定时器T0准确设定中断时间为20ms,终端中统计50次中断即为一秒)。

而次要功能,则是修改时间,设定闹钟等。

在实现程序的同时,尽量使显示人性化,如LED显示时,光标的显示与移动可以方便的修改设定时间及闹钟。

1)主程序设计:

主程序中完成对8255芯片和定时器设置的初始化,然后进入无限循环的查询模块,动态扫描LED显示模块,使显示走时正常。

同时在循环中完成对矩阵键盘的状态(是否有键按下,如有是哪一个)进行监控,如果有键按下根据其键值跳转到相应的子程序中进行执行,完成相应的功能后会自动跳转回来。

这样整个程序就实现了连续有效的运行。

2)按键扫描子程序:

首先根据端口状态判断是否有键按下,如果没有就跳过读键值这个阶段。

如果有键按下就通过行列扫描判断出所按下键的位置,并相应的形成键值,保存在一个全局变量中等待被查询。

然后跳出子程序。

3)显示子程序:

该子程序在LED扫描中被调用。

首先根据参数判别是显示时间还是显示闹钟,然后针对六个位形成相应的段码值。

通过参数值在相应位输出显示。

4)时间及闹钟设定子程序:

本程序完成时间的修改及闹钟的设置,对时间和闹钟的设置是通过修改时间值的全局变量或闹钟值的全局变量来完成的。

在修改过程中正在修改位用光标来显示,按下数字后光标自动转移到下一位,可以通过左右移动光标来实现正在修改位的调整。

当六位全部修改完毕,或者按下确定/退出键后自动跳出子程序。

5)响铃子程序:

当设定的闹钟时间到时,转入本程序执行。

本程序通过读取频率表来设定T1定时中断的设定,以在响铃端口输出频率一定的脉冲波。

同时通过读取时间表控制每一频率所响的时间,这样就可以在扬声器输出音乐了。

同时在程序中添加了键盘扫描环节,一旦按下退出键,就关闭T1定时器,跳出程序,响铃就可以终止。

五调试

由于我们采用了“模块化”的编程思路,程序的调试变得相对简单。

首先我们编制出主程序,使走时功能正常完成,显示现在的时间,过程中出现的主要问题是动态扫面的相关参数设置不合理,显示出现不正常的现象;然后我们开始编写相关子程序,由于几个主要的子程序之间没有参数上的直接联系,所以我们分别编写各个子程序,调试功能无误后添加到主干程序中来。

由于程序编写分工完成,这个阶段碰到最大的问题之一就是程序中对变量的复杂定义极大的浪费了资源,甚至有些重名的非法定义。

然后我们通过设置几个统一的全局变量,在各个子程序中分别对全局变量做出不同的修改已完成不同的功能。

最后这个问题得到了比较好的解决。

程序调试中还出现了种种命令的错误使用,以及不注意所造成的错误,而更重要的是逻辑错误。

很多时候程序执行出来的结果和所设想的有很大差距,这就靠着不断的修正逻辑错误来调试。

六新增功能及实现方法

在原先的电子时钟基础上添加秒表功能,基本要求如下:

应具有开始,暂停,继续,清零的基本功能,并且要求在秒表模式下,不再对所定的闹钟有反应,即要求闹钟模式与时钟模式完全分离。

实现方法如下:

将键12,13,14复用,分别作为开始键,暂停(继续)键和清零键。

在键盘扫描过程中,如果扫描到14键按下,则转到清零函数,开始进入秒表模式。

由于在清零函数中,将变量pp置零,取消了闹钟模式,因此在秒表模式下不会出现闹铃响的情况。

按下键12,启动定时器T0工作,开始计时,当键盘扫描检测到13键按下时,令TR0取反,计时器T0停止工作,再按一下13键时,TR0再取反,T0又继续工作,这样就实现了暂停和继续的功能。

注意,在键盘扫描值得到以后因为要转向不同的处理程序,在处理程序中要将键值先修改,避免因键值不变,而重复进入子程序。

此处说明12,13键的复用原理:

12,13键作为时间模式下的光标左右移动键,是在先按下调时键(10键)或定时键(11键)后转向修改时间函数后才起作用的,而直接按下12,13键会自动转向秒表模式,不会进入时间模式,因此也就不会与此键的其他复用功能产生冲突。

七小结

项目进行中遇到了各种各样的问题,有些问题是预想中没有过的。

项目的开始主要问题是Keil所编写的程序如何导入到Proteus中,然后在Proteus中进行仿真。

程序正常编写过程中遇到的主要问题是逻辑的错误,往往很多程序的运行并不像预想的那样,所以往往要一遍遍重复的修改,这个工作量是相当大的。

其次,就是课本知识掌握并不是特别扎实,有些命令的使用出现了些许的小问题。

总之,这次的项目锻炼了我的能力,真正的把学到的知识运用到了实际当中去,做出的东西也很让人振奋。

八参考文献

【1】《单片机原理、接口及应用——单片机嵌入式系统技术基础(第2版)》,肖看、李群芳,清华大学出版社

【2】《51单片机开发与应用技术详解》,赵建领、薛圆圆,电子工业出版社

 

附录:

源程序代码

#include"Absacc.h"

#include"reg51.h"

//8255端口地址定义

#defineC8255_AXBYTE[0x7F00]

#defineC8255_BXBYTE[0x7F01]

#defineC8255_CXBYTE[0x7F02]

#defineC8255_CONXBYTE[0x7F03]

//键盘及数码管显示变量组

unsignedchardatatimer=0,second=0,minute=0,hour=0;

unsignedchardatasecond_bell=59,minute_bell=59,hour_bell=23;

unsignedcodetab_high[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

unsignedcodetab_low[10]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};

unsignedcodetab_position[6]={0x3e,0x3d,0x3b,0x37,0x2f,0x1f};

unsignedchartab2[6]={0x00,0x00,0x00,0x00,0x00,0x00};

unsignedcharkey_down;

unsignedcharkey_value;

unsignedcharflag,tab,pp=1;

unsignedchardataposition=0;

unsignedintval;

unsignedchari;

unsignedcharnumber=100;

//响铃函数变量组

#defineClk0x070000

sbitP17=P1^7;//扬声器控制引脚

unsignedchardataval_H;//计数器高字节

unsignedchardataval_L;//计数器低字节

//响铃音乐频率表

unsignedintcodefreq_list[]={371,495,495,495,624,556,495,556,624,

495,495,624,742,833,833,833,742,624,

624,495,556,495,556,624,495,416,416,

371,495,833,742,624,624,495,556,495,

556,833,742,624,624,742,833,990,742,

624,624,495,556,495,556,624,495,416,

416,371,495,0};

//响铃音乐频率对应时间表

unsignedcharcodetime_list[]={4,6,2,4,4,6,2,4,4,6,

2,4,4,12,1,3,6,2,4,4,

6,2,4,4,6,2,4,4,12,4,

6,2,4,4,6,2,4,4,6,2,

4,4,12,4,6,2,4,4,6,2,

4,4,6,2,4,4,12};

//延时函数

voiddelay_short(void)

{

inti=0;

for(i=0;i<=255;i++){}

}

//清除函数

voidclear()

{

timer=0;

second=0;

minute=0;

hour=0;

pp=0;

}

//***********************************//

//键盘函数组(包括按键扫描函数、得到按键值函数和键盘情况函数)

//按键扫描函数

voidkeyscan()

{

unsignedcharcc;

P1=0x00;

cc=C8255_C;key_down=(~cc)&0x0f;

}

//得到按键值函数

voidgetkey()

{

unsignedcharvalue;

unsignedchari,j=0x0e;

for(i=0;i<4;i++)

{

P1=j;

value=C8255_C&0x0f;

if(!

(value&0x01))

{

key_value=i+0;

return;

}

if(!

(value&0x02))

{

key_value=i+4;

return;

}

if(!

(value&0x04))

{

key_value=i+8;

return;

}

if(!

(value&0x08))

{

key_value=i+12;

return;

}

j<<=1;

}

}

//键盘情况函数

voidkeycondition()

{

keyscan();

if(key_down)

{

delay_short();

keyscan();

if(key_down)

{

getkey();

}

}

}

//***********************************//

//显示函数组(包括数码管显示函数和显示光标函数)

//数码管显示函数

voiddisplay(unsignedcharV,unsignedcharM)

{

if(M==0)

{

tab2[5]=hour/10%10;

tab2[4]=hour%10;

tab2[3]=minute/10%10;

tab2[2]=minute%10;

tab2[1]=second/10%10;

tab2[0]=second%10;

}

if(M==1)

{

tab2[5]=hour_bell/10%10;

tab2[4]=hour_bell%10;

tab2[3]=minute_bell/10%10;

tab2[2]=minute_bell%10;

tab2[1]=second_bell/10%10;

tab2[0]=second_bell%10;

}

if(V==0)

{

C8255_A=tab_position[0];

C8255_B=tab_high[tab2[5]];

delay_short();

}

if(V==1)

{

C8255_A=tab_position[1];

C8255_B=tab_low[tab2[4]];

delay_short();

}

if(V==2)

{

C8255_A=tab_position[2];

C8255_B=tab_high[tab2[3]];

delay_short();

}

if(V==3)

{

C8255_A=tab_position[3];

C8255_B=tab_low[tab2[2]];

delay_short();

}

if(V==4)

{

C8255_A=tab_position[4];

C8255_B=tab_high[tab2[1]];

delay_short();

}

if(V==5)

{

C8255_A=tab_position[5];

C8255_B=tab_high[tab2[0]];

delay_short();

}

}

//显示光标函数

voiddisplay_cursor(unsignedcharV)

{

if((V%2)==0)

tab=0x08;

if((V%2)==1)

tab=0x88;

C8255_A=tab_position[V];

C8255_B=tab;

delay_short();

}//**********************************//

//响铃函数

voidbell_sound(void)

{

unsignedintval;

unsignedchari;

unsignedcharm,k,mark=1;

TR1=1;

while(mark)

{

i=0;

while((freq_list[i]!

=0)&&(mark==1)){

keycondition();

if(key_value==15)

{

TR1=0;

mark=0;

}

val=Clk/(freq_list[i]);

val=0xFFFF-val;

val_H=(val>>8)&0xff;

val_L=val&0xff;

TH1=val_H;

TL1=val_L;

for(m=0;m

{

for(k=0;k<0x26;k++)

{

if(position<=5)

{

display(position,0);

position+=1;

}

else

position=0;

}

}

i++;

}

}

}

//***********************************//

//调整时间函数

voidmodify_time(unsignedchard)

{unsignedchara,b,c;

key_value=100;

for(flag=0;flag<=5;)

{

if(position<=5)

{

if(position!

=flag)

display(position,d);

if(position==flag)

display_cursor(position);

delay_short();

delay_short();

position+=1;

}

else

position=0;

if(number>=100)

keycondition();

if(number<100)

number=number+1;

if((key_value==12)&&(flag>0))

{

flag=flag-1;

key_value=100;

delay_short();

number=0;

}

if((key_value==13)&&(flag<5))

{

flag=flag+1;

key_value=100;

delay_short();

number=0;

}

if((key_value==15))

flag=6;

if((0<=key_value)&&(key_value<=9))

{

delay_short();

if((flag==0)&&(key_value<3))

{

a=a%10+key_

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1