《毕业论文-于基pic16f877的led旋转时钟单片机设计实验报告.doc》由会员分享,可在线阅读,更多相关《毕业论文-于基pic16f877的led旋转时钟单片机设计实验报告.doc(36页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、班 号 单片机设计实验报告2013年小学期单片机设计实验报告题目:基于PIC16F877单片机的LED旋转时钟班 级: 学 号: 班内序号: 实验组号: 学生姓名: 指导教师: 期中检查教师评语指导教师签字: 年 月 日基于PIC16F877单片机的LED旋转时钟 班 实验摘要 本次我们制作的基于PIC16F877单片机的LED旋转时钟是能够输入、显示时间的时钟。结构新颖,效果奇特。加入了现代科技的元素,利用人眼的视觉暂留特性,解决了传统时钟结构单一,显示效果固定的缺陷,更好了满足了人们对美的追求。整个系统中,微控制器采用了Microchip公司的PIC16F877,软件设计中涉及PORTA用
2、作普通数字I/O脚控制按键输入,PORTB、PORTC控制灯的亮灭,PORTD向时钟芯片DS1302写入和读出时间。概括来说,本实验就是用人眼的视觉暂留特性,用PIC16F877单片机作为主控芯片,采用电机带动发光二极管高速旋转,利用频闪显示原理呈现时钟画面。AbstractIn this experiment, we made a LED rotating clock base on PIC16F877 MCU. It can input and show time. Its structure is novel and its effect is amazing. Its full of
3、modern technology element. With human eyes persistence of vision, it solves traditional clocks structure and effects disadvantage, fits human pursue for beauty better.The system uses the production of the Microchip cord-PIC16F877. The design includes the drive of PORTA as general digital ports to in
4、put time, the drive of PORTB and PORTC to control the LEDs on, the drive of PORTD to write and read time on DS1302. In conclusion, with human eyes persistence of vision, this experiment uses PIC16F877 MCU as master chip, uses motor to drive LED rotate at high speed, uses strobe display principle to
5、show the clock.关键字单片机microcontroller 芯片CMOS chip LED旋转时钟- LED rotating clock一.实验论证与比较1.LED显示模块LED的特点非常明显,寿命长、光效高、无辐射与低功耗。LED的光谱几乎全部集中于可见光频段,其发光效率可达8090%。将LED与普通白炽灯、螺旋节能灯及T5三基色荧光灯进行对比,结果显示:普通白炽灯的光效为12lmW,寿命小于2000小时,螺旋节能灯的光效为60lmW,寿命小于8000小时,T5荧光灯则为96lmW,寿命大约为10000小时,而直径为5毫米的白光LED为2028lmW,寿命可大于100000小
6、时。有人还预测,未来的LED寿命上限将无穷大。由于LED的种种优势,使得其在现在的各个领域里运用越来越广泛,我们设计的旋转LED显示屏幕,具有结构新颖,节约材料的特点,一列16个LED灯旋转显示之后,可以代替显示近似于16x120像素的显示宽度和内容。旋转时钟是利用视觉暂留效应设计出来的,物体在快速运动时, 当人眼所看到的影像消失后,人眼仍能继续保留其影像0.1-0.4秒左右的图像,这种现象被称为视觉暂留现象。是人眼具有的一种性质。人眼观看物体时,成像于视网膜上,并由视神经输入人脑,感觉到物体的像。但当物体移去时,视神经对物体的印象不会立即消失,而要延续0.1 -0.4秒的时间,人眼的这种性质
7、被称为“眼睛的视觉暂留”。假设我们设定我们的眼睛的暂留时间是0.4秒,如果我们的16个LED旋转一周的时间快过0.4秒,那么我们看到的图像就是这一列LED在各个位置显示的图像的叠加,如右图,如果我们用定时器把LED旋转一周的各个位置分割出120分,让它在相应的位置显示相应的图像,那么我们就可以得到一个累加的图像效果了。旋转LED时钟的实现方法是把一组LED(16个左右) 紧密的排列成一条直线,组成一条LED列,每个LED都由PIC单片机来控制其点灭。把整个电路板固定在电机上,使得紧密排列的LED条的一端固定在电机的旋转轴附近,如图所示。电路板转过一圈的时间极短,远小于0.1秒。通过单片机控制L
8、ED灯在一圈内转到不同位置时的亮灭,来显示图像或文字。2.DS1302时钟模块大多数的单片机没有实时时钟部件,一旦系统掉电时钟就不能运行,下次再运行,时间就不准确了。即便使用备用电池,但要维持单片机系统的较大功耗也是坚持不了多久的。而我所做的旋转时钟用到的单片机主要是来准确显示时间的,因此实时时钟部件必不可少,这里我用了MAXIM公司的DS1302时钟芯片作为实时时钟部件,保证时间的长久准确性。DS1302 有着很强的功能。包括时钟/日历寄存器和31 字节(8位)的数据暂存寄存器,数据通信仅通过一条串行输入输出口。实时时钟/日历提供包括秒、分、时、日期、月份和年份信息。闰年可自行调整,可选择A
9、M/PM的12 小时制或24小时制。只通过三根线进行数据的控制和传递:CE(输入信号,在读、写数据期间,必须为高。该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。);I/O(三线接口时的双向数据线);SCLK(串行时钟输入)。通过备用电源可以让芯片在小于1MW的功率下运作。对时钟寄存器初始化可以设定当前时间,控制芯片的运行,时间是用BCD码保存的,RAM可以用来存取用户数据,在用了备用电池后RAM内的数据在系统掉电时能够保持不丢失。芯片采用了简单的I2C 三线通信方式,便于节省芯片资源和与之接口的MCU的引脚。芯片有着2.05.5
10、V的宽供电电压范围,在5V供电时其接口与TTL电平兼容。并且有着很低的功耗,在2.0V供电时仅耗300nA 的电流。引脚X1 和X2 连接32.768kHz 晶体,与内部振荡器组成时钟。晶体的精度直接影响着芯片时间的准确与否。DS1302有两个电源引脚VCC1和VCC2,分别连接备用电池和电源VCC。VCC2与主电源连接,VCC1接备用电池。当VCC2低于VCC1时,芯片由VCC1供电;当VCC2-VCC10.2V时,备用电池为芯片供电。在VCC2供电时芯片能够对接在VCC1的备用电池充电,并且是否充电和充电电流都可以由芯片内地址为08H的时钟寄存器进行控制。DS1302与单片机的硬件接线图如
11、图三所示。 图三 DS1302硬件接线图在进行任何数据传输时,CE必须被制高电平(虽然CE被置为高电平,但内部时钟还是在晶振作用下不停地计时的),在每个SCLK上升沿时读入数据,下降沿时写出数据。每个字节的传输都是由控制字节(如表1所示)指定的,控制字节的最高位Bit7必须是“1”,否则读写将会被禁止。bit6 为“0”则指定对时钟/日历寄存器进行读写操作,为“1”则对RAM区的数据进行读写操作,bit1-bit5 指定相关寄存器进行输入输出操作,最低位bit0 指定是输入还是输出,为“0”则为写,相反则为读,输入输出根据脉冲的上升沿和下降沿串行进行。765432101RAM/用来表示相关寄存
12、器的地址RD/表1 DS1302控制字节控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。数据读写时序如图四所示。图四 DS1302数据读写时序通过8个脉冲便可读取一个字节,从而实现串行输入与输出。最初通过8个时钟周期载入控制字节到移位寄存器。如果控制指令选择的是单字节模式,连续的8个时钟脉冲可以进行8位数据的读写操作。8个脉冲便可读写一个字节。载入控制字节后就可以对时钟/日历寄存器进行相应操作,时
13、钟/日历寄存器如下表所示。读寄存器写寄存器BIT7BIT6BIT5BIT4BIT3BIT2-BIT0范围81h80hCH16-59秒0-15秒00-5983h82h16-59分0-15分00-5985h84h12020-2315-19时0-15时1-12/0-23/PM87h86h00016-31日0-15日1-3189h88h00010月月1-128Bh8Ah000001-7周1-78Dh8Ch015-99年0-15年00-998Fh8EhWP0秒寄存器(81h、80h)的位7定义为时钟暂停标志(CH)。当该位置1时,时钟振荡器停止,DS1302处于低功耗状态;当该位置为0时,时钟开始运行。
14、小时寄存器(85h、84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。当为高时,选择12小时模式。在12小时模式下,位5为1时,表示PM。在24小时模式时,位5是第二个10小时位(20-23时)。控制寄存器(8Fh、8Eh)的位7是写保护位(WP),其它7位均置为0。在任何的对时钟和RAM的写操作之前,WP位必须为0。当WP位为1时,写保护位防止对任一寄存器的写操作。二.系统总体设计系统模块总体框图如下:6V电源2.7V电源单片机(PIC16F877)控制亮灭显示模块(LED灯)控制转动电动机输入时间时间存储模块 DS1302输入模块(按键)底座 转动部分开始程序总体框图
15、:输入时间时间写入DS1302开始旋转,显示时钟界面结束输入时间模块框图该模块利用两个按键sw1和sw2实现时间输入。sw1按一次时间加1,sw2按一次切换时、分、秒的输入。按完三次sw2结束。通过八个LED灯显示输入的时间的二进制数。开始程序框图如下:是否切换否是输入时,亮灯是否切换否 是输入分,亮灯是否切换否是输入秒,亮灯结束DS1302读写模块写时间程序框图:开始关闭写保护写入地址写入1字节打开写保护结束读时间程序框图:开始关闭写保护写入地址读取1字节打开写保护结束4.LED显示模块单片机转20圈(小于1秒)从DS1302读一次数。将表盘分成120格,走一格计数器加1。开始程序框图:判断
16、是否转20圈,转20圈从DS1302读一次时间判断计数器是否为120,是120则清0。判断是否为表盘位置,是则点亮表盘是否秒针?否是否分针?否是是否时针?否延时点亮指针,延时计数器加1三. 硬件连接两个按键sw1和sw2接PORTA0和PORTA1。PORTB和PORTC接16个LED灯。PORTD0接DS1302的SLCK(时钟),PORTD1接DS1302的I/O接口, PORTD2接DS1302的CE(使能端)。马达上套一个轮子,用万能胶粘在电路板上。PIC单片机和LED灯由电路板上两个纽扣电池供电。实物连接图:正面图:背面图:侧面图:局部细节图:效果图:电路原理图:四.调试过程在此,列
17、举几个调试过程中遇到的的问题。1.RA端口的输入和输出问题上述提到我们用RA0、RA1接上两个按键给单片机输入时间,但是,我在编写好程序进行单步调试时,发现尽管我用异步激励将这三个端口设置为高电平,在观察窗口中RA的值没有丝毫变化。经过思考,并联系提高篇中讲到的RA端口兼备5条数/模转换器的模拟量输入通道,在将RA端口当作普通数字输入/输出端口时需要将其控制寄存器ADCON1的低四位送入011x(x取0或1均可)。因此,修改程序后,再次编译和调试,问题得到解决。2.DS1302的编码问题开始我没有注意DS1302里存的是BCD码而不是普通二进制码,结果秒针一跳一跳的不能连续地走。修改完后时间恢
18、复正常。3.读取时间的问题单片机读取DS1302需要一定的时间。每秒钟时钟大概转二十几转,每转一圈读一次时间没有必要,所以我设定转20圈(一秒钟内)读一次时间。五.参考文献:PIC单片机实用教程基础篇 (五号 宋体)李学海北京航空航天大学出版社使用说明:的确是一本不可或缺的教材,本书列举了很多实用的具有实战意义的例子,单片机入门就是通过把这本书里的好例子一字一行敲进电脑去来实现的。PIC单片机实用教程提高篇李学海北京航空航天大学出版社使用说明:继承了前面基础篇的风格,例子也具有实战意义,主要讲RA、TMR2的使用和CCP模块的PWM脉宽调制功能。六.实验心得体会通过本次实验,我对单片机有了一个
19、初步的认识,也能用汇编编写一些简单的程序。这次的程序800行左右,不长,但绝大多数是我自己打的。看着单片机能够实现自己编写的程序所设定的功能,还是很有自豪感的。这次实验对我的动手实践能力是一次极大的考验,我也从中学到了很多东西。除了动手能力有所提高外,得益于二人组队的形式,我也明白了团队协作的重要性,获得了许多与他人合作的经验。在这里也要感谢我的两位老师和队友,他们在实验过程中给予了我非常大的帮助,没有他们,这个单片机很难完成。我也非常希望能够在以后还能遇上这种动手实践的机会,这是一个很好的提升能力的机遇。下附汇编代码:注意,此代码有BUG,秒针会先用55秒走完60秒,然后消失5秒,再出现在0
20、秒处。去掉按键输入时间的模块,直接在程序里把时间打进去,秒针又恢复正常。我研究了几个小时也没找到问题在哪。#DEFINE T_IO portd,1 ;1302 I_O #DEFINE T_CLK portd,0 ;1302时钟 #DEFINE T_RST portd,2 ;1302使能位 #DEFINE DS1302_RX 27H ;保存接受的1个数据 #DEFINE DS1302_TX 28H ;准备写入到DS1302的一个数据 indfequ00hstatus equ 03hrp0 equ 5hCequ0hZequ2hfsrequ04hadcon1equ9fhtrisb equ 86htr
21、isc equ 87htrisdequ88hportb equ 06hportc equ 07hportdequ08hportaequ05htrisaequ85hn equ 20h ;延时循环变量counter equ 21h;指针位置计数器secnequ22h;秒针列数minnequ23h;分针列数hournequ24h;时针列数jumpdecequ25h;跳转判断,0位秒,1位分,2位时hourcequ26h;d10,时钟计数循环变量counter1 equ 29h temp_cnt equ 2ah W_Secondequ2bhW_Minuteequ2chW_Hourequ2dhSecAd
22、drequ2ehsecequ2fhminequ30hhourequ31hreadnequ32htr1equ33htr2equ34hbcdnequ35hdata1 equ 36hdata2 equ 37hn1 equ d13n2 equ 0ffhtb1equ38h;十位tb2equ39h;个位;-;主程序;-;-;输入时间;-org0000hgotomainorg0005hmain bsf status,rp0 clrf trisc ;设置c口输出 clrf trisb ;设置b口输出clrftrisd ;设置d口输出 movlw 0ffh movwf trisa;a口定义为输入movlw06h
23、movwfadcon1;a口设为数字I/O bcf status,rp0;体0clrfsecnclrfminnclrfhournclrfjumpdecclrfportbclrfportc;c口灯灭clrfportdclrfW_HourclrfW_MinuteclrfW_SecondsetW_Hourbtfssporta,1 ;sw2是否按下 gotosetW_Minute1check btfsc porta,0;测开关sw1按下否?是,跳过下条指令 goto setW_Hour;否!则循环检测 call delay btfsc porta,0;再次测开关sw1按下否?是,跳过下条指令 goto
24、 check;否!则循环检测incfW_Hour,1 ;时针加1movlwd12subwfW_Hour,0 ;看是否等于12 btfsc status,ZclrfW_HourmovfW_Hour,0movwfportccheck1 btfss porta,0;测开关sw1断开否?是,跳过下条指令 goto check1;否!则循环检测 call delay btfss porta,0;再次测开关sw1断开否?是,跳过下条指令 goto check1;否!则循环检测 goto setW_Hour;返回setW_Minute1btfssporta,1;sw2松开否gotosetW_Minute1c
25、alldelaybtfssporta,1gotosetW_Minute1setW_Minutebtfssporta,1 ;sw2是否按下 gotosetW_Second1check2 btfsc porta,0;测开关sw1按下否?是,跳过下条指令 goto setW_Minute;否!则循环检测 call delay btfsc porta,0;再次测开关sw1按下否?是,跳过下条指令 goto check2;否!则循环检测incfW_Minute,1 ;分针加1movlwd60subwfW_Minute,0 ;看是否等于60 btfsc status,ZclrfW_MinutemovfW_
26、Minute,0movwfportccheck3 btfss porta,0;测开关sw1断开否?是,跳过下条指令 goto check3;否!则循环检测 call delay btfss porta,0;再次测开关sw1断开否?是,跳过下条指令 goto check3;否!则循环检测 goto setW_Minute;返回setW_Second1btfssporta,1gotosetW_Second1calldelaybtfssporta,1gotosetW_Second1setW_Secondbtfssporta,1 ;sw2是否按下 gotobegincheck4 btfsc porta
27、,0;测开关sw1按下否?是,跳过下条指令 goto setW_Second;否!则循环检测 call delay btfsc porta,0;再次测开关sw1按下否?是,跳过下条指令 goto check4;否!则循环检测incfW_Second,1 ;秒针加1movlwd60subwfW_Second,0 ;看是否等于60 btfsc status,ZclrfW_SecondmovfW_Second,0movwfportccheck5 btfss porta,0;测开关sw1断开否?是,跳过下条指令 goto check5;否!则循环检测 call delay btfss porta,0;
28、再次测开关sw1断开否?是,跳过下条指令 goto check5;否!则循环检测 goto setW_Second;返回begin calltbcd;-;显示时间;-callSet_DS1302rsrnmovlwd20movwfreadn;20圈读一次时间showmovlwd20subwfreadn,0btfscstatus,ZcallGet_DS1302callbcdtdecfreadn,1clrfcounter;指针位置计数器清零 judgecallclearc;清表盘movlwd119subwfcounter,0btfscstatus,Zgotorsrn ;判断指针位置计数器是否达到11
29、9;*是否显示刻度*movlwd0subwfcounter,0btfscstatus,Zcalldraw2_0movlwd1subwfcounter,0btfscstatus,Zcalldraw2_1movlwd2subwfcounter,0btfscstatus,Zcalldraw2_2movlwd3subwfcounter,0btfscstatus,Zcalldraw2_3movlwd10subwfcounter,0btfscstatus,Zcalldrawgramovlwd20subwfcounter,0btfscstatus,Zcalldrawgramovlwd27subwfcount
30、er,0btfscstatus,Zcalldraw3_0movlwd28subwfcounter,0btfscstatus,Zcalldraw3_1movlwd29subwfcounter,0btfscstatus,Zcalldraw3_2movlwd30subwfcounter,0btfscstatus,Zcalldraw3_3movlwd31subwfcounter,0btfscstatus,Zcalldraw3_4movlwd32subwfcounter,0btfscstatus,Zcalldraw3_5movlwd33subwfcounter,0btfscstatus,Zcalldra
31、w3_6movlwd40subwfcounter,0btfscstatus,Zcalldrawgramovlwd50subwfcounter,0btfscstatus,Zcalldrawgramovlwd58subwfcounter,0btfscstatus,Zcalldraw6_0movlwd59subwfcounter,0btfscstatus,Zcalldraw6_1movlwd60subwfcounter,0btfscstatus,Zcalldraw6_2movlwd61subwfcounter,0btfscstatus,Zcalldraw6_3movlwd62subwfcounter
32、,0btfscstatus,Zcalldraw6_4movlwd70subwfcounter,0btfscstatus,Zcalldrawgramovlwd80subwfcounter,0btfscstatus,Zcalldrawgramovlwd87subwfcounter,0btfscstatus,Zcalldraw9_0movlwd88subwfcounter,0btfscstatus,Zcalldraw9_1movlwd89subwfcounter,0btfscstatus,Zcalldraw9_2movlwd90subwfcounter,0btfscstatus,Zcalldraw9
33、_3movlwd91subwfcounter,0btfscstatus,Zcalldraw9_4movlwd92subwfcounter,0btfscstatus,Zcalldraw9_5movlwd93subwfcounter,0btfscstatus,Zcalldraw9_6movlwd100subwfcounter,0btfscstatus,Zcalldrawgramovlwd110subwfcounter,0btfscstatus,Zcalldrawgramovlwd116subwfcounter,0btfscstatus,Zcalldraw1_0movlwd117subwfcount
34、er,0btfscstatus,Zcalldraw1_1movlwd118subwfcounter,0btfscstatus,Zcalldraw1_2;*是否显示秒针*movfsec,0movwfsecnaddwfsecn,1movfsecn,0subwfcounter,0btfscstatus,Zcalldrawsecclrfsecnbtfssjumpdec,0gotodec_mingotosd04;*是否显示分针*dec_minmovfmin,0movwfminnaddwfminn,1movfminn,0subwfcounter,0btfscstatus,Zcalldrawminclrfm
35、innbtfssjumpdec,1gotodec_hourgotosd04;*是否显示时针*dec_hourmovlwd10movwfhourcaddhmovfhour,0addwfhourn,1decfszhourc,1gotoaddhmovfmin,0movwfminnjudhmovlwd6subwfminn,1btfscstatus,Cgotopoint1gotopoint2point1incfhourn,1gotojudhpoint2movfhourn,0subwfcounter,0btfscstatus,Zcalldrawhourclrfhournclrfminnbtfssjumpd
36、ec,1gotosd05gotosd04sd04calldelay04;callclearc;calldelay01;gotoadd;sd05calldelay05addincfcounter,1;指针位置计数器加1clrfjumpdecgotojudge;*delay ;10ms延时子程序,防抖 movlw n1 movwf data1ip0 movlw n2 movwf data2ip1 decfsz data2,1 goto ip1 decfsz data1,1 goto ip0 return;-;2进制转BCD;-tbcdclrftb1movfW_Hour,0movwftb2movlwd10divsubwftb2,1btfssstatus,Cgotopoint3incftb1,1gotodivpoint3movlwd10addwftb2,1swapftb1,1movftb1,0iorwftb2,0movwfW_Hourclrftb1movfW_Minute,0movwftb2movlwd10div1subwftb2,1btfssstatus,Cgotopoint4incftb1,1gotodiv1point4movlwd10addwftb2,1swapftb1,1movftb1,0