基于单片机的电子时钟

点击链接获取Keil源码与Project Backups仿真图:

https://download.csdn.net/download/qq_64505944/87453487

基于单片机的电子时钟_第1张图片

源码获取

摘要

本次设计由于前期我们已经完成了单片机最小系统的制作,为了节省时间,故利用已有资源,选择用单片机最小系统来实现数字钟的制作。采用的是以单片机芯片为核心,辅以必要的外围电路包括时钟电路、复位电路、片外,RAM 片外

ROM 按键、数码管、外部扩展接口等部分,设计了一个简易的电子时钟。本方案是在AT89S52的单片机的P0和P2端口分别接有两个共阴数码管,显示"00一00-00"的时间开始计时,并且用P1口控制3个按键分别来控制"秒"、"分"、"时"的调整,每按一次加1秒、1分和1个小时,在硬件方面,我们使用单片机最小系统。软件方面采用C语言编程。整个电子钟系统能完成上电或按键复位后能自动显示显示"00-00-00"时间的显示,调时,复位等功能。

关键词:电子钟;单片机;数码管。

1项目概述

1.1项目简介

项目内容:以C51单片机为核心,设计一个定电子时钟,8位LED数码管,分别显示“时-分-秒”。显示范围范围从0时0分0秒到23时59分59秒,通过定时器来定时一秒钟,每过一秒刷新一次显示时间。通过矩阵键盘设置小时、分钟和秒数的初值。按调时按键按下后开始进入调整时间模式,通过矩阵按键进行新一次时间调整,并且可以通过按键设置闹钟,当到达闹钟时间时间时,数码管会闪烁一段时间并停止刷新时间,当按下24-12进制切换按键后,时钟显示会在24时制和12时制之间切换。项目用途:电子时钟广泛用于生活中的各种场景,在人们的生活中不可或缺,在国防科技、工业制造领域也有着极其重要的地位。学习价值:利用C51单片机进行电子时钟设计,掌握了关于中断、定时器、数码管等知识,对今后关于部件图的绘制有了更深的理解。社会意义:此次进行单片机电子时钟的课程设计,我们懂得了时间的重要性,在以后的学习生活中要珍惜时间,在今后的学习中深入单片机领域的学习与探索。

1.2功能需求分析

系统可以时间进行设计,显示格式为:“时”(第1,2位),“分”(第4,5位),“秒”(第7,8位)。
(2)当调整时间键被按下时自动进入调整时间模式,时钟不再刷新时间,通过矩阵键盘的按下从左至右依次可以进行时间更改。
(3)当24/12时制切换键被按下时,时钟显示自动切换另一种显示模式。
(4)当时间到达设置的闹钟时间时,数码管显示自动停止刷新时间并开始闪烁一段时间。

1.3系统开发环境

工具需求分析与选择,PROTUES软件进行仿真、keil软件

2 理论基础

2.1 AT89c51芯片

基于单片机的电子时钟_第2张图片

图1 AT89C51芯片引脚图

其中主要应用到的引脚口介绍:

(1)P0口的第一功能是作为一般I/O口使用,第二功能是在CPU访问外部存储器时,分时提供低8位地址和8位双向数据。

(2)P1口是8位准双向I/O口,51子系列中P1只能用作一般I/O口,52子系列中P1.0和P1.1引脚还具有第二功能。

(3)P2口是8位准双向I/O口,第二功能是在CPU访问外部存储器时,作为高8位地址总线,输出高8位地址。

(4)P3口是8位准双向I/O口,其第一功能是用作一般I/O口,第二功能是作为中断信号和外部数据存储器的读写控制信号。

(5)RES,复位信号高电平有效。

2.2 Keil的简单介绍

Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统。Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(μVision)将这些部分组合在一起。此处简单介绍一下Keil 工程的建立等,以Keil μVision2界面为例。

(1)建立一个工程,选择菜单栏中的【Project】下的【New Project】,菜单栏如图2所示。

图2 菜单栏

选择工程要保存的路径并且输入工程名,以电子时钟工程的建立为例,如图3所示。

基于单片机的电子时钟_第3张图片

图3 保存新工程

选择系统要用的单片机如图4所示,选择添加启动文件如图5所示。

基于单片机的电子时钟_第4张图片

图4 选择单片机

基于单片机的电子时钟_第5张图片

图5 添加启动文件

(4)建立文件,选择菜单【File】下的【New】,出现界面如图6所示。

基于单片机的电子时钟_第6张图片

图6 新建文件界面

保存文件为“*.c”文件,并且添加文件到所建的工程下,保存文件截面图如图7所示,添加文件显示界面如图8所示,右键点击SourceGroup添加。

基于单片机的电子时钟_第7张图片

图7 保存文件界面

基于单片机的电子时钟_第8张图片

图8 添加文件界面

2.3 Protues的简单介绍

Proteus软件是英国Lab Center Electronics公司出版的EDA工具软件,它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前比较好的仿真单片机及外围器件的工具,可以仿真51系列、AVR、PIC、ARM、等常用主流单片机。在PROTEUS绘制好原理图后,调入已编译好的目标代码文件:*.HEX,可以在PROTEUS的原理图中看到模拟的实物运行状态和过程。

(1)Keil中生成*.HEX的界面如图9所示。

基于单片机的电子时钟_第9张图片

图9 生成hex文件

Protues中加载HEX文件,在Protues界面中双击AT89C51芯片,所示界面如图10所示。

基于单片机的电子时钟_第10张图片

图10 加载HEX文件界面

3项目硬件系统设计

3.1 系统方案原理图

(1)项目主要硬件。

硬件系统是指构成微机系统的实际装置,通常是由单片机、数码管显示、定时器计数、矩阵按键和外部中断等组成。单片机芯片选择AT89C51,显示区域使用8位LED数码管,键盘是34普通矩阵键盘以及外部中断INT0 INT1。

基于单片机的电子时钟_第11张图片

(2)项目主要模块介绍

34键盘:数据从此地方进行数据输入,将数值传给单片机。

定时器:定时时间,使得显示数据按秒进行刷新。

中断INT0、INT1:可进行24小时制与12小时制的转化以及时间设定开始开关。

8位LED数码管:进行时间的显示。

仿真图如下:

基于单片机的电子时钟_第12张图片

抽象组件图如下:

基于单片机的电子时钟_第13张图片

3.2 外设原理介绍

输入电路:主要完成信息的采集,本项目采用3*4动态按键扫描,由12个分别位于行和列的按键组成,4条行线分别接单片机的P1.0P1.3,3条列线分别接单片机的P1.4P1.6。两个中断开关分别连接到单片机的P3.2和P3.3口。

输出电路:本项目采用8位LED数码管动态扫描显示电路,笔段A~DP分别与单片机的P0口相连,公共端分别受单片机的P2口控制。

控制电路:通过定时器的定时1秒钟不断刷新来改变显示的数值,对输入的信息进行分析,本项目用C51单片机来实现。

中断电路:通过INT0和INT1两个中断来增加了调整时间模式和24/12时制之间转换模式。

3.3 键盘输入模块工作原理

本设计之中使用的是3x4的普通键盘,我们可以使用其行列号来识别被按下的按键以此来获知被按键的信息,因此将行输出信号和列输出信号接入单片机芯片C51的 P1口,通过循环扫描,读取行列的数据来判断是否有按键被按下,如果有则调用按键识别程序来识别具体按键,并执行相应的操作,按键识别是根据按键时得到的列代码与行代码的结合,在汇编语言中进行查表来判断是哪个键。

3.4 数码管显示模块工作原理

8位一体共阳极LED数码管,这8个数码管的段选端在器件内部并联在了一起,外部引出了一个共用的段选端AG,DP。每一个数码管的公共端单独引出,分别对应引脚18。数码管段选信号由单片机的P0口输出,位选信号由P2.0~P2.7引脚控制。

4系统软件体系设计

4.1 主程序流程图

基于单片机的电子时钟_第14张图片

(1)显示程序流程图

基于单片机的电子时钟_第15张图片

(2)中断程序流程图

基于单片机的电子时钟_第16张图片

(3)定时器流程图

基于单片机的电子时钟_第17张图片
基于单片机的电子时钟_第18张图片

4.2 项目运行效果展示

下图为24时进制显示的16时9分52秒

基于单片机的电子时钟_第19张图片

下图为12时进制显示的4时10分12秒

基于单片机的电子时钟_第20张图片

5 实验代码

#include 
#include                     
unsigned char code table[] = { 0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0xff };
unsigned char count = 0;//定时器 计数变量 
unsigned char time[] = { 16,9,50 };//初始显示的时间  16-09-50 
unsigned char p = 0;//调整时间时候,将要调整的位数 
unsigned char num = 0;//按键接收值 
unsigned char state = 0;//state=0 显示时间模式,state=1 调整时间模式 
unsigned char change = 0;//change=0 24时显示时间,change=1 12时显示
void delay(unsigned int z)
{
unsigned int x, y;
for (x = z; x > 0; x--)
for (y = 110; y > 0; y--);
}
void disp()//数码管显示函数 
{
P2 = 0x01;
P0 = table[time[0] / 10];
delay(3);
P2 = _crol_(P2, 1);
P0 = table[time[0] % 10];
delay(3);
P2 = _crol_(P2, 1);
P0 = 0xbf;
delay(3);
P2 = _crol_(P2, 1);
P0 = table[time[1] / 10];
delay(3);
P2 = _crol_(P2, 1);
P0 = table[time[1] % 10];
delay(3);
P2 = _crol_(P2, 1);
P0 = 0xbf;
delay(3);
P2 = _crol_(P2, 1);
P0 = table[time[2] / 10];
delay(3);
P2 = _crol_(P2, 1);
P0 = table[time[2] % 10];
delay(3);
P0 = 0xff;
}
void keyscan()//按键扫描函数 
{
P1 = 0xfe;
while ((P1 & 0xf0) != 0xf0)
{
delay(3);
while ((P1 & 0xf0) != 0xf0)
{
switch (P1)
{
case 0xee:num = 1; break;
case 0xde: num = 2; break;
case 0xbe: num = 3; break;
}
if (state) p++;//在调整时间模式 每次按下按键自动调整为修改下一位 
delay(300);
while ((P1 & 0xf0) != 0xf0) disp();
}
}
P1 = 0xfd;
while ((P1 & 0xf0) != 0xf0)
{
delay(3);
while ((P1 & 0xf0) != 0xf0)
{

switch (P1)
{
case 0xed: num = 4; break;
case 0xdd: num = 5; break;
case 0xbd: num = 6; break;
}
if (state)p++;
delay(300);
while ((P1 & 0xf0) != 0xf0) disp();
}
}
P1 = 0xfb;
while ((P1 & 0xf0) != 0xf0)
{
delay(3);
while ((P1 & 0xf0) != 0xf0)
{
switch (P1)
{
case 0xeb: num = 7; break;
case 0xdb:num = 8; break;
case 0xbb: num = 9; break;
}
if (state)p++;
delay(300);
while ((P1 & 0xf0) != 0xf0) disp();
}
}
P1 = 0xf7;
while ((P1 & 0xf0) != 0xf0)
{
delay(3);
while ((P1 & 0xf0) != 0xf0)
{
switch (P1)
{
case 0xe7: num++; p--; break;
case 0xd7: num = 0; break;
case 0xb7: break;
}
if (state)p++;
delay(300);
while ((P1 & 0xf0) != 0xf0) disp();
}
}
}
void change_time()//调整时间模式 计算函数 
{
if (state)
{
switch (p)
{
case 1:time[0] = (num * 10 + time[0] % 10); break;//num接受按键的值,小时的十位上改为num的值,个位不变 
case 2:time[0] = (num + (time[0] / 10 * 10)); break;//小时的个位上改为num的值,十位不变 
case 3:time[1] = (num * 10 + time[1] % 10); break;//num接受按键的值,分钟的十位上改为num的值,个位不变 
case 4:time[1] = (num + (time[1] / 10 * 10)); break;//分钟的个位上改为num的值,十位不变
case 5:time[2] = (num * 10 + time[2] % 10); break;//num接受按键的值,秒的十位上改为num的值,个位不变 
case 6:time[2] = (num + (time[2] / 10 * 10)); break;//秒的个位上改为num的值,十位不变
}
if (p >= 6)//全部调整完时间,进入正常时间显示模式,并打开定时器 
{
state = 0;
TR1 = 1;
p = 0;
}
}
}
void init_timer1()
{
TMOD = 0x15;
IE = 0x85;
IP = 0x04;
TL1 = (65536 - 50000) % 256;
TH1 = (65536 - 50000) / 256;
TR1 = 1;
ET1 = 1;
EA = 1;
}
void main()
{
init_timer1();//定时器中断初始化 
while (1)
{
disp();
keyscan();
change_time();
}
}
void TIME_1() interrupt 3//定时器计数 
{
TL1 = (65536 - 50000) % 256; //50ms 
TH1 = (65536 - 50000) / 256;
count++;
if (change) time[0] %= 12;//保证小时小于12 
else time[0] %= 24;//保证小时小于12 
time[1] %= 60;//保证分钟用于小于60 
if (count == 20)//到达1s 
{
count = 0;
time[2]++;//秒加一 
if (time[2] >= 60)//秒进位 
{
time[2] = 0;//秒清零 
time[1]++;//分加一 
if (time[1] >= 60)//分进位 
{
time[1] = 0;//分清零 
time[0]++;//小时加一 
}
}
}
}
void int0() interrupt 0//进入调整时间模式 
{
state = 1;
TR1 = 0;//关闭定时器 
}
void int1() interrupt 2//切换24-12时间显示 
{
change = ~change;
}

6 总结

通过单片机课程设计,我们对单片机原理的学习更加掌握和了解,为以后的学习奠定了基础。这次课程设计基于每周做的单片机项目,使得我们对单片机整体构架有个初步的认识和见解,在课程设计的过程中,明白了合理的小组分工尤为重要,本课程设计我们制作电子时钟,完成了正常电子时钟的显示功能、定时闹钟和调整时间功能,并在此基础完善了增加了利用矩阵键盘进行调整时间的功能,实现显示“小时.分钟.秒”的定时功能和12时/24小时切换显示,可灵活实现小时加、分钟加等功能。本设计具有较强的灵活性,可实现性高,具有较高的应用价值。虽然进行了代码多次优化与调试,但是对于部分功能仍存在显示出错的问题,我们在以后的学习中会继续完善代码,将软件与硬件完美结合,在单片机领域更加努力的学习。

参考文献

[1]张毅刚.单片机原理及应用[M].北京:高等教育出版社,2008

[2]郭天祥新概念51单片机C语言教程-入门、提高、开发拓展全攻略[M]北

京:电子工业出版社2010

[3]彭伟单片机C语言程序设计实训100例-基于8051+Proteus仿真[M]北京:电子工业出版社2010.6

[4]张大明.单片机控制实训指导及综合应用实例[M]北京:清华大学出版社,2004

[5] 张齐,朱宁西.单片机应用系统设计技术一基于C51的Proteus 仿真[M].北

京:化学工业出版社,2004.

[6]沈光斌,刘冬,姚志成,单片机系统实用抗干扰设计,[M].北京:人民邮电出版社,2004

[7]冯育长.单片机系统设计与实例分析.[M].西安:西安电子科技大学出版社,2007

[8]晁阳,单片机MCS-51原理及应用开发教程[M]北京:清华大学出版社,2009

你可能感兴趣的:(单片机,单片机,51单片机)