单片机综合实验报告电子时钟
单片机电子时钟实验报告

单片机电子时钟实验报告一、实验任务及要求在焊接的电路板中,4个LED数码管,设计带有闹铃功能的数字时钟,要求:1、在4位数码管上显示当前时间。
显示格式“时时分分”;2、由LED闪动做秒显示;3、利用按键可对时间及闹玲进行设置,并可显示闹玲时间。
当闹玲时间到蜂鸣器发出声响,按停止键使可使闹玲声停止。
二、方案论证与比较2.1数字时钟方案数字时钟是本设计的最主要的部分。
根据需要,可利用两种方案实现。
方案一:本方案采用Dallas公司的专用时钟芯片DS12887A。
该芯片内部采用石英晶体振荡器,其芯片精度不大于10ms/年,且具有完备的时钟闹钟功能,因此,可直接对其以用于显示或设置,使得软件编程相对简单。
为保证时钟在电网电压不足或突然掉电等突发情况下仍能正常工作,芯片内部包含锂电池。
当电网电压不足或突然掉电时,系统自动转换到内部锂电池供电系统。
而且即使系统不上电,程序不执行时,锂电池也能保证芯片的正常运行,以备随时提供正确的时间。
方案二:本方案完全用软件实现数字时钟。
原理为:在单片机内部存储器设三个字节分别存放时钟的时、分、秒信息。
利用定时器与软件结合实现5毫秒定时中断,每产生一次中断,存储器内相应的计数值加1;若计数值达到200,则将其清零,并将方案一:静态显示。
所谓静态显示,就是当显示器显示某一字符时,相应的发光二极管恒定的导通或截止。
该方式每一位都需要一个8 位输出口控制。
静态显示时较小的电流能获得较高的亮度,且字符不闪烁。
但当所显示的位数较多时,静态显示所需的I/O口太多,造成了资源的浪费。
方案二:动态显示。
所谓动态显示就是一位一位的轮流点亮各个位,对于显示器的每一位来说,每隔一段时间点亮一次。
利用人的视觉暂留功能可以看到整个显示,但必须保证扫描速度合适,字符才不闪烁。
显示器的亮度既与导通电流有关,也于点亮时间与间隔时间的比例有关。
调整参数可以实现较高稳定度的显示。
动态显示节省了I/O 口,降低了能耗。
单片机电子时钟实验报告

电子时钟预备知识:数码管:内部接线C语言程序:一、电子时钟(一)设计目的通过电子时钟综合设计,使学生学会利用8051定时器时间计时处理功能,了解按键扫描及控制LED数码管显示原理,掌握单片机和按键以及LED数码管硬件电路设计及控制程序的设计方法。
思考按键消除抖动、LED动态显示与静态显示的特点,从而提高学生解决实际问题的能力。
(二)设计任务及要求利用实验平台上4个LED数码管,设计带有闹铃功能的数字时钟,要求:1.在4位数码管上显示当前时间。
显示格式“时时分分”2.由LED闪动做秒显示。
3.利用按键可对时间及闹玲进行设置,并可显示闹玲时间。
当闹玲时间到蜂鸣器发出声响,按停止键使可使闹玲声停止。
(三)我采用的是TB-22766板子,单片机类型是STC89C52RC(四)软件设计思想:采用语言:C语言,主要中断:内部T0中断为唯一的中断,主程序大体分为两部分:无按键被按下时的显示,有按键被按下时,输入定时时间或者书输入当前时间,然后的显示软件,最后是一个蜂鸣器的控制程序。
前面是三个子程序:两个按键扫描和一个延时小程序。
N具体的C语言程序:/*---------------------------------------------------------------------------------------------------------------------=======================================基于JD51开发板的电子闹钟程序=======================================************************************程序功能说明********************************************************************* ***1、基础功能为计时,并显示当前时间。
单片机电子时钟(LCD显示)综合实验报告

单片机综合实验报告题目:电子时钟(LCD)显示一、实验内容:以AT89C51单片机为核心的时钟,在LCD显示器上显示当前的时间:●使用字符型LCD显示器显示当前时间。
●显示格式为“时时:分分:秒秒”。
●用4个功能键操作来设置当前时间,4个功能键接在P1.0~P1.3引脚上。
功能键K1~K4功能如下。
●K1—进入设置现在的时间。
●K2—设置小时。
●K3—设置分钟。
●K4—确认完成设置。
程序执行后工作指示灯LED闪动,表示程序开始执行,LCD显示“00:00:00”,然后开始计时。
二、实验电路及功能说明1)单片机主控制模块以AT89C51单片机为核心进行一系列控制。
2)时钟显示模块用1602为LCD显示模块,把对应的引脚和最小系统上的引脚相连,连接后用初始化程序对其进行简单的功能测试。
测试成功后即可为实验所用,如图:3)时间调整电路用4个功能键操作来设置当前时间,4个功能键接在P1.0~P1.3引脚上。
功能键K1~K4功能如下。
K1—进入设置现在的时间。
K2—设置小时。
K3—设置分钟。
K4—确认完成设置。
如图:三、实验程序流程图:主程序:时钟主程序流程子程序:四、实验结果分析实验结果及分析:单片机的晶振可以根据要求设定。
6MHZ为和现实时间显示相同。
实验采用12MHZ晶振采用方式1定时,选取50ms采用20次中断达到一秒,采用查表方式控制LCD显示。
当烧入程序后开始运行,根据初始值设定可以观察到显示的时间,这里为了更明显观察显示数据变化把起始值设为23:59:50 运行后显示,K1为进入现在设置时间,当按下K1后显示,和实验要求相比较,实现了按下K1进入现在时间设置,按下K4确认完成时间设置的功能;不同之处: 当进入时间设置时在按下K1设置小时,再次按下K1是设置分钟。
增加功能:进入时间设置并选择设置位置后K2键位数字增加功能,K3键为数字减小功能。
根据仿真结果能够确定编程正确,基本实现了所有功能,而且有所改进。
多功能电子时钟实训报告

一、实训目的本次实训旨在通过学习单片机技术,设计并实现一个基于单片机的多功能电子时钟系统。
通过实训,使学生掌握以下知识和技能:1. 熟悉单片机的基本原理和编程方法;2. 掌握电子时钟系统的硬件设计、软件编程和调试方法;3. 提高动手能力和实际应用能力。
二、实训内容1. 系统硬件设计(1)核心控制器:选用AT89C51单片机作为系统的核心控制器。
(2)时钟芯片:使用DS1302实时时钟芯片,提供精确的时间信号。
(3)液晶显示屏:选用1602液晶显示屏,用于显示时间、日期、温度等信息。
(4)按键模块:设计包含时间设置键、日期设置键、闹钟设置键等的按键模块。
(5)温度传感器:使用DS18B20温度传感器,用于检测环境温度。
(6)电源模块:为整个系统提供稳定的工作电压。
2. 系统软件设计(1)主程序:负责系统初始化、时钟显示、闹钟提醒、温度检测等功能。
(2)中断程序:负责时钟中断、闹钟中断、温度中断等。
(3)显示程序:负责液晶显示屏的显示内容更新。
(4)按键处理程序:负责按键扫描、按键消抖、按键功能处理等。
三、实训过程1. 硬件搭建(1)根据设计图纸,焊接电路板。
(2)连接单片机、时钟芯片、液晶显示屏、按键模块、温度传感器和电源模块。
(3)检查电路连接是否正确,确保系统硬件正常工作。
2. 软件编程(1)编写主程序、中断程序、显示程序和按键处理程序。
(2)使用C语言进行编程,并利用Keil软件进行编译。
(3)将编译好的程序烧录到单片机中。
3. 调试与优化(1)在Proteus仿真软件中,对系统进行仿真调试。
(2)检查程序运行是否正常,优化程序代码。
(3)对硬件电路进行调整,确保系统稳定运行。
四、实训结果1. 系统功能实现(1)显示当前时间、日期和温度。
(2)设置闹钟时间,并在设定时间响起。
(3)计时器功能,可以记录时间。
(4)温度检测功能,实时显示环境温度。
2. 系统稳定性通过仿真和实际测试,系统稳定运行,满足设计要求。
单片机实训报告(电子时钟)

单片机实训报告课程名称:单片微型计算机原理与接口技术实验项目:电子时钟实验班级:09电本一设计人:于润婷学号:2009104143004指导老师:祁伟实验时间:2011.9.28~2011.9.12学校:广东技术师范学院目录第一章绪论 (2)1.1 电子时钟的概述 (2)1.2 电子时钟的发展现状及前景 (2)第二章控制系统的硬件设计 (3)2.1 电源模块 (3)2.2 处理器模块 (5)2.3 显示模块 (6)2.4 按键模块 (9)2.5 蜂鸣器模块 (10)第三章系统的的软件实现 (11)3.1 主程序流程图 (11)3.2 按键流程图 (13)3.3 时钟中断流程图 (15)3.4 显示流程图 (15)第四章系统的功能及性能测试 (19)心得体会 (21)参考文献 (22)附件:程序清单第一章:绪论1.1 电子时钟的概述1957年,Ventura发明了世界上第一个电子表,从而奠定了电子时钟的基础,电子时钟开始迅速发展起来。
现代的电子时钟是基于单片机的一种计时工具,采用延时程序产生一定的时间中断,用于一秒的定义,通过计数方式进行满六十秒分钟进一,满六十分小时进一,满二十四小时小时清零。
从而达到计时的功能,基于单片机设计的电子时钟精确度较高,因为在程序的执行过程中,任何指令都不影响定时器的正常计数,即便程序很长也不会影响中断的时间。
从而,使电子时钟的精度仅仅取决于单片机的产生机器周期电路和定时器硬件电路的精确度。
另外,程序较为简洁,具有可靠性和较好的可读性。
如果我们想将它应用于实时控制之中,只要对上述程序和硬件电路稍加修改,便可以得到实时控制的实用系统,从而应用到实际工作与生产中去。
该电子时钟由AT89C51,SN74LS04N ,按键,数码管等构成,采用晶振电路作为驱动电路,由延时程序和循环程序产生的一秒定时,达到时分秒的计时,六十秒为一分钟,六十分钟为一小时,满二十四小时为一天,满三十一天为一个月,满十二个月为一年。
单片机数字钟实习报告

一、实习目的随着电子技术的飞速发展,单片机作为一种重要的电子元件,在工业、医疗、通讯等领域得到了广泛的应用。
为了更好地掌握单片机的原理和应用,提高动手能力,我们选择了单片机数字钟作为实习项目。
通过本次实习,我们旨在掌握单片机的编程、调试、硬件连接等方面的知识,实现数字时钟的显示与控制。
二、实习内容1. 单片机数字钟硬件设计(1)选用AT89C51单片机作为核心控制单元,具有丰富的片上资源,方便编程和调试。
(2)采用LCD1602液晶显示屏,显示时间、日期等信息。
(3)使用DS1302实时时钟芯片,实现时间的存储和更新。
(4)选用按键作为输入设备,实现时间的调整和设置。
(5)选用蜂鸣器作为报警设备,实现定时报警功能。
2. 单片机数字钟软件设计(1)编写主程序,实现系统初始化、时间显示、按键扫描、时间调整等功能。
(2)编写中断服务程序,实现DS1302时钟芯片的读写、按键消抖等功能。
(3)编写子程序,实现时间的计算、格式化、显示等功能。
3. 单片机数字钟调试与测试(1)连接电路,检查各个模块的连接是否正确。
(2)编写程序,将程序烧录到单片机中。
(3)调试程序,确保程序运行正常。
(4)测试各个功能模块,如时间显示、按键调整、定时报警等。
三、实习过程1. 硬件设计(1)根据设计要求,绘制电路原理图。
(2)购买所需元器件,进行焊接。
(3)组装电路板,连接各个模块。
2. 软件设计(1)编写程序,采用C语言进行编程。
(2)使用Keil软件进行编译、烧录。
(3)在仿真软件Proteus中进行仿真,验证程序的正确性。
3. 调试与测试(1)连接电路,检查各个模块的连接是否正确。
(2)编写程序,将程序烧录到单片机中。
(3)调试程序,确保程序运行正常。
(4)测试各个功能模块,如时间显示、按键调整、定时报警等。
四、实习总结1. 通过本次实习,我们掌握了单片机的编程、调试、硬件连接等方面的知识。
2. 学会了使用LCD1602液晶显示屏、DS1302实时时钟芯片、按键等元器件。
单片机实验报告数字时钟设计报告

单片机实验报告数字时钟设计报告一、实验目的本次单片机实验的目的是设计并实现一个基于单片机的数字时钟。
通过该实验,深入了解单片机的工作原理和编程方法,掌握定时器、中断、数码管显示等功能的应用,提高综合运用知识解决实际问题的能力。
二、实验原理1、单片机选择本次实验选用了常见的 51 系列单片机,如 STC89C52。
它具有丰富的资源和易于编程的特点,能够满足数字时钟的设计需求。
2、时钟计时原理数字时钟的核心是准确的计时功能。
通过单片机内部的定时器,设定合适的定时时间间隔,不断累加计时变量,实现秒、分、时的计时。
3、数码管显示原理采用共阳或共阴数码管来显示时间数字。
通过单片机的 I/O 口控制数码管的段选和位选信号,使数码管显示相应的数字。
4、按键控制原理设置按键用于调整时间。
通过检测按键的按下状态,进入相应的时间调整模式。
三、实验设备与材料1、单片机开发板2、数码管3、按键4、杜邦线若干5、电脑及编程软件(如 Keil)四、实验步骤1、硬件连接将数码管、按键与单片机开发板的相应引脚通过杜邦线连接起来。
确保连接正确可靠,避免短路或断路。
2、软件编程(1)初始化单片机的定时器、中断、I/O 口等。
(2)编写定时器中断服务程序,实现秒的计时。
(3)设计计时算法,将秒转换为分、时,并进行进位处理。
(4)编写数码管显示程序,将时间数据转换为数码管的段选和位选信号进行显示。
(5)添加按键检测程序,实现时间的调整功能。
3、编译与下载使用编程软件将编写好的程序编译生成可执行文件,并下载到单片机中进行运行测试。
五、程序设计以下是本次数字时钟设计的主要程序代码片段:```cinclude <reg52h>//定义数码管段选码unsigned char code SEG_CODE ={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};//定义数码管位选码unsigned char code BIT_CODE ={0x01, 0x02, 0x04, 0x08, 0x10,0x20, 0x40, 0x80};//定义时间变量unsigned int second = 0, minute = 0, hour = 0;//定时器初始化函数void Timer_Init(){TMOD = 0x01; //定时器 0 工作在方式 1 TH0 =(65536 50000) / 256; //定时 50ms TL0 =(65536 50000) % 256;EA = 1; //开总中断ET0 = 1; //开定时器 0 中断TR0 = 1; //启动定时器 0}//定时器 0 中断服务函数void Timer0_ISR() interrupt 1{TH0 =(65536 50000) / 256;TL0 =(65536 50000) % 256;second++;if (second == 60){second = 0;minute++;if (minute == 60){minute = 0;hour++;if (hour == 24){hour = 0;}}}}//数码管显示函数void Display(){unsigned char i;for (i = 0; i < 8; i++)P2 = BIT_CODEi;if (i == 0){P0 = SEG_CODEhour / 10;}else if (i == 1){P0 = SEG_CODEhour % 10;}else if (i == 2){P0 = 0xBF; //显示“”}else if (i == 3){P0 = SEG_CODEminute / 10;else if (i == 4){P0 = SEG_CODEminute % 10;}else if (i == 5){P0 = 0xBF; //显示“”}else if (i == 6){P0 = SEG_CODEsecond / 10;}else if (i == 7){P0 = SEG_CODEsecond % 10;}delay_ms(1);//适当延时,防止闪烁}}//主函数void main(){Timer_Init();while (1){Display();}}```六、实验结果与分析1、实验结果将程序下载到单片机后,数字时钟能够正常运行,准确显示时、分、秒,并且通过按键可以进行时间的调整。
单片机实验报告(电子时钟)

一、课程设计的内容和要求:1了解单片机的种类,掌握单片机的工作原理;2 掌握利用单片机进行系统设计的方法;3掌握利用protel进行原理图设计和PCB设计的方法;4学会进行单片机硬件调试和软件调试;5 了解单片机系统整个设计开发流程。
二、设计装置功能1、用单片机实现设计要求(1)实现功能:①正常的24小时制的电子表功能显示(时/分/秒)。
②任意时间(时/分/秒)闹钟时刻的设置并在设定时刻响铃。
(2)所使用器件:STC 89C52RC单片机1个、2位共阳极数码管3个、蜂鸣器1个、74LS138一片、74LS47一片、74HC04一片、电阻、电容及其他辅助电子元件。
(3)显示时间与闹钟时刻的设置:单片机的人机操作部分由六个按钮组成。
从电子钟电路板上(从左到右)分别是:①单片机复位键②闹钟开关③小时位累加键④分钟位累加键⑤秒钟位累加键⑥闹钟/时间显示切换键按键说明:复位键——把3个2位数码管显示数字全部清零。
闹钟开关键——按下键,闹钟开关模式切换。
时针位累加键——按下键,则实现时针位的累加00-23(累加循环)。
分针位累加键——按下键,则实现分针位的累加00-59(累加循环)。
秒针位累加键——按下键,则实现秒针位的累加00-59(累加循环)。
闹钟/时间显示切换键——按下键,能够实现数码管闹钟和时间两种显示功能的切换。
三、设计问题分析面对的问题主要是两方面:一个是软件的设计,也就是实现计时定时的控制功能的程序编辑,在电脑上模拟需要实现的功能;另一个是硬件的设计,需要我们自己购买器件、设计并焊接电路板。
而更为重要的一步是将软件、硬件相结合,做好电路后,我们试着把程序写入芯片测试,然而没有获得应该有的显示,接着我们多次检查电路,修改程序,在不断调试中终于实现正确显示。
四、设计思路本次设计的系统以动态显示显示时分秒模块,它能显示正确的时间,而且所显示时间与北京时间相同,基本做到同步,显示清晰明亮,可读性强。
系统主程序开始后,首先是对系统环境初始化,设置好时分秒后系统开始运行;然后可打开闹钟,预设响铃的时刻,计时系统到该时刻后自动响设定铃声。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、实验内容:设计一个数字时钟,显示范围为00:00:00~23:59:59。
通过5个开关进行控制,其中开关K1用于切换时间设置(调节时钟)和时钟运行(正常运行)状态;开关K2用于切换修改时、分、秒数值;开关K3用于使相应数值加1调节;开关K4用于减1调节;开关K5用于设定闹钟,闹钟同样可以设定初值,并且设定好后到时间通过蜂鸣器发声作为闹铃。
选做增加项目:还可增加秒表功能(精确到0.01s)或年月日设定功能。
二、实验电路及功能说明1602显示器电路(不需接线)电子音响电路按键说明:按键键名功能说明K1切换键进入设定状态K2 校时依次进入闹钟功能是否启用,闹钟时,分秒,年,月,日及时间时,分,秒的设置,直到退出设置状态K3 加1键调整是否起用闹钟和调节闹钟时,分,秒,年,月,日,时间的时,分,秒的数字三、实验程序流程图:四、实验结果分析定时程序设计:单片机的定时功能也是通过计数器的计数来实现的,此时的计数脉冲来自单片机的内部,即每个机器周期产生一个计数脉冲,也就是每经过1个机器周期的时间,计数器加1。
如果MCS-51采用的12MHz晶体,则计数频率为1MHz,即每过1us的时间计数器加1。
这样可以根据计数值计算出定时时间,也可以根据定时时间的要求计算出计数器的初值。
MCS-51单片机的定时器/计数器具有4种工作方式,其控制字均在相应的特殊功能寄存器中,通过对特殊功能寄存器的编程,可以方便的选择定时器/计数器两种工作模式和4种工作方式。
定时器/计数器工作在方式0时,为13位的计数器,由TLX(X=0、1)的低5位和THX的高8位所构成。
TLX低5位溢出则向THX进位,THX计数溢出则置位TCON中的溢出标志位TFX.当定时器/计数器工作于方式1,为16位的计数器。
本设计师单片机多功能定时器,所以MCS-51内部的定时器/计数器被选定为定时器工作模式,计数输入信号是内部时钟脉冲,每个机器周期产生一个脉冲使计数器增1。
实时时钟实现的基本方法:这次设计通过对单片机的学习、应用,以A T89S51芯片为核心,辅以必要的电路,设计了一个简易的电子时钟,它主要通过51单片机综合仿真实验仪实现,通过1602能够准确显示时间,调整时间,它的计时周期为24小时,从而到达学习、设计、开发软、硬件的能力。
主要实现功能为显示时间,时间校准调时(采用手动按键调时),闹铃功能(设置定时时间,到点后闹铃发出响声)。
通过键盘可以进行校时、定时。
闹铃功能使用I/O 口定时翻转电平驱动的无源蜂鸣器。
本文主要介绍了工作原理及调试实现。
四个按键K1、K2、K3、K4、一个蜂鸣器。
1602显示时钟、跑表。
时钟的最小计时单位是秒,但使用定时器的方式1,最大的定时时间也只能达到131ms。
我们可把定时器的定时时间定为50ms。
这样,计数溢出20次即可得到时钟的最小计时单位:秒。
而计数20次可以用软件实现。
秒计时是采用中断方式进行溢出次数的累积,计满20次,即得到秒计时。
从秒到分,从分到时是通过软件累加并进行比较的方法来实现的。
要求每满1秒,则“秒”单元中的内容加1;“秒”单元满60,则“分”单元中的内容加1;“分”单元满60,则“时”单元中的内容加1;“时”单元满24,则将时、分、秒的内容全部清零。
实时时钟程序设计步骤:先对系统进行初始化,如:LCD1602初始化,DS1302初始化等,然后才能进入主显示模块,即可在LCD1602上看到相应的信息。
对于LCD1602的初始化,主要是对开启显示屏,清屏,设置显示初始行等操作。
DS1302的初始化主要是先开启写功能,然后写入一个初始值。
本系统采用的是LCD1602液晶显示器,由于其是本身带有驱动模块的液晶屏,所以对于LCD1602操作程序可分为开显示、设置显示初始行、写数据和清屏等部分。
LCD1602的写命令程序和写数据程序分别以子程序的形式写在程序里,以便主程序中的调用。
(1)选择工作方式,计算初值;(2)采用中断方式进行溢出次数累计;(3)计时是通过累加和数值比较实现的;(4)时钟显示缓冲区:时钟时间在方位数码管上进行显示,为此在内部RAM中要设置显示缓冲区,共6个地址单元。
显示缓冲区从左到右依次存放时、分、秒数值;(5)主程序:主要进行定时器/计数器的初始化编程,然后反复调用显示子程序的方法等待中断的到来;(6)中断服务程序:进行计时操作;(7)加1子程序:用于完成对时、分、秒的加操作,中断服务程序在秒、分、时加1时共有三种条调用加1子程序,包括三项内容:合字、加1并进行十进制调整、分字。
程序说明:按K1按键进入设定状态按K2,依次进入闹钟功能是否启用,闹钟时,分秒,年,月,日及时间时,分,秒的设置,直到退出设置状态按K3,调整是否起用闹钟和调节闹钟时,分,秒,年,月,日,时间的时,分,秒的数字LCD第二排中间显示小喇叭,表示启用闹钟功能,无则禁止闹钟功能(可在调整状态进行设置)正常状态,LCD上排最前面显示自定义字符,LCD下排最前面闪动"_"设置状态,LCD上排最前面显示"P",下排最前面在设置闹钟时间时显示"alarm_",其它状态显示"time"年代变化2000--2099,星期自动转换程序中有自定义字符写入在整个系统中,在单片机的30H、31H和32H中存储当前时间的小时、分钟和秒。
由于要用数码管显示当前的时间,必须用到分字和合字,因此在33H、34H、35H、36H、37H和38H中存储当前时间的时十位、时个位、分十位、分个位、秒十位和秒个位,方便显示。
本设计有由四个轻触按键组成的小键盘,这些按键可以任意改变当前的状态。
按功能移位键一次,表示当前要校对小时的十位;按第二次,表示当前校对的是小时的个位;按第三次,则表示校对的是分钟的十位;第四次,表示的校对的是分钟的个位。
按下数字“+”键和数字“-”键可在当前校对的数字上相应加上1或者减去1。
本设计采用查表方式,在程序里预先存储两个表格,即日常作息时间表和考试时间表,可以通过手动按键来选择所要执行的时间表。
并且用红、绿发光二极管来区别当前所执行的时间表。
系统开机后,按功能移位键就可以调整当前的时间,整个系统操作简单,功能明确。
显示数据时,先把要显示的数据送到数据缓冲区SBUF中,再从SBUF中显示。
串行口缓冲寄存器SBUF器是可直接寻址的专用寄存器。
在物理上,它对应着两个寄存器,一个发送寄存器,一个接收寄存器。
CPU写SBUF,就是修改发送寄存器;读SBUF,就是读接收寄存器。
接收器是双缓冲的,以避免在接收下一帧数据之前,CPU未能及时响应接收器的中断,没有把上一帧数据读走,而产生两帧数据重叠的问题。
对于发送器,为了保持最大的传输速率,一般不需要双缓冲,因为发送时CPU是主动的,不会产生写重叠的问题。
五、心得体会在享受我们成果之时,懂得的重要性与高难度性,所以为期一周的单片机课程设计没有浪费,我们从中学到了很多知识.,也让我们对单片机有了更深一步的了解.虽然最后结果是出来了,可这与老师的精心指导是分不开的。
通过对这程序的制作,是我对单片机的基本知识的使用更加熟练,同时也增加了我对单片机的一些认识,在作业完成过程中通过和同学的交流,也增加了合作的技巧。
通过查阅资料也学到了一些课本上没有的东西,拓宽了自己的知识面,增加了学好单片机的信心。
这次实训虽然其中会有些错误和失败,但总的来说是受益匪浅,在运用中发现问题,解决问题,就是最大的收获。
专心做自己的事,是一种乐趣;互相交流,是大家一起进步的必要过程;上网查阅资料,是获得所需信息的有效途径。
我想,这些练习和经验都将是我以后最宝贵的财富!附录:实验主程序及注释#include <reg51.h>#include <intrins.h>unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"} ;unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5};//星期月参变数unsigned char data dis_buf1[16];//lcd上排显示缓冲区unsigned char data dis_buf2[16];//lcd下排显示缓冲区unsigned char data year,month,date,week;//年、月、日、星期unsigned char data armhour,armmin,armsec;//闹钟时、分、秒unsigned char data hour,min,sec,sec100; //时、分、秒、百分之一秒unsigned char data flag,vkey,skey;//设置状态计数标志、按键先前值、按键当前值bit alarm; //标识是否启用闹钟,1--启用,0--关闭sbit rs = P2^0; //LCD数据/命令选择端(H/L)sbit rw = P2^1; //LCD读/写选择端(H/L)sbit ep = P2^2; //LCD使能控制sbit PRE = P3^3; //调整键(AN3)sbit SET = P3^4; //调整键(AN4)sbit SPK = P3^6;void delayms(unsigned char ms); //延时程序bit lcd_busy(); //测试LCD 忙碌状态程序void lcd_wcmd(char cmd); //写入指令到LCD程序void lcd_wdat(char dat); //写入数据到LCD程序void lcd_pos(char pos); //LCD数据指针位置程序void lcd_init(); //LCD初始化设定程序void pro_timedate(); //时间日期处理程序void pro_display(); //显示处理程序void pro_key(); //按键处理程序void time_alarm(); //定时报警功能(闹钟)unsigned char scan_key(); //按键扫描程序unsigned char week_proc(); //星期自动计算与显示函数bit leap_year(); //判断是否为闰年void lcd_sef_chr(); //LCD自定义字符程序void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s);//更新显示缓冲区函数// 延时程序void delay(unsigned char ms){ while(ms--){ unsigned char i;for(i = 0; i< 250; i++){_nop_(); //执行一条_nop_()指令为一个机器周期_nop_();_nop_();_nop_();}}}//测试LCD忙碌状态bit lcd_busy(){bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result =(bit)(P0&0x80); //LCD的D0--D7中,D7=1为忙碌,D7=0为空闲ep = 0;return result;}//写入指令到LCDvoid lcd_wcmd(char cmd){while(lcd_busy()); //当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写指令rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//写入数据到LCDvoid lcd_wdat(char dat){while(lcd_busy()); //当lcd_busy为1时,再次检测LCD忙碌状态,lcd-busy为0时,开始写数据rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//LCD数据指针位置程序void lcd_pos(char pos){lcd_wcmd(pos|0x80); //数据指针=80+地址码(00H~27H,40H~67H)}//设定二个自定义字符,(注意:LCD1602中自定义字符的地址为0x00--0x07,即可定义8个字符) //这里我们设定把一个自定义字符放在0x00位置(000),另一个放在0x01位子(001)void lcd_sef_chr(){ //第一个自定义字符lcd_wcmd(0x40); //"01 000 000" 第1行地址 (D7D6为地址设定命令形式D5D4D3为字符存放位置(0--7),D2D1D0为字符行地址(0--7))lcd_wdat(0x1f); //"XXX 11111" 第1行数据(D7D6D5为XXX,表示为任意数(一般用000),D4D3D2D1D0为字符行数据(1-点亮,0-熄灭)lcd_wcmd(0x41); //"01 000 001" 第2行地址lcd_wdat(0x11); //"XXX 10001" 第2行数据lcd_wcmd(0x42); //"01 000 010" 第3行地址lcd_wdat(0x15); //"XXX 10101" 第3行数据lcd_wcmd(0x43); //"01 000 011" 第4行地址lcd_wdat(0x11); //"XXX 10001" 第4行数据lcd_wcmd(0x44); //"01 000 100" 第5行地址lcd_wdat(0x1f); //"XXX 11111" 第5行数据lcd_wcmd(0x45); //"01 000 101" 第6行地址lcd_wdat(0x0a); //"XXX 01010" 第6行数据lcd_wcmd(0x46); //"01 000 110" 第7行地址lcd_wdat(0x1f); //"XXX 11111" 第7行数据lcd_wcmd(0x47); //"01 000 111" 第8行地址lcd_wdat(0x00); //"XXX 00000" 第8行数据//第二个自定义字符lcd_wcmd(0x48); //"01 001 000" 第1行地址lcd_wdat(0x01); //"XXX 00001" 第1行数据lcd_wcmd(0x49); //"01 001 001" 第2行地址lcd_wdat(0x1b); //"XXX 11011" 第2行数据lcd_wcmd(0x4a); //"01 001 010" 第3行地址lcd_wdat(0x1d); //"XXX 11101" 第3行数据lcd_wcmd(0x4b); //"01 001 011" 第4行地址lcd_wdat(0x19); //"XXX 11001" 第4行数据lcd_wcmd(0x4c); //"01 001 100" 第5行地址lcd_wdat(0x1d); //"XXX 11101" 第5行数据lcd_wcmd(0x4d); //"01 001 101" 第6行地址lcd_wdat(0x1b); //"XXX 11011" 第6行数据lcd_wcmd(0x4e); //"01 001 110" 第7行地址lcd_wdat(0x01); //"XXX 00001" 第7行数据lcd_wcmd(0x4f); //"01 001 111" 第8行地址lcd_wdat(0x00); //"XXX 00000" 第8行数据}//LCD初始化设定void lcd_init(){lcd_wcmd(0x38); //设置LCD为16X2显示,5X7点阵,八位数据借口delay(1);lcd_wcmd(0x0c); //LCD开显示及光标设置(光标不闪烁,不显示"-")delay(1);lcd_wcmd(0x06); //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动) delay(1);lcd_wcmd(0x01); //清除LCD的显示内容delay(1);}//闰年的计算bit leap_year(){bit leap;if((year%4==0&&year%100!=0)||year%400= =0)//闰年的条件leap=1;elseleap=0;return leap;}//星期的自动运算和处理unsigned char week_proc(){ unsigned char num_leap;unsigned char c;num_leap=year/4-year/100+year/400;//自00年起到year所经历的闰年数if( leap_year()&& month<=2 ) //既是闰年且是1月和2月c=5;elsec=6;week=(year+para_month[month]+date+num_ leap+c)%7;//计算对应的星期return week;}//更新显示缓冲区void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s){ dis_buf1[0]=t1; //dis_buf1[1]=0x20; //空格dis_buf1[2]=50; //'2'dis_buf1[3]=48; //'0'dis_buf1[4]=year/10+48;dis_buf1[5]=year%10+48;dis_buf1[6]=0x2d;dis_buf1[7]=month/10+48;dis_buf1[8]=month%10+48;dis_buf1[9]=0x2d; //'-'dis_buf1[10]=date/10+48;dis_buf1[11]=date%10+48;dis_buf1[12]=0x20;dis_buf1[13]=dis_week[4*week];dis_buf1[14]=dis_week[4*week+1];dis_buf1[15]=dis_week[4*week+2];dis_buf2[0]=t2[0];dis_buf2[1]=t2[1];dis_buf2[2]=t2[2];dis_buf2[3]=t2[3];dis_buf2[4]=t2[4];dis_buf2[5]=t2[5];dis_buf2[6]=t2[6]; //空格if (alarm)dis_buf2[7]=0x01; //alarm=1,显示闹钟启用标致(第二个自定义字符)elsedis_buf2[7]=0x20; //alarm=0,不显示闹钟启用标致dis_buf2[8]=dis_h/10+48;dis_buf2[9]=dis_h%10+48;dis_buf2[10]=0x3a; //':'dis_buf2[11]=dis_m/10+48;dis_buf2[12]=dis_m%10+48;dis_buf2[13]=0x3a;dis_buf2[14]=dis_s/10+48;dis_buf2[15]=dis_s%10+48;}//时间和日期处理程序void pro_timedate(){sec++;if(sec > 59){sec = 0;min++;if(min>59){min=0;hour++;if(hour>23){hour=0;date++;if(month==1||month==3||month==5||month==7||m onth==8||month==10||month==12)if (date>31) {date=1;month++;} //大月31天if(month==4||month==6||month==9||month==11)if (date>30) {date=1;month++;} //小月30天if (month==2){if( leap_year())//闰年的条件{if (date>29) {date=1;month++;}} //闰年2月为29天else{if (date>28) {date=1;month++;}} //平年2月为28天}if (month>12) {month=1;year++;}if (year>99) year=0;}}}week_proc();if (sec==armsec && min==armmin && hour==armhour){if (alarm)TR1=1; //闹钟启用时,报警时间到,启动Timer1}}//显示处理程序void pro_display(){ unsigned char i;lcd_pos(0x00);for (i=0;i<=15;i++){lcd_wdat(dis_buf1[i]);}lcd_pos(0x40);for (i=0;i<=15;i++){lcd_wdat(dis_buf2[i]);}}//Timer0中断处理程序,秒的产生void timer0() interrupt 1{TH0=0xD8;TL0=0xF0;sec100++;if(sec100 >= 100) //1秒时间(100*10ms=1000ms=1s){sec100 = 0;pro_timedate();//调用时间和日期处理程序}if (sec&0x01)//"__run__"闪一秒,停一秒update_disbuf(0x00,"",hour,min,sec); //0x00表示显示00位置的自定义字符elseupdate_disbuf(0x00,"__run__",hour,min,sec) ;pro_display(); //调用显示处理函数}//按键扫描程序unsigned char scan_key(){skey=0x00;//给变量vkey置初值skey|=PRE;//读取PRE键的状态skey=skey<<1;//将PRE键的状态存于skey的B1位skey|=SET;//读取SET键的状态,并存于skey的B0位return skey;//返回skey的键值(即PRE,SET的状态) }//外部中断INT0中断处理程序void int0() interrupt 0{TR0=0;//禁止Timer0IE=0;//禁止中断lcd_wcmd(0x0e);//显示光标"_",整个光标不闪烁alarm=1;update_disbuf(0x50,"alarm_",armhour,ar mmin,armsec); //更新显示数据,0x50表示要显示"P"pro_display();//调用显示处理程序lcd_pos(0x47);//使光标位于第一个调整项下flag=0;vkey=0x03;while(flag^0x0a){skey = scan_key();//扫描按键状态if (skey^vkey)//若skey与vkey相同,跳出循环,相异执行循环体{ delay(10);//去按键抖动skey = scan_key();//转回扫描按键状态if (skey^vkey)//若skey与vkey相同,跳出循环,相异执行循环体{ vkey=skey;//将skey的值付给vkeyif (skey==0x01) //PRE键按下{flag++; //调整标志位加1switch (flag) //将光标置于相应调整位置{case 1: lcd_pos(0x49);break; //光标置小时报警设置位置case 2: lcd_pos(0x4c);break; //光标置分钟报警设置位置case 3: lcd_pos(0x4f);break; //光标置秒时报警设置位置case 4: update_disbuf(0x50,"time_",hour,min,sec);pro_display();lcd_pos(0x05);break; //光标置年调整位置case 5: lcd_pos(0x08);break; //光标置月调整位置case 6: lcd_pos(0x0b);break; //光标置日调整位置case 7: lcd_pos(0x49);break; //光标置时调整位置case 8: lcd_pos(0x4c);break; //光标置分调整位置case 9: lcd_pos(0x4f);break; //光标置秒调整位置default:break;}}if (skey==0x02) //SET键按下{pro_key(); //转设置按键处理程序}}}}lcd_wcmd(0x0c);//设置LCD开显示及光标不闪烁,不显示"-"lcd_wcmd(0x01);//清除LCD的显示内容IE=0x8f;//CPU开中断,INT0,INT1,开中断TR0=1;//Timer0启动}//主程序,初始化及初值设定void main(){lcd_init(); //初始化LCDlcd_sef_chr(); //写入自定义字符号hour=0;min=0;sec=0; //开机时的时,分,秒显示armhour=0;armmin=0;armsec=0; //开机时的时,分,秒报警初值year= 5; month=1;date=1; //开机时的年,月,日,星期显示week_proc();alarm=1; //初始开机,启用闹钟IE = 0x8f;//CPU开中断,INT0,INT1,Timer0,Timer1开中断IP = 0x04; //设置INT0为中断最高优先级IT0=0;IT1=0; //外部INT0,INT1设置为电平触发方式(注意,触发不要选边沿方式,易误动)TMOD = 0x11;//Timer0,Timer1工作于模式1, 16位定时方式TH0 = 0xdc;TL0 = 0x00;//Timer0置10ms定时初值TH1 = 0xff;TL1 = 0x00;//Timer1置初值TR0 = 1;//Timer0启动TR1 = 0;while(1);}//设置按键处理程序void pro_key(){switch (flag){case 0:alarm=!alarm; //启用或关闭闹钟(alarm=1:启用,alarm=0:关闭)update_disbuf(0x50,"alarm_",armhour,ar mmin,armsec); //更新显示数据pro_display();//调用显示处理lcd_pos(0x47);break;//光标回到原调整位置case 1:armhour++;if (armhour>23) armhour=0;update_disbuf(0x50,"alarm_",armhour,armmin,armsec); //更新显示数据pro_display();//调用显示处理lcd_pos(0x49);break;//光标回到原调整位置case 2:armmin++;if (armmin>59) armmin=0;update_disbuf(0x50,"alarm_",armhour,armmin,armsec);pro_display();lcd_pos(0x4c);break;case 3:armsec++;if (armsec>59) armsec=0;update_disbuf(0x50,"alarm_",armhour,armmin,armsec);pro_display();lcd_pos(0x4f);break;case 4:year++;if (year> 99) year= 0;week_proc(); //星期自动运算update_disbuf(0x50,"time_",hour,min,sec);pro_display();lcd_pos(0x05);break;case 5:month++;if (month>12) month=1;week_proc();//星期自动运算update_disbuf(0x50,"time_",hour,min,sec);pro_display();lcd_pos(0x08);break;case 6:date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)if (date>31) date=1;//大月31天if(month==4||month==6||month==9||month==11)if (date>30) date=1;//小月30天if (month==2){if(leap_year())//闰年的条件{if (date>29) date=1;} //闰年2月为29天else{if (date>28) date=1;}} //平年2月为28天week_proc();//星期自动运算update_disbuf(0x50,"time_ ",hour,min,sec);pro_display();lcd_pos(0x0b);break;case 7:hour++;if (hour>23) hour=0;update_disbuf(0x50,"time_ ",hour,min,sec);pro_display();lcd_pos(0x49);break;case 8:min++;if (min>59) min=0;update_disbuf(0x50,"time_ ",hour,min,sec);pro_display();lcd_pos(0x4c);break;case 9:sec++;if (sec>59) sec=0;update_disbuf(0x50,"time_ ",hour,min,sec);pro_display();lcd_pos(0x4f);break;default: break ;}} //Timer1中断处理程序,产生报警的声音void timer1() interrupt 3{TH1=0x80;TL1=0x00;SPK=~SPK;t++;}//外部中断INT1中断处理程序,停止报警声音void int1() interrupt 2{if(TR1)TR1=0;}。