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

1 绪论电子表是20世纪50年代才开始出现的新型计时器。
最早的一款电子表被称做“摆轮游丝电子表”,它诞生于1955年。
这种手表用电磁摆轮代替发条驱动,以摆轮游丝作为振荡器,微型电池为能源,通过电子线路驱动摆轮工作。
它的走时部分与机械手表完全相同,被称为第一代电子手表。
1960年,美国布洛瓦公司最早开始出售“音叉电子手表”。
这种手表以金属音叉作为振荡器,用电子线路输出脉冲电流,使机械音叉振动。
它比摆轮式电子手表结构简单,走时更精确,被称为第二代电子手表。
1969年,日本精工舍公司推出了世界上最早的石英电子表。
石英电子表的出现,立刻成为了钟表界主流产品,它走时精确,结构简单,轻松地将一、二代电子表,甚至机械表淘汰出局。
石英表又称“水晶振动式电子表”,因为它是利用水晶片的“发振现象”来计时的。
当水晶受到外部的加力电压,就会产生变形和伸缩反应;如果压缩水晶,便会使水晶两端产生电力。
这样的性质在很多结晶体上也可见到,称为“压电效果”。
石英表就是利用周期性持续“发振”的水晶,为我们带来准确的时间。
单片机是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域的广泛应用。
从上世纪80年代,由当时的4位、8为单片机,发展到现在的32位300M的高速单片机。
1.1 单片机的介绍单片微型计算机简称单片机,是典型的嵌入式微控制器(Microcontroller Unit),常用英文字母的缩写MCU表示单片机,单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。
概括的讲:一块芯片就成了一台计算机。
51单片机实现数码管电子表

// 按button1切换时间显示状态, 时:分 <--> 分:秒
// 按button3开关整点报时
void checkButtonTime()
{
if(isButton(0))
{
mode = 0; //调时间
PILOT_LIGHT |= 0xc0; //开启前两个灯
k = 5;
while(k != 0 && (P2 & 0x0f) ==p)
{
k--;
j = 100;
while(j != 0 && (P2 & 0x0f) == p)
{
j--;
if(mode == 0)
displayTime(hour,min,0);
//在进入调时间模式时flag标志是否调过时间
unsigned char flag = 0,tellTime = 1;
//当前时间
unsigned char hour = 5,min = 59,sec = 40;
//起床和熄灯时间
unsigned char getUpH = 6,getUpM = 0,sleepH = 22,sleepM = 30;
PILOT_LIGHT |= 0x0c;
tempP3 = P3;
while(1)
{
displayTime(sleepH,sleepM,0);
if(isButton(0))
{
EA = 1;
mode = 3; //恢复正常走表形式
PILOT_LIGHT &= 0x03;
tempP3 = P3;
基于51单片机的电子表设计

1 绪论电子表是20世纪50年代才开始出现的新型计时器。
最早的一款电子表被称做“摆轮游丝电子表”,它诞生于1955年。
这种手表用电磁摆轮代替发条驱动,以摆轮游丝作为振荡器,微型电池为能源,通过电子线路驱动摆轮工作。
它的走时部分与机械手表完全相同,被称为第一代电子手表。
1960年,美国布洛瓦公司最早开始出售“音叉电子手表”。
这种手表以金属音叉作为振荡器,用电子线路输出脉冲电流,使机械音叉振动。
它比摆轮式电子手表结构简单,走时更精确,被称为第二代电子手表。
1969年,日本精工舍公司推出了世界上最早的石英电子表。
石英电子表的出现,立刻成为了钟表界主流产品,它走时精确,结构简单,轻松地将一、二代电子表,甚至机械表淘汰出局。
石英表又称“水晶振动式电子表”,因为它是利用水晶片的“发振现象”来计时的。
当水晶受到外部的加力电压,就会产生变形和伸缩反应;如果压缩水晶,便会使水晶两端产生电力。
这样的性质在很多结晶体上也可见到,称为“压电效果”。
石英表就是利用周期性持续“发振”的水晶,为我们带来准确的时间。
单片机是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域的广泛应用。
从上世纪80年代,由当时的4位、8为单片机,发展到现在的32位300M的高速单片机。
1.1 单片机的介绍单片微型计算机简称单片机,是典型的嵌入式微控制器(Microcontroller Unit),常用英文字母的缩写MCU表示单片机,单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
相当于一个微型的计算机,和计算机相比,单片机只缺少了I/O设备。
概括的讲:一块芯片就成了一台计算机。
基于80C51单片机的智能电表设计

基于80C51单片机的智能电表设计智能电表的推广与使用是一项惠及百姓的民生工程,它大大改善了农村居民用电条件,提高了配电网的自动化水平,对于减少电力能源的消耗具有重大的意义。
采用单片机80C51为核心,同时增加电能计量芯片CS5460A、LCD显示器1602、Wifi通信电路、SD存储卡等芯片,来实现电能的计量与显示、无线通信、数据存储等功能。
用户可以通过电表上的按键来选择是显示用户当前用电量,还是某一时段用电量。
随着计算机技术和通信技术的发展,建筑智能化程度越来越高。
住宅的智能化抄表系统在建筑智能化中是必不可少的。
在我国,对用户的电表仍采用人工抄表的方法。
这种原始的查表方法不仅造成了人力、物力的浪费,打扰居民正常生活,而且其精度差,电量数据需要人为读数不能实时传输。
为了从根本上解决这个问题,因此设计一种基于单片机的智能电表。
电表若以单片机为主体取代传统仪器仪表的常规机械及电子线路,可以容易地将计算技术与测量控制技术结合在一起,形成智能化测量仪表。
这种仪表由计量电路、微处理器、LCD显示器、实时时钟、通信接口及电源等组成,具有电能量计量、信息存储及处理、实时监测、自动控制、信息交互等功能。
1 智能电表的工作原理智能电表的硬件方案框图如图1 所示。
电能表主要由计量、电源管理、存储、显示、按键处理、脉冲输出和通信单元7 个部分组成。
本文的智能电表是以80C51为核心处理器。
除此之外,加入了电能计量芯片CS5460A 和LCD 显示芯片1602,用于用户用电量的计量与显示。
但是,由于CS5460A芯片只能测量瞬时的电量,所以,还需要采用时间芯片DS1302将时间分段,这样电表就可以通过按键,不但可以显示出用户的瞬时用电量,而且还能显示某个时段的用电量。
WiFi通信电路的使用,可以实现智能电表的无线通信,这样查电表的工作人员不用再挨家挨户的登门查询,而是直接接收WiFi信号,就可以了解到用户的用电情况,比较方便、省时。
基于51单片机的电能表的课程设计任务书

基于51单片机的电能表的课程设计本次设计主要是利用单片机和接口技术设计、研制一种新型电能表,可实现峰谷用电量和剩余金额,并用LCD显示。
进一步了解有关单片机、存储电路、IC卡的应用;掌握信号获取、传输、处理及检测的一般方法;综合运用已有的理论和技术,制定设计方案,掌握用电量的测量方法;学会应用存储电路、IC 卡、单片机组建一个实际测量系统,提高设计者的应用能力;通过测量、计算、显示,能运用所学知识并学会查阅有关资料,培养仪器仪表设计的基本技能,为今后的深入学习等奠定基础。
1.1、设计要求参考利用存储电路、IC卡、单片机及其接口技术研制出一种新型电能表,设计内容包括:(1)详细了解所选用的存储电路、IC卡、单片机的工作原理和工作特性;(2)设计合理的计算测量电路;(3)用单片机、IC卡、LCD的显示技术实现测量电路,单片机的指令系统开发相关的应用程序,并对程序作详细的分析和解释。
(4)列出制作该装置的元器件,搭建试验电路,并进行试验验证调试。
(5)撰写详细的设计技术报告。
1.2、方案设计与分析此电能表主要由计量模块、单片机、IC卡模块、LCD显示、EEPROM存储器、实时时钟电路及电源电路等部分组成。
其硬件系统框图如下图1所示。
其中,单片机以AT89C51为电能表的核心控制芯片,它是电能表的“大脑”,外围所有的硬件模块都是在它的控制协调下进行工作的。
单片机通过控制在其中的各种程序,控制着其它硬件模块的工作状态,由它智能化地形成并可靠地提供电能计算、时段判断、费率切换、IC卡读写、电能量控制及负荷控制等功能。
1.3、AT89C51单片机本电能表的硬件设计原则是在低功耗的前提下,实现多功能目的,该芯片功耗低,特别适用于电能表控制线路多、功能全、功耗低的要求。
它能方便地读取IC卡的数据,并控制液晶显示器的工作,同时还可以将电能表的数据存入EEPROM进行永久保存并可通过串口送至表外的数据终端,大大地提高了电能表的智能化功能。
#基于51单片机的简易电子表设计与仿真

智能仪器及使用实验报告项目名称:基于51单片机的简易电子表设计和仿真专业名称:测控技术和仪器班级:测控0901班学生姓名:指导教师:一、任务要求使用Keil uVision编程软件以及ISIS 7 Professional仿真软件制作一个简易电子表,要求具备电子表基本功能(时间显示、时间调整等)。
二、总体设计方案利用AT89C51作为控制以及1602LCD作为显示,通过6个按键实现出入时间设置状态、出入闹铃设置状态、小时位调整、分钟位调整、开关闹铃等功能。
系统的流程图如下:图1-1 系统仿真流程图三、系统硬件1、AT89C51引脚功能说明:AT89C51芯片如图1-2所示图1-2 AT89C51VCC:供电电压。
GND:接地。
P0口:P0口为一个8位漏极开路双向I/O口,每脚可吸收8TTL门电流。
当P1口的管脚第一次写1时,被定义为高阻输入。
P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。
在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。
P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。
在FLASH编程和校验时,P1口作为第八位地址接收。
P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。
并因此作为输入时,P2口的管脚被外部拉低,将输出电流。
这是由于内部上拉的缘故。
P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。
在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。
P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
单片机电子表设计

目录第1章单片机和数字钟概述 (5)第2章系统总体方案设计 (6)2.1课程设计内容要求 (6)2.2设计思路简要分析 (6)第3章硬件设计 (8)3.1 结构框图 (8)3.2工作原理 (8)3.2主要硬件功能及机构介绍 (10)3.2.1、晶振电路 (10)3.2.2、AT89C51 (10)3.2.3、6位7段共阳显示器 (11)3.2.4、8255芯片 (12)第4章软件设计与调试 (13)4.1 系统软件方案的设计 (13)4.2 系统应用程序设计 (13)4.2.1主程序设计 (13)4.2.2子程序设计 (15)第5章调试和使用说明 (17)第六章总结与体会 (18)参考文献 (20)附录 (34)第1章单片机和数字钟概述单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。
我们都知道,设计系统的关键是思路,而系统通常又由各个模块所组成,所以必须先把所要设计系统模块化,再把各个模块组合在一起,实现一个完整的系统。
这就要求我们先要有较扎实的理论知识,特别对芯片的各个管脚功能必须了解,这样才能进行硬件设计。
同时,又必须掌握MCS51的指令功能,通过编程实现其功能,这就能让我们更好地理解《单片机原理及应用》这门课程,也是一种理论在实践中的运用。
如果说我们以前学的都只是些理论,包括c语言,微机原理,c++,微机接口,protel,单片机,那么这次的课程设计就是一个贯穿多学科的综合性实践!单片机自20世纪70年代问世以来,以极其高的性价比受到人们的重视和关注,所以应用很广,发展很快。
单片机的优点是体积小、重量轻、抗干扰能力强,对环境要求不高,价格低廉,可靠性高,灵活性好,开发较为容易。
数字钟是一种用数字电路技术实现时、分、秒计时的装置,与机械式时钟相比具有更高的准确性和直观性,且无机械装置,具有更更长的使用寿命,因此得到了广泛的使用。
数字钟从原理上讲是一种典型的数字电路,其中包括了组合逻辑电路和时序电路。
基于51单片机的电子表设计

目录目录 (1)第1章概述 (1) (1)第2章设计思路及框图 (1) (1) (2)第3章系统的硬件设计 (2) (2) (3) (3) (4) (4)第4章电路设计原理图 (4) (4)第5章程序设计 (5) (5) (7)第6章系统的验证及调试 (43) (43) (43) (44)第7章总结 (45)第8章参考文献 (45)第1章概述单片机集成度高、功能强、可靠性高、体积小、功耗地、使用方便、价格低廉等一系列优点,目前已经渗入到人们工作和生活的方方面面,几乎“无处不在,无所不为”。
单片机的应用领域已从面向工业控制、通讯、交通、智能仪表等迅速发展到家用消费产品、办公自动化、汽车电子、PC机外围以及网络通讯等广阔领域。
单片机有两种基本结构形式:一种是在通用微型电脑中广泛采用的,将程序存储器和数据存储器合用一个存储器空间的结构,称为普林斯顿结构。
另一种是将程序存储器和数据存储器截然分开,分别寻址的结构,一般需要较大的程序存储器,目前的单片机以采用程序存储器和数据存储器截然分开的结构为多。
本课题讨论的方波发生器的核心是目前应用极为广泛的 51系列单片机。
利用AT89C51单片机定时器完成计时功能,定时器0计时中断程序每隔0.01s中断一次并当作一个计数,设定定时1秒的中断计数初值为0,每中断一次中断计数初值加1,当加到100时,则表示1s到了,秒变量加1,同理再判断是否1min钟到了,再判断是否1h到了。
为了将时间在6位LED数码管上显示,可采用静态显示法和动态显示法,由于静态显示法需要译码器,数据锁存器等较多硬件,可采用动态显示法实现LED显示,通过对每位数码管的依次扫描,使对应数码管亮,同时向该数码管送对应的字码,使其显示数字。
由于数码管扫描周期很短,由于人眼的视觉暂留效应,使数码管看起来总是亮的,从而实现了各种显示。
第2章设计思路及框图设计思路针对要实现的功能,采用AT89S51单片机进行设计,AT89S51 单片机是一款低功耗,高性能CMOS8位单片机,第一,熟悉AT89S51单片机,在编程之前必须了解硬件结构尤其是各引脚的用法,以及内部寄存器、存储单元的用法,否则,编程无从下手,电路也无法设计。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录目录 (1)第1章概述 (1)1.1实验原理 (1)第2章设计思路及框图 (1)2.1设计思路 (1)2.2设计框图 (2)第3章系统的硬件设计 (2)3.1主控制部件 (2)3.2显示模块 (3)3.3晶振模块 (3)3.4按键模块 (3)3.5驱动模块 (4)第4章电路设计原理图 (4)4.1电路原理图 (4)第5章程序设计 (5)5.1程序流程图 (5)5.2源程序 (6)第6章系统的验证及调试 (26)6.1日期设置显示测试 (26)6.2秒表测试 (26)6.3倒计时测试 (27)第7章总结 (28)第8章参考文献 (28)第1章概述1.1实验原理单片机集成度高、功能强、可靠性高、体积小、功耗地、使用方便、价格低廉等一系列优点,目前已经渗入到人们工作和生活的方方面面,几乎“无处不在,无所不为”。
单片机的应用领域已从面向工业控制、通讯、交通、智能仪表等迅速发展到家用消费产品、办公自动化、汽车电子、PC机外围以及网络通讯等广大领域。
单片机有两种基本结构形式:一种是在通用微型计算机中广泛采用的,将程序存储器和数据存储器合用一个存储器空间的结构,称为普林斯顿结构。
另一种是将程序存储器和数据存储器截然分开,分别寻址的结构,一般需要较大的程序存储器,目前的单片机以采用程序存储器和数据存储器截然分开的结构为多。
本课题讨论的方波发生器的核心是目前应用极为广泛的 51系列单片机。
利用AT89C51单片机定时器完成计时功能,定时器0计时中断程序每隔0.01s中断一次并当作一个计数,设定定时1秒的中断计数初值为0,每中断一次中断计数初值加1,当加到100时,则表示1s到了,秒变量加1,同理再判断是否1min钟到了,再判断是否1h到了。
为了将时间在6位LED数码管上显示,可采用静态显示法和动态显示法,由于静态显示法需要译码器,数据锁存器等较多硬件,可采用动态显示法实现LED显示,通过对每位数码管的依次扫描,使对应数码管亮,同时向该数码管送对应的字码,使其显示数字。
由于数码管扫描周期很短,由于人眼的视觉暂留效应,使数码管看起来总是亮的,从而实现了各种显示。
第2章设计思路及框图2.1设计思路针对要实现的功能,采用AT89S51单片机进行设计,AT89S51 单片机是一款低功耗,高性能CMOS8位单片机,第一,熟悉AT89S51单片机,在编程之前必须了解硬件结构尤其是各引脚的用法,以及内部寄存器、存储单元的用法,否则,编程无从下手,电路也无法设计。
这是前期准备工作。
第二,设计硬件部分:依据想要的功能分块设计设计,比如输入需要开关电路,输出需要显示驱动电路和数码管电路等。
第三,画图部分:设计好电路后进行画图。
第四,软件部分:先学习理解汇编语言的编程方法再根据设计的硬件电路进行分块的编程调试,最终完成程序设计。
第五部分是软件仿真部分:软硬件设计好后将软件载入芯片中进行仿真,仿真无法完成时检查软件程序和硬件电路并进行修改直到仿真成功。
第六部分是硬件实现部分:连接电路并导入程序检查电路,实现想要的功能。
2.2设计框图此次设计主要是应用单片机来设计电子时钟,硬件部分主要分以下电路模块:显示电路用8个共阴极数码显示管、按键模块、晶振模块。
显示管分别显示:小时、分钟和秒,通过动态扫描进行显示。
电路的总体设计框架如下:图1→→ →→第3章系统的硬件设计3.1主控制部件89C51是一个8位单片机,片内ROM 全部采用FLASH ROM 技术,晶振时钟为12MHz 。
89C51是标准的40引脚双列直插式集成电路芯片,有4个八位的并行双向I/O 端口,分别记作P0、P1、P2、P3。
第31引脚需要接高电位使单片机选用内部程序存储器;第40脚为电源端VCC ,接+5V 电源,第20引脚为接地端VSS ,通常在VCC 和VSS 引脚之间接0.1μF 高频滤波电容。
硬件原理图如图2所示:图23.2显示模块方案一:静态显示。
静态显示,即当显示器显示某一字符时,相应的发光二极管恒定导通或截至。
该方式每一位都需要一个8位输出口控制。
静态显示时较小电流能获得较高的亮度,且字符不闪烁。
但因当所需显示的位数较多时,静态显示所需的I/O口数较大,造成资源的浪费。
方案二:动态显示。
动态显示,即各位数码管轮流点亮,对于显示器各位数码管,每隔一段延时时间循环点亮一次。
利用人的视觉暂留功能可以看到整个显示,但必须保证扫描速度足够快,人的视觉暂留功能才可以察觉不到字符闪烁。
显示器的亮度与导通电流、点亮时间及间隔时间的比例有关。
调整参数可实现较高稳定度的显示。
动态显示节省了I/O口,降低了能耗。
从节省单片机I/O口和降低能耗角度出发,本电子表显示选择采用方案二。
3.3晶振模块单片机芯片可使用内部时钟电路和外部时钟电路两种方式产生电路所需的时钟脉冲,内部时钟电路实现可用石英晶体和微调电容外接即可达到,外部时钟电路实现需要一个外部脉冲源引入脉冲信号以保证个单片机之间时钟信号的同步。
从硬件实现难易角度考虑,内部时钟电路的实现比外部时钟电路的实现更简易。
既本数字电子钟设计所需的时钟源采用内部时钟电路实现。
3.4按键模块本数字电子钟设计所需按键用于进行显示时间的调整与设置扩展的小键盘。
单片机芯片4个I/O口可与按键直接相连,通过编程,单片机芯片即可控制按键接口电平的高低,即按键的开与关,以达到用按键进行显示时间的调整与设置扩展的小键盘的设计要求,本电路采用P1口与按键相连。
3.5驱动模块从实物制作简易程度与驱动数码管段码能力角度出发,本数字电子钟设计采用数码管段码与AT89C51P0口相连,单片机AT89C51的P2口控制数码管的片选信号,通过编程,单片机芯片即可控制段码电平的高低的方式实现数码管段码控制。
第4章电路设计原理图4.1电路原理图图3第5章程序设计5.1程序流程图在主程序的开始定义了一组固定单元用来存储计数的分、秒、时的存储单元。
在主程序中,对不同的按键进行扫描,实现秒表,时间调整。
系统总体流程图如图4所示。
开始↓T0中断入口↓通过查表方式显示数据↓位选数值=0↓秒计数加1↓秒计数=1000↓秒计数=0↓Seconds+1↓中断返回图4系统子程序流程图如图5所示:图55.2源程序#include <reg52.h>#include "ds1302.h"#include "lcd1602.h"#include "key.h"//sbit wela=P2^7;//sbit dula=P2^6;uchar tab_date[14]="2012-11-16 TUE";//表示年月日星期uchar tab_time[8]="00:00:00";//表示时分秒uchar tab_time1[8]="00:00:00";//表示时分秒uchar tiao;uchar msecond;uchar hour,min,sec,key,sition;//uchar kong[]=" ";uchar flag; //时间秒表选择标志//------------------------------------------// 数据转换//------------------------------------------void trans(){tab_date[2]=tab_1302[6]/10+'0'; //年十位tab_date[3]=tab_1302[6]%10+'0'; //年个位tab_date[5]=tab_1302[4]/10+'0'; //月十位tab_date[6]=tab_1302[4]%10+'0'; //月个位tab_date[8]=tab_1302[3]/10+'0'; //日十位tab_date[9]=tab_1302[3]%10+'0'; //日个位tab_time[0]=tab_1302[2]/10+'0'; //小时十位tab_time[1]=tab_1302[2]%10+'0'; //小时个位tab_time[3]=tab_1302[1]/10+'0'; //分十位tab_time[4]=tab_1302[1]%10+'0'; //分个位tab_time[6]=tab_1302[0]/10+'0'; //秒十位tab_time[7]=tab_1302[0]%10+'0'; //秒个位}//------------------------------------------// 星期显示//------------------------------------------void week(){uchar i;if(tab_1302[5]==1){i=7;}else{i=tab_1302[5]-1;} /*实时时钟里的值是6,但是2008/08/08是星期五,所以减1,Proteus的问题?? */switch(i){case 1: tab_date[11]='M';tab_date[12]='O';tab_date[13]='N'; break;case 2: tab_date[11]='T';tab_date[12]='U';tab_date[13]='E'; break;case 3: tab_date[11]='W';tab_date[12]='E';tab_date[13]='D'; break;case 4: tab_date[11]='T';tab_date[12]='H';tab_date[13]='U'; break;case 5: tab_date[11]='F';tab_date[12]='R';tab_date[13]='I'; break;case 6: tab_date[11]='S';tab_date[12]='T';tab_date[13]='A'; break;case 7: tab_date[11]='S';tab_date[12]='U';tab_date[13]='N'; break;default: ; break; //其它情况}}void getweek(uchar week1,uchar t[]){uchar i;if(week1==1)i=7;elsei=week1-1; /*实时时钟里的值是6,但是2008/08/08是星期五,所以减1, Proteus的问题?? */switch(i){case 1: t[0]='M';t[1]='O';t[2]='N'; break;case 2: t[0]='T';t[1]='U';t[2]='E'; break;case 3: t[0]='W';t[1]='E';t[2]='D'; break;case 4: t[0]='T';t[1]='H';t[2]='U'; break;case 5: t[0]='F';t[1]='R';t[2]='I'; break;case 6: t[0]='S';t[1]='T';t[2]='A'; break;case 7: t[0]='S';t[1]='U';t[2]='N'; break;default: ; break; //其它情况}}void cls(uchar i) //表示打印出i个空格{// lcd_wcom(addr); //重新设定显示地址为0xc4,即下排第5位for(;i>0;i--){lcd_wdat(' ');lcddelay(1);}}//------------------------------------------// lcd液晶屏显示//------------------------------------------void display(uchar a[],uchar b[]){uchar i,j;lcd_wcom(0x80+0x01); //显示地址设为80H(即00H,)上排第一位for(i=0;i<14;i++){lcd_wdat(a[i]); //将日期显示在lcd1602上lcddelay(1);}lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<8;j++) //将tab_time中的数据依次写入1602显示{lcd_wdat(b[j]);lcddelay(1);}}//------------------------------------------// 显示倒计时//------------------------------------------void djsdsp(uchar hour,uchar min,uchar sec){uchar j,key,t;// uchar t[]="00:00:00";// TR1=1;while(1){t=tab_1302[0];ds1302();if(t!=tab_1302[0])msecond=1;key=Getkey();if(key==KEY_BK){return;}sec=sec-msecond;msecond=0;if(sec==255){sec=59;min--;if(min==255){min=59;hour--;if(hour==255)while(1){key=Getkey();if(key==KEY_BK)return;}}}tab_time[0]=hour/10+'0';tab_time[1]=hour%10+'0';tab_time[3]=min/10+'0';tab_time[4]=min%10+'0';tab_time[6]=sec/10+'0';tab_time[7]=sec%10+'0';lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<8;j++) //将tab_time中的数据依次写入1602显示{lcd_wdat(tab_time[j]);lcddelay(1);}}}//------------------------------------------// 设置倒计时//------------------------------------------void djishi(){uchar ch[]="Countdown:";uchar t[]="00:00:00";uchar str[]="00";uchar i;sition=3;hour=min=sec=0;lcd_wcom(0x01); //清屏lcd_wcom(0x80+0x01); //显示地址设为80H(即00H,)上排第一位for(i=0;i<10;i++){lcd_wdat(ch[i]); //将"Countdown:"显示在lcd1602上lcddelay(1);}lcd_wcom(0x80+0x44); //显示地址设为80H(即00H,)上排第一位for(i=0;i<8;i++){lcd_wdat(t[i]); //将时间显示在lcd1602上lcddelay(1);}while(1){key=Getkey();switch(key){case KEY_MU:return;case KEY_UP:switch(sition){case 1:hour++;if(hour>=24) hour=0;break;case 2:min++;if(min>=60) min=0;break;case 3:sec++;if(sec>=60) sec=0;break;default:break;};break;case KEY_DN:switch(sition){case 1:hour--;if(hour==255) hour=59;break;case 2:min--;if(min==255) min=59;break;case 3:sec--;if(sec==255) sec=59;break;default:break;};break;case KEY_L:{lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);sition--;if(sition==0)sition=3;}break;case KEY_R:{lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);sition++;if(sition==4)sition=1;}break;case KEY_OK:djsdsp(hour,min,sec);lcd_wcom(0x01);return;case KEY_BK:lcd_wcom(0x01);return;default:break;}// lcd_wcom(0x01); //清屏if(sition==1){str[0]=hour/10|+'0';str[1]=hour%10+'0';lcd_wcom(0x80+0x44);if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x44);}else if(2==sition){str[0]=min/10+'0';str[1]=min%10+'0';lcd_wcom(0x80+0x47);if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x47);}else{str[0]=sec/10+'0';str[1]=sec%10+'0';lcd_wcom(0x80+0x4a);if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x4a);}}}//------------------------------------------ // 设置日期//------------------------------------------ void setdate(){uchar i,j,yearh,yearl,month,date,week;uchar str[]="00";uchar ch[]="set date:";sition=5;lcd_wcom(0x01); //清屏lcd_wcom(0x80+0x01); //显示地址设为80H(即00H,)上排第一位for(i=0;i<9;i++){lcd_wdat(ch[i]); //将"set date:"显示在lcd1602上lcddelay(1);}lcd_wcom(0x80+0x41); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<14;j++) //将tab_date中的数据依次写入1602显示{lcd_wdat(tab_date[j]);lcddelay(1);}yearh=(tab_date[0]-'0')*10+(tab_date[1]-'0');yearl=tab_1302[6];month=tab_1302[4];date=tab_1302[3];week=tab_1302[5];while(1){key=Getkey();switch(key){// case KEY_MU:djishi();return;case KEY_UP:switch(sition){case 1:yearh++;if(yearh>=100) yearh=0;break;case 2:yearl++;if(yearl>=100) yearl=0;break;case 3:month++;if(month>=13) month=0;break;case 4:{date++;if(((yearh*100+yearl)%4==0&&(yearh*100+yearl)%100!=0)||((yearh*100+yearl) %400==0)) //如果是闰年{if(month==2&&date>29)date=1;}else{if(month==2&&date>28)date=1;}if(month==4||month==6||month==9||month==11){if(date>30)date=1;}else{if(date>31)date=1;}}break;case 5:week++;if(week==8)week=1;break;default:break;};break;case KEY_DN:switch(sition){case 1:yearh--;if(yearh==255) yearh=99;break;case 2:yearl--;if(yearl==255) yearl=99;break;case 3:month--;if(month==0) month=12;break;case 4:{date--;if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) //有31天的月份{if(date==0)date=31;}else if(month!=2){if(date==0)date=30;}elseif(((yearh*100+yearl)%4==0&&(yearh*100+yearl)%100!=0)||((yearh*100+yearl)%400 ==0))//闰年中的2月{if(date==0)date=29;}else{if(date==0)date=28;}}break;case 5:week--;if(week==0) week=7;break;default:break;};break;case KEY_L:{if(sition!=5){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{lcd_wdat(ch[0]);lcddelay(1);lcd_wdat(ch[1]);lcddelay(1);lcd_wdat(ch[2]);}sition--;if(sition==0) sition=5;}break;case KEY_R:{if(sition!=5){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{lcd_wdat(ch[0]);lcddelay(1);lcd_wdat(ch[1]);lcddelay(1);lcd_wdat(ch[2]);}sition++;if(sition==6)sition=1;}break;case KEY_OK:{tab_date[0]=yearh/10+'0';tab_date[1]=yearh%10+'0';tab1_1302[6]=yearl;tab1_1302[4]=month;tab1_1302[3]=date;tab1_1302[5]=week;ds1302();tab1_1302[0]=tab_1302[0];tab1_1302[1]=tab_1302[1];tab1_1302[2]=tab_1302[2];ds1302_init();lcd_wcom(0x01); //清屏return;}case KEY_BK: lcd_wcom(0x01);return;default:break;}// lcd_wcom(0x80+0x4a);if(sition==1){lcd_wcom(0x80+0x41);str[0]=yearh/10|+'0';str[1]=yearh%10+'0';if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x41); }else if(2==sition){lcd_wcom(0x80+0x43);str[0]=yearl/10+'0';str[1]=yearl%10+'0';if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x43); }else if(3==sition){lcd_wcom(0x80+0x46);str[0]=month/10+'0';str[1]=month%10+'0';if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x46);}else if(4==sition){lcd_wcom(0x80+0x49);str[0]=date/10+'0';str[1]=date%10+'0';if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x49);}else{getweek(week,ch);lcd_wcom(0x80+0x4c);if(tiao<10){lcd_wdat(ch[0]);lcddelay(1);lcd_wdat(ch[1]);lcddelay(1);lcd_wdat(ch[2]);}else{cls(3);}lcd_wcom(0x80+0x4c);}}}//------------------------------------------// 设置时间//------------------------------------------void settime(){uchar i,j;// uchar sition; //闪烁位置uchar ch[]="set time:";uchar str[]="00";// TR0=1; //lcd不执行中断中的在变时间sition=3; //3调秒,2调分,1调时lcd_wcom(0x01); //清屏lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<8;j++) //将tab_time中的数据依次写入1602显示{lcd_wdat(tab_time[j]);lcddelay(1);}lcd_wcom(0x80+0x01); //显示地址设为80H(即00H,)上排第一位for(i=0;i<9;i++){lcd_wdat(ch[i]); //将"set time:"显示在lcd1602上lcddelay(1);}hour=tab_1302[2];min=tab_1302[1];sec=tab_1302[0]; //获取当前时间,在此基础上进行调时while(1){// steval();key=Getkey();switch(key){case KEY_MU:setdate();return;case KEY_UP:switch(sition){case 1:hour++;if(hour>=24) hour=0;break;case 2:min++;if(min>=60) min=0;break;case 3:sec++;if(sec>=60) sec=0;break;default:break;};break;case KEY_DN:switch(sition){case 1:hour--;if(hour==255) hour=23;break;case 2:min--;if(min==255) min=59;break;case 3:sec--;if(sec==255) sec=59;break;default:break;};break;case KEY_L:{lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);sition--;if(sition==0)sition=3;}break;case KEY_R:{lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);sition++;if(sition==4)sition=1;}break;case KEY_OK:{tab1_1302[0]=sec;tab1_1302[1]=min;tab1_1302[2]=hour;tab1_1302[3]=tab_1302[3];tab1_1302[4]=tab_1302[4];tab1_1302[5]=tab_1302[5];tab1_1302[6]=tab_1302[6];ds1302_init();lcd_wcom(0x01);return;}case KEY_BK:lcd_wcom(0x01);return;default:break;}// lcd_wcom(0x01); //清屏if(sition==1){str[0]=hour/10|+'0';str[1]=hour%10+'0';lcd_wcom(0x80+0x44);if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x44);}else if(2==sition){str[0]=min/10+'0';str[1]=min%10+'0';lcd_wcom(0x80+0x47);if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x47);}else{str[0]=sec/10+'0';str[1]=sec%10+'0';lcd_wcom(0x80+0x4a);if(tiao<10){lcd_wdat(str[0]);lcddelay(1);lcd_wdat(str[1]);lcddelay(1);}else{cls(2);}lcd_wcom(0x80+0x4a);}}}void miaobiao(){uchar j;uchar i;sec=min=0;lcd_init();lcd_wcom(0x01); //清屏lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<8;j++) //将tab_time中的数据依次写入1602显示{lcd_wdat(tab_time1[j]);lcddelay(1);}// TR1=1;while(1){if(BK==0){TR1=0;return;}if(MB==0){if(i<2)TR1=~TR1;while(MB==0);i++;if(i==3){i=0;lcd_wcom(0x01); //清屏lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<8;j++) //将tab_time中的数据依次写入1602显示{lcd_wdat(tab_time1[j]);lcddelay(1);}}}}}//------------------------------------------// 处理按键函数//------------------------------------------void dealkey(uchar key1){uchar num;num=key1;switch(num){case KEY_MU:TR0=1;settime();TR0=0;break;case KEY_MB:miaobiao();break;case KEY_CK:TR0=1;djishi();TR0=0;break;default:break;}}void T0_init(){TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256; //50ms中断一次EA=1; //开总中断ET0=1; //允许T0定时器中断// TR0=1; //启动T0开始定时PT0=0; //设置中断优先级}void T1_init(){TMOD=TMOD|0x10;//T1工作方式2TH1=(65536-10000)/256;TL1=(65536-10000)%256; //10ms中断一次ET1=1; //允许T0定时器中断// TR1=1;PT1=1;}void main(){uchar key;// ds1302_init();lcd_init();T0_init();T1_init();while(1){ds1302();trans();week(); //获取时钟芯片内的数据key=Getkey();if(0!=key)dealkey(key);// if(flag==0)display(tab_date,tab_time);}}void T0_SEVER(void) interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256; //重装初值,10ms后再次中断一次tiao++;if(tiao==20) //定时一秒tiao=0;}void T1_SEVER(void) interrupt 3 //250us中断一次{// uchar t=0;// uchar time[]="00:00:00";uchar j;TH1=(65536-10000)/256;TL1=(65536-10000)%256; //10ms中断一次msecond++;if(msecond>=100){msecond=0;sec++;if(sec>=60){sec=0;min++;if(min==60)min=0;}tab_time[0]=min/10+'0';tab_time[1]=min%10+'0';tab_time[3]=sec/10+'0';tab_time[4]=sec%10+'0';tab_time[6]=msecond/10+'0';tab_time[7]=msecond%10+'0';lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位for(j=0;j<8;j++) //将tab_time中的数据依次写入1602显示{lcd_wdat(tab_time[j]);// lcddelay(1);}}else{tab_time[0]=min/10+'0';tab_time[1]=min%10+'0';tab_time[3]=sec/10+'0';tab_time[4]=sec%10+'0';tab_time[6]=msecond/10+'0';tab_time[7]=msecond%10+'0';lcd_wcom(0x80+0x4a);lcd_wdat(tab_time[6]);lcddelay(1);lcd_wdat(tab_time[7]);}}第6章系统的验证及调试6.1日期设置显示测试结果显示如图6:图66.2秒表测试结果如图7:图7 6.3倒计时测试结果如图8:图8第7章总结这次单片机课程设计我收获很多。