综合课程设计
——数字时钟_秒表的设计
姓名: 学号: 班级: 学院:自动化 联系方式:
数字时钟_秒表设计
1.1 项目要求
设计基于AT89C51单片机的数字可调时钟,晶振采用12HZ ,要求如下: (1) 设计采用显示。
(2) 可以显示时、分、秒,24小时制。
(3) 具有校时功能:可以对小时和分单独校时。对分校时的时候,停止分向小
时的进位。
(4) 具有秒表功能。
1.2系统设计
数字时钟以AT89C51为核心,通过按键1切换模式、调试时间。由内部振荡电路模块、按键复位电路模块、数码管显示模块和功能按键模块组成。
1.2.1 框图设计
1.2.2 知识点
本项目通过学习和查阅资料,了解和掌握以下知识: ●
AT89C51单片机原理及设计; ● 单片机内部振荡电路工作原理及设计; ● 单片机按键复位电路工作原理及设计;
● 74LS2458路同相三态双向总线收发器引脚及原理;
如果用C51的P0口输出到数码管,那就要考虑到数码管的亮度以及P0口带负载的能力,选用74LS245提高驱动能力。P0口的输出经过74LS245提高驱动后,输出到数码管显示电路。 74LS245是我们常用的芯片,用来驱动led 或者其他的设备,它是8路同相三态双向总线收发器,可双向传输数据。74LS245还具有双向三态功能,既
可以输出,也可以输入数据。当8051单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。当 片选端/CE低电平有效时,DIR=“0”,信号由 B 向 A 传输;(接收)DIR=“1”,信号由 A 向 B 传输;(发送)当CE 为高电平时,A 、B 均为高阻态。由于P2口始终输出地址的高8位,接口时74LS245的三态控制端1G 和2G 接地,P2口与 驱动器输入线对应相连。P0口与74LS245输入端相连,E 端接地,保证数据线畅通。8051的/RD和/PSEN相与后接DIR ,使得RD 和PSEN 有效时,74LS245输入(P0.1←D1),其它时间处于输出(P0.1→D1)。
● 7SEG-MPX6-CC 7段六位共阴级数码管的特性及使用。
7SEG-MPX6-CC 7是8段(其中有一段是小数点,可以忽略不计)六位共阴极数码管。如果要实现动态显示必须位码,(1—6)轮流通低电位,也就是片选,段选控制数码管的显示。
● C 语言及程序设计。
● Keil µVision 中的源程序设计与编译;
在Keil 集成开发环境下使用工程的方法来管理文件而不是单一文件的模式 所有的文件包括源程序(如C 程序、汇编程序) 、头文件等都可以放在工程项目文件里统一管理。对于刚刚使用Keil 的用户一般可以按照下面的步骤来创建一个自己的应用程序
(1) 一个工程项目文件
(2) 选择目标器件(例如选择ATMEL 公司的AT89C51) (3) 为工程项目设置软硬件调试环境 (4) 创建源程序文件并输入程序代码 (5) 保存创建的源程序项目文件 (6) 把源程序文件添加到项目中。
● Proteus 与单片机电路的交互式仿真与调试。
双击单片机AT89C51打开其属性编辑框。在“Program File ”栏中单击打开按钮,选取目标代码文件。在“Clock Frequency ”栏中设置时钟频率为12MHz, 因为运行时的时钟频率是以单片机属性中设置的频率值为准,所以在Proteus ISIS界面中设计电路原理图时,可以略去单片机的时钟电路。另外复位电路也可略去。对于MCS-51系列单片机而言,在不进行电路电气检测时EA 引脚也可悬空。
1.3 硬件设计
基于AT89C51单片机数字可调时钟的元件清单如表1-1所示:
表 1-2 数字时钟-秒表电路图
元件名称 单片机 电解电容 电阻 数码管显示
按键 电源
三态双向总线收发器
晶振 电容
型号 AT89C51 10uF 10k Ω 7SEG-MPX6-CC
+5V/0.5A 74LS245 12MHZ 12pF
数量 1个 1个 10个 1个 4个 1个 1个 1个 2个
用途 控制核心 复位电路 上拉电阻 显示模块 复位及功能按键 提供+5V电源 总线驱动 晶振电路 振荡电路
表1-1 基于A T89C51 单片机数字时钟-秒表元件清单
1.4 软件设计
程序清单
#include
#define uchar unsigned char #define uint unsigned int
uchar code Tab0[]= //定义数码管数组,没有小数点 {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f };
uchar code Tab1[]= //定义数码管数组,有小数点 { 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef };
sbit K1=P3^2; //模式选择键,本程序三种模式,分别是时间显示、秒表、时间设置 sbit K2=P3^3; //设置时间时加一/开始(暂停)秒表按键 sbit K3=P3^4; //切换设置位/清零秒表按键
void Delay(uchar x); //延时函数 void Init(); //中断初始化函数 void Mode_K1(); //模式切换函数 void Display0(); //时间显示函数 void Display1(); //秒表显示函数 void KEY_MiaoBiao(); //检测秒表操作按键 void Display2(); //时间设置显示函数 void KEY_Time_Set(); //检测时间设置按键
uchar Hours=00,Minutes=00,seconds=00; //分别定义三个变量表示时、分、秒 uchar K1_bit=0; //用于模式切换的标志(当K1_bit为0时显示时钟,为1时进入秒表,为2时进入时间设置模式) uchar Time0_bit=0; //用于定时器0的溢出标志 bit Set_Time=0; //设置时 闪烁时长的标志位 bit Set0=0; //设置时间标志,确定是设置‘分’还设置‘时’ uchar Miao_Biao0,Miao_Biao1,Miao_Biao2,Miao_Biao3,Miao_Biao4; //用于秒表的变量
void main() { Init(); //中断初始化 while(1) //死循环 { Mode_K1(); //模式扫描 switch(K1_bit) //模式选择 { case 0: { Display0(); //显示时间 break; }
case 1: { Display1();
//显示秒表 } case 2: 位 } } }
void Init() { EA=1; TMOD=0X11; 择第1种工作方式 TH0=(65536-50000)/256; TL0=(65536-50000)%256; ET0=1; TR0=1; TH1=(65536-50000)/256; TL1=(65536-50000)%256; ET1=1; TR1=0; }
void Delay(uchar x) { uchar i,j; for(i=x;i>0;i--) for(j=110;j>0;j--); }
void Time0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256;
KEY_MiaoBiao(); //扫描秒表操作
break;
{ Display2(); //设置时间时的显示程序,可闪烁定
KEY_Time_Set(); //扫描按键 break;
}
//中断初始化函数
//开总中断
//定时器工作方式选择,定时器0和定时器1都选 //定时器0装初值,定时50ms //开定时器0开关 //开定时器0小开关
//定时器1装初值,定时50ms //开定时器1开关
//关定时器1小开关
//延时
//定时器0函数
//重装初值
Time0_bit++; if((Time0_bit%10)==0) //每溢出10次Time0_bit取反一次 Set_Time=~Set_Time; //0.5秒闪烁一次 if(Time0_bit==20) //以下为时间数据处理 { Time0_bit=0; seconds++; if(seconds==60) { seconds=0; Minutes++; if(Minutes==60) { Minutes=0; Hours++; if(Hours==24) { Hours=0; } } } } }
void Time1() interrupt 1 //定时器1函数 { TH1=(65536-50000)/256; //重装初值 TL1=(65536-50000)%256; Miao_Biao0++; if(Miao_Biao0==2) //以下为秒表数据处理 { Miao_Biao0=0; Miao_Biao1++; //Miao_Biao1每加1次为100ms , if(Miao_Biao1==10) { Miao_Biao1=0; Miao_Biao2++; if(Miao_Biao2==60) { Miao_Biao2=0; Miao_Biao3++;
if(Miao_Biao3==60) { Miao_Biao3=0; Miao_Biao4++; if(Miao_Biao4==10) Miao_Biao4=0; } } } } }
void Mode_K1() //模式选择键,本程序三种模式,分别是时间显示、秒表、时间设置 { if(K1==0) { Delay(10); if(K1==0) { K1_bit++; if(K1_bit==3) { K1_bit=0; } while(!K1); } } }
void Display0() //显示时钟 { P0=Tab0[seconds%10]; //显示秒的个位 P1=0xdf; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[seconds/10]; //显示秒的十位 P1=0xef; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Minutes%10]; //显示分的个位,需要加上小数点做分隔符 P1=0xf7; //段选
Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Minutes/10]; //显示分的十位 P1=0xfb; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Hours%10]; //显示时的个位,需要加上小数点做分隔符 P1=0xfd; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Hours/10]; //显示时的十位 P1=0xfe; //段选 Delay(10); //延时 P0=0X00; //消隐 }
void KEY_MiaoBiao() //检测秒表按键操作 { if(K1_bit==1) //判断是否为秒表模式 { if(K2==0) { Delay(10); if(K2==0) { TR1=~TR1; //K2每按一次TR1取反,暂停或开始定时器1,达到暂停或开始秒表的目的 while(!K2); } } if(K3==0) { Delay(10); if(K3==0) //当K3按下时秒表所有数据清零,并停止定时器1 { TR1=0; //停止定时器1 Miao_Biao0=0; //清零数据 Miao_Biao1=0; Miao_Biao2=0; Miao_Biao3=0;
Miao_Biao4=0; while(!K3); } } } }
void Display1() //显示秒表 { P0=Tab0[Miao_Biao1%10]; //显示1/10秒的个位 P1=0xdf; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Miao_Biao2%10]; //显示秒的个位,需要加上小数点做分隔符 P1=0xef; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Miao_Biao2/10]; //显示秒的十位 P1=0xf7; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Miao_Biao3%10]; //显示分的个位,需要加上小数点做分隔符 P1=0xfb; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Miao_Biao3/10]; //显示分的十位 P1=0xfd; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Miao_Biao4%10]; //显示时的个位,需要加上小数点做分隔符 P1=0xfe; //段选 Delay(10); //延时 P0=0X00; //消隐 }
void Display2() //时间设置时的显示函数 { if(Set0==0) //判断是否为设置‘时’还是‘分’ {
符
P0=Tab0[seconds%10]; P1=0xdf; Delay(10); P0=0X00; //显示秒的个位
//段选 //延时 //消隐
P0=Tab0[seconds/10]; //显示秒的十位
P1=0xef; //段选 Delay(10); //延时 P0=0X00; //消隐
if(Set_Time) //这个if 语句实现分钟以0.5秒的频率闪烁 { P0=Tab1[Minutes%10]; //显示分的个位,需要加上小数点做分隔
P1=0xf7; Delay(10); P0=0X00;
//段选 //延时 //消隐 //显示分的十位 //段选 //延时 //消隐
} else {
P0=Tab0[Minutes/10];
P1=0xfb; Delay(10); P0=0X00;
P0=0x00; P1=0xf7; Delay(10); P0=0X00; //显示分的个位,需要加上小数点做分隔符 //段选 //延时 //消隐 //显示分的十位 //段选 //延时 //消隐
P0=0x00;
P1=0xfb; Delay(10); P0=0X00; }
P0=Tab1[Hours%10]; P1=0xfd; Delay(10); P0=0X00; P0=Tab0[Hours/10]; P1=0xfe; Delay(10);
//显示时的个位,需要加上小数点做分隔符 //段选 //延时 //消隐 //显示时的十位 //段选 //延时
} else { 分隔符
P0=0X00; //消隐
//‘时’钟闪烁
//显示秒的个位
//段选 //延时 //消隐 //显示秒的十位 //段选 //延时 //消隐
//显示分的个位,需要加上小数点做分隔符 //段选 //延时 //消隐
P0=Tab0[seconds%10];
P1=0xdf; Delay(10); P0=0X00; P0=Tab0[seconds/10]; P1=0xef; Delay(10); P0=0X00;
P0=Tab1[Minutes%10]; P1=0xf7; Delay(10); P0=0X00;
P0=Tab0[Minutes/10]; //显示分的十位 P1=0xfb; //段选 Delay(10); //延时 P0=0X00; //消隐
if(Set_Time) //这个if 语句实现‘时’钟以0.5秒的频率闪烁 { P0=Tab1[Hours%10]; //显示时的个位,需要加上小数点做 } else {
P1=0xfd;
Delay(10); P0=0X00;
//段选 //延时 //消隐 //显示时的十位 //段选 //延时 //消隐
P0=Tab0[Hours/10];
P1=0xfe; Delay(10); P0=0X00;
P0=0x00; P1=0xFF; Delay(10); //显示时的个位,需要加上小数点做分隔符 //段选 //延时
P0=0X00; //消隐 P0=0X00; //显示时的十位 P1=0xFF; //段选 Delay(10); //延时 P0=0X00; //消隐 } } }
void KEY_Time_Set() //设置时间时的按键扫描函数 { if(K1_bit==2) //判断是否为时间设置模式 { if(K2==0) //K2有按下(下同) { Delay(10); //延时消抖(下同) if(K2==0) //再次检测是否为误按 { if(Set0==0) //检测是设置‘时’还是分,Set0为0时设置‘分’,Set0为1时设置‘时’ { Minutes++; //‘分’加1 if(Minutes==60) //当' 分' 加到60时,重新赋值0 Minutes=0; } else { Hours++; //‘时’加1 if(Hours==24) //当' 时' 加到24时,重新赋值0 Hours=0; } while(!K2); //按键松开检测,消除松开按键时的抖动干扰 } } if(K3==0) { Delay(10); if(K3==0) { Set0=~Set0; //K3每按一次Set0取反,以确定是设置‘时’还是设置‘分’,Set0为0时设置‘分’,Set0为1时设置‘时’ while(!K3);
}
}
}
}
1.5 系统仿真及调试
通过本次实验,各方面又得到了进一步的提高。从整个单片机开发系统的把握上,感觉比以前更具有信心。尤其是在调试大型程序时,需先根据要求划分模块,优化结构;再根据各模块特点确定何为主程序,何为子程序,何为中断服务程序,相互间如何调用;再根据各模块性质和功能将各模块细化,设计出程序流程图;最后才根据各模块流程图编制具体程序。调试时应先调主程序,实现最基本最主要的功能,在此基础上再将各模块功能往主程序上堆砌,直至各模块联调、统调,实现全部功能。
实验过程的细节让我更加地确定做什么事情都要细心、仔细,不放过任何一个小小的点,只有这样,我们才以最高的效率完成任务。
总的来说,还有很多的不足之处,要在以后的实践中慢慢完善,不断的提高这方面的能力。
综合课程设计
——数字时钟_秒表的设计
姓名: 学号: 班级: 学院:自动化 联系方式:
数字时钟_秒表设计
1.1 项目要求
设计基于AT89C51单片机的数字可调时钟,晶振采用12HZ ,要求如下: (1) 设计采用显示。
(2) 可以显示时、分、秒,24小时制。
(3) 具有校时功能:可以对小时和分单独校时。对分校时的时候,停止分向小
时的进位。
(4) 具有秒表功能。
1.2系统设计
数字时钟以AT89C51为核心,通过按键1切换模式、调试时间。由内部振荡电路模块、按键复位电路模块、数码管显示模块和功能按键模块组成。
1.2.1 框图设计
1.2.2 知识点
本项目通过学习和查阅资料,了解和掌握以下知识: ●
AT89C51单片机原理及设计; ● 单片机内部振荡电路工作原理及设计; ● 单片机按键复位电路工作原理及设计;
● 74LS2458路同相三态双向总线收发器引脚及原理;
如果用C51的P0口输出到数码管,那就要考虑到数码管的亮度以及P0口带负载的能力,选用74LS245提高驱动能力。P0口的输出经过74LS245提高驱动后,输出到数码管显示电路。 74LS245是我们常用的芯片,用来驱动led 或者其他的设备,它是8路同相三态双向总线收发器,可双向传输数据。74LS245还具有双向三态功能,既
可以输出,也可以输入数据。当8051单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。当 片选端/CE低电平有效时,DIR=“0”,信号由 B 向 A 传输;(接收)DIR=“1”,信号由 A 向 B 传输;(发送)当CE 为高电平时,A 、B 均为高阻态。由于P2口始终输出地址的高8位,接口时74LS245的三态控制端1G 和2G 接地,P2口与 驱动器输入线对应相连。P0口与74LS245输入端相连,E 端接地,保证数据线畅通。8051的/RD和/PSEN相与后接DIR ,使得RD 和PSEN 有效时,74LS245输入(P0.1←D1),其它时间处于输出(P0.1→D1)。
● 7SEG-MPX6-CC 7段六位共阴级数码管的特性及使用。
7SEG-MPX6-CC 7是8段(其中有一段是小数点,可以忽略不计)六位共阴极数码管。如果要实现动态显示必须位码,(1—6)轮流通低电位,也就是片选,段选控制数码管的显示。
● C 语言及程序设计。
● Keil µVision 中的源程序设计与编译;
在Keil 集成开发环境下使用工程的方法来管理文件而不是单一文件的模式 所有的文件包括源程序(如C 程序、汇编程序) 、头文件等都可以放在工程项目文件里统一管理。对于刚刚使用Keil 的用户一般可以按照下面的步骤来创建一个自己的应用程序
(1) 一个工程项目文件
(2) 选择目标器件(例如选择ATMEL 公司的AT89C51) (3) 为工程项目设置软硬件调试环境 (4) 创建源程序文件并输入程序代码 (5) 保存创建的源程序项目文件 (6) 把源程序文件添加到项目中。
● Proteus 与单片机电路的交互式仿真与调试。
双击单片机AT89C51打开其属性编辑框。在“Program File ”栏中单击打开按钮,选取目标代码文件。在“Clock Frequency ”栏中设置时钟频率为12MHz, 因为运行时的时钟频率是以单片机属性中设置的频率值为准,所以在Proteus ISIS界面中设计电路原理图时,可以略去单片机的时钟电路。另外复位电路也可略去。对于MCS-51系列单片机而言,在不进行电路电气检测时EA 引脚也可悬空。
1.3 硬件设计
基于AT89C51单片机数字可调时钟的元件清单如表1-1所示:
表 1-2 数字时钟-秒表电路图
元件名称 单片机 电解电容 电阻 数码管显示
按键 电源
三态双向总线收发器
晶振 电容
型号 AT89C51 10uF 10k Ω 7SEG-MPX6-CC
+5V/0.5A 74LS245 12MHZ 12pF
数量 1个 1个 10个 1个 4个 1个 1个 1个 2个
用途 控制核心 复位电路 上拉电阻 显示模块 复位及功能按键 提供+5V电源 总线驱动 晶振电路 振荡电路
表1-1 基于A T89C51 单片机数字时钟-秒表元件清单
1.4 软件设计
程序清单
#include
#define uchar unsigned char #define uint unsigned int
uchar code Tab0[]= //定义数码管数组,没有小数点 {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f };
uchar code Tab1[]= //定义数码管数组,有小数点 { 0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef };
sbit K1=P3^2; //模式选择键,本程序三种模式,分别是时间显示、秒表、时间设置 sbit K2=P3^3; //设置时间时加一/开始(暂停)秒表按键 sbit K3=P3^4; //切换设置位/清零秒表按键
void Delay(uchar x); //延时函数 void Init(); //中断初始化函数 void Mode_K1(); //模式切换函数 void Display0(); //时间显示函数 void Display1(); //秒表显示函数 void KEY_MiaoBiao(); //检测秒表操作按键 void Display2(); //时间设置显示函数 void KEY_Time_Set(); //检测时间设置按键
uchar Hours=00,Minutes=00,seconds=00; //分别定义三个变量表示时、分、秒 uchar K1_bit=0; //用于模式切换的标志(当K1_bit为0时显示时钟,为1时进入秒表,为2时进入时间设置模式) uchar Time0_bit=0; //用于定时器0的溢出标志 bit Set_Time=0; //设置时 闪烁时长的标志位 bit Set0=0; //设置时间标志,确定是设置‘分’还设置‘时’ uchar Miao_Biao0,Miao_Biao1,Miao_Biao2,Miao_Biao3,Miao_Biao4; //用于秒表的变量
void main() { Init(); //中断初始化 while(1) //死循环 { Mode_K1(); //模式扫描 switch(K1_bit) //模式选择 { case 0: { Display0(); //显示时间 break; }
case 1: { Display1();
//显示秒表 } case 2: 位 } } }
void Init() { EA=1; TMOD=0X11; 择第1种工作方式 TH0=(65536-50000)/256; TL0=(65536-50000)%256; ET0=1; TR0=1; TH1=(65536-50000)/256; TL1=(65536-50000)%256; ET1=1; TR1=0; }
void Delay(uchar x) { uchar i,j; for(i=x;i>0;i--) for(j=110;j>0;j--); }
void Time0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256;
KEY_MiaoBiao(); //扫描秒表操作
break;
{ Display2(); //设置时间时的显示程序,可闪烁定
KEY_Time_Set(); //扫描按键 break;
}
//中断初始化函数
//开总中断
//定时器工作方式选择,定时器0和定时器1都选 //定时器0装初值,定时50ms //开定时器0开关 //开定时器0小开关
//定时器1装初值,定时50ms //开定时器1开关
//关定时器1小开关
//延时
//定时器0函数
//重装初值
Time0_bit++; if((Time0_bit%10)==0) //每溢出10次Time0_bit取反一次 Set_Time=~Set_Time; //0.5秒闪烁一次 if(Time0_bit==20) //以下为时间数据处理 { Time0_bit=0; seconds++; if(seconds==60) { seconds=0; Minutes++; if(Minutes==60) { Minutes=0; Hours++; if(Hours==24) { Hours=0; } } } } }
void Time1() interrupt 1 //定时器1函数 { TH1=(65536-50000)/256; //重装初值 TL1=(65536-50000)%256; Miao_Biao0++; if(Miao_Biao0==2) //以下为秒表数据处理 { Miao_Biao0=0; Miao_Biao1++; //Miao_Biao1每加1次为100ms , if(Miao_Biao1==10) { Miao_Biao1=0; Miao_Biao2++; if(Miao_Biao2==60) { Miao_Biao2=0; Miao_Biao3++;
if(Miao_Biao3==60) { Miao_Biao3=0; Miao_Biao4++; if(Miao_Biao4==10) Miao_Biao4=0; } } } } }
void Mode_K1() //模式选择键,本程序三种模式,分别是时间显示、秒表、时间设置 { if(K1==0) { Delay(10); if(K1==0) { K1_bit++; if(K1_bit==3) { K1_bit=0; } while(!K1); } } }
void Display0() //显示时钟 { P0=Tab0[seconds%10]; //显示秒的个位 P1=0xdf; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[seconds/10]; //显示秒的十位 P1=0xef; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Minutes%10]; //显示分的个位,需要加上小数点做分隔符 P1=0xf7; //段选
Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Minutes/10]; //显示分的十位 P1=0xfb; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Hours%10]; //显示时的个位,需要加上小数点做分隔符 P1=0xfd; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Hours/10]; //显示时的十位 P1=0xfe; //段选 Delay(10); //延时 P0=0X00; //消隐 }
void KEY_MiaoBiao() //检测秒表按键操作 { if(K1_bit==1) //判断是否为秒表模式 { if(K2==0) { Delay(10); if(K2==0) { TR1=~TR1; //K2每按一次TR1取反,暂停或开始定时器1,达到暂停或开始秒表的目的 while(!K2); } } if(K3==0) { Delay(10); if(K3==0) //当K3按下时秒表所有数据清零,并停止定时器1 { TR1=0; //停止定时器1 Miao_Biao0=0; //清零数据 Miao_Biao1=0; Miao_Biao2=0; Miao_Biao3=0;
Miao_Biao4=0; while(!K3); } } } }
void Display1() //显示秒表 { P0=Tab0[Miao_Biao1%10]; //显示1/10秒的个位 P1=0xdf; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Miao_Biao2%10]; //显示秒的个位,需要加上小数点做分隔符 P1=0xef; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Miao_Biao2/10]; //显示秒的十位 P1=0xf7; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Miao_Biao3%10]; //显示分的个位,需要加上小数点做分隔符 P1=0xfb; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab0[Miao_Biao3/10]; //显示分的十位 P1=0xfd; //段选 Delay(10); //延时 P0=0X00; //消隐 P0=Tab1[Miao_Biao4%10]; //显示时的个位,需要加上小数点做分隔符 P1=0xfe; //段选 Delay(10); //延时 P0=0X00; //消隐 }
void Display2() //时间设置时的显示函数 { if(Set0==0) //判断是否为设置‘时’还是‘分’ {
符
P0=Tab0[seconds%10]; P1=0xdf; Delay(10); P0=0X00; //显示秒的个位
//段选 //延时 //消隐
P0=Tab0[seconds/10]; //显示秒的十位
P1=0xef; //段选 Delay(10); //延时 P0=0X00; //消隐
if(Set_Time) //这个if 语句实现分钟以0.5秒的频率闪烁 { P0=Tab1[Minutes%10]; //显示分的个位,需要加上小数点做分隔
P1=0xf7; Delay(10); P0=0X00;
//段选 //延时 //消隐 //显示分的十位 //段选 //延时 //消隐
} else {
P0=Tab0[Minutes/10];
P1=0xfb; Delay(10); P0=0X00;
P0=0x00; P1=0xf7; Delay(10); P0=0X00; //显示分的个位,需要加上小数点做分隔符 //段选 //延时 //消隐 //显示分的十位 //段选 //延时 //消隐
P0=0x00;
P1=0xfb; Delay(10); P0=0X00; }
P0=Tab1[Hours%10]; P1=0xfd; Delay(10); P0=0X00; P0=Tab0[Hours/10]; P1=0xfe; Delay(10);
//显示时的个位,需要加上小数点做分隔符 //段选 //延时 //消隐 //显示时的十位 //段选 //延时
} else { 分隔符
P0=0X00; //消隐
//‘时’钟闪烁
//显示秒的个位
//段选 //延时 //消隐 //显示秒的十位 //段选 //延时 //消隐
//显示分的个位,需要加上小数点做分隔符 //段选 //延时 //消隐
P0=Tab0[seconds%10];
P1=0xdf; Delay(10); P0=0X00; P0=Tab0[seconds/10]; P1=0xef; Delay(10); P0=0X00;
P0=Tab1[Minutes%10]; P1=0xf7; Delay(10); P0=0X00;
P0=Tab0[Minutes/10]; //显示分的十位 P1=0xfb; //段选 Delay(10); //延时 P0=0X00; //消隐
if(Set_Time) //这个if 语句实现‘时’钟以0.5秒的频率闪烁 { P0=Tab1[Hours%10]; //显示时的个位,需要加上小数点做 } else {
P1=0xfd;
Delay(10); P0=0X00;
//段选 //延时 //消隐 //显示时的十位 //段选 //延时 //消隐
P0=Tab0[Hours/10];
P1=0xfe; Delay(10); P0=0X00;
P0=0x00; P1=0xFF; Delay(10); //显示时的个位,需要加上小数点做分隔符 //段选 //延时
P0=0X00; //消隐 P0=0X00; //显示时的十位 P1=0xFF; //段选 Delay(10); //延时 P0=0X00; //消隐 } } }
void KEY_Time_Set() //设置时间时的按键扫描函数 { if(K1_bit==2) //判断是否为时间设置模式 { if(K2==0) //K2有按下(下同) { Delay(10); //延时消抖(下同) if(K2==0) //再次检测是否为误按 { if(Set0==0) //检测是设置‘时’还是分,Set0为0时设置‘分’,Set0为1时设置‘时’ { Minutes++; //‘分’加1 if(Minutes==60) //当' 分' 加到60时,重新赋值0 Minutes=0; } else { Hours++; //‘时’加1 if(Hours==24) //当' 时' 加到24时,重新赋值0 Hours=0; } while(!K2); //按键松开检测,消除松开按键时的抖动干扰 } } if(K3==0) { Delay(10); if(K3==0) { Set0=~Set0; //K3每按一次Set0取反,以确定是设置‘时’还是设置‘分’,Set0为0时设置‘分’,Set0为1时设置‘时’ while(!K3);
}
}
}
}
1.5 系统仿真及调试
通过本次实验,各方面又得到了进一步的提高。从整个单片机开发系统的把握上,感觉比以前更具有信心。尤其是在调试大型程序时,需先根据要求划分模块,优化结构;再根据各模块特点确定何为主程序,何为子程序,何为中断服务程序,相互间如何调用;再根据各模块性质和功能将各模块细化,设计出程序流程图;最后才根据各模块流程图编制具体程序。调试时应先调主程序,实现最基本最主要的功能,在此基础上再将各模块功能往主程序上堆砌,直至各模块联调、统调,实现全部功能。
实验过程的细节让我更加地确定做什么事情都要细心、仔细,不放过任何一个小小的点,只有这样,我们才以最高的效率完成任务。
总的来说,还有很多的不足之处,要在以后的实践中慢慢完善,不断的提高这方面的能力。