指针式模拟时钟_第1页
指针式模拟时钟_第2页
指针式模拟时钟_第3页
指针式模拟时钟_第4页
指针式模拟时钟_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 陕西理工学院毕业设计毕业设计 题 目 用PG12864LCD设计的指针式电子钟 学生姓名 王康康 学号 1110064047 所在院(系) 物理与电信工程学院 专业班级 电子信息科学与技术1102 指导教师 杨创华 完成地点 实验楼1104教室 2015年5月目录引言11 设计任务及方案论证11.1设计任务与要求11.2 总体方案论证与设计12系统硬件设置12.1 STC89C51单片机简介12.2显示模块设计32.2.1 PG12864LCD的特性介绍42.2.2 LCD12864引脚介绍42.2.3 12864内部功能器件及相关功能52.2.4 12864液晶与单片机接口电路62.3设置

2、模块82.4 振荡电路92.5 复位电路93系统软件设计93.1总体软件设计93.2 时钟函数模块103.3 指针时钟设计113.3.1 实现功能113.3.2实现算法113.3.3 函数设计133.4 显示函数模块153.4.1实现功能173.4.2 函数设计173.5.1 功能183.5.2 函数183.6主函数模块194.设计结果205.使用方法206.设计进度207.教学单位可以提供的条件20致谢21参考文献21用PG12864LCD设计的指针式电子钟王康康(陕西理工学院物理与电信工程学院电子信息科学与技术专业电信1102班,陕西汉中 723000)指导教师:杨创华 摘要本设计采用的是

3、STC89C51单片机,通过单片机内部定时器定时实现时钟定时计数功能,并以模拟时钟的形式显示在LCD_12864上。同时可通过三个按键可实现时间的调节。 关键词时钟 AT89C51单片机 LCD12864液晶By using the analog electronic clock design PG12864LCDWang kangkang (Grade11,Class2,Major Electronic Information Science and Technology,Physics Dept.,Shaanxi University of Technology,Hanzhong 7230

4、00,Shaanxi)Tutor:Yang chuanghua Abstract :This design uses STC89C51 microcontroller, through the MCU internal timer from time to time to achieve the clock timing and counting function and in the form of analog clock display on the LCD 12864. At the same time can be adjusted by the three keys to real

5、ize the time. Keywords: AT89C51microcontroller LCD12864 LCD clock引言如今二十一电子钟、机械式手表等钟表已经普遍存在于市场,并且钟表已经成为人们生活中不可缺少的一部分。在生活中到处都能看到其身影。当穿行于马路上时总会看到几乎每个人手腕上戴着一块手表。当大人家里做客时总能看到大厅里面挂着个钟表。当打开手机时屏幕上依旧是钟表的画面。时间伴随着我们钟表也成为我们生活中必不可少的一大部分。当今市场有好多电子钟,但大多数是纯数字式的,指针式的电子钟比较新颖,而且具有真实表盘式时钟的效果。用PG12864LCD设计的模拟电子钟采用PG1286

6、4LCD液晶屏,用来模拟表盘与时分秒指针指示当前时钟,此模拟指针式电子钟实现的功能为:在PG12864显示屏上显示圆形表盘与时分秒三个指针表示当前时刻;三个按键,K1键用来选择工作模式;K2键用来选择调整时分秒;K3键用来调节大小。1 设计任务及方案论证 1.1设计任务与要求利用单片机等器件做一个简易的模拟指针式时钟,硬件设计以单片机为主,主要包括显示模块、复位模块、时钟模块。采用PG12864液晶屏作为显示单元,液晶屏上显示圆形表盘、时、分、秒指针,并且设置按钮可以调节时间,软件设计主要是通过单片机编程软件Keil C51设计,模拟仿真是利用仿真软件Proteus对所设计的硬件电路和程序进行

7、调试。 1.2 总体方案论证与设计在设计中要包含显示模块,控制器,设置模块;方案一:利用基于MFC的Windows应用程序在屏幕上显示一个指针式时钟,并可通过菜单选项对时间调节,设计的时钟画面清晰,显示准确,但缺点是时间必须与系统机器时间一样,不可以随意设置时间,另外此方案涉及微软基础类库,对于不熟悉的我们难度较大。方案二:因此我们采用另一套方案,显示模块用LCD12864模块,可以显示系统时间;整个代码实现主要由51单片机来实现;设置模块为按键处理可自行调节时间,整体流程以AT89C51单片机为控制核心,将得到的数据通过LCD12864模块显示出来,同时通过相应的按键调整相应的值,此方案具有

8、设计简单,成本低廉,可执行度高等优点,因此采用本方案。图2.1 STC89C51管脚图2系统硬件设置 2.1 STC89C51单片机简介 在设计中可用STC89C5代替AT89C51,此芯片具有速度更高,功能更全,寿命更长,价格更低等优点;我们采用双列直插40引脚的 STC89C51,它可以实现ISP在线编程功能,然而AT89C51则不可以,将AT89C51的程序通过软件直接下载到STC89C51中后,就可以代替AT单片机直接工作,基本上都不需要做修改就可以正常工作了,STC公司推出的51系列单片机芯片是兼容其它51单片机的,而51单片机作为单片机界的应用最广泛芯片,几乎每一个高等院校、普通学

9、校、网站、业余单片机培训都是用51单片机作为基础而学习的,正是因为如此可以利用的参考资料和例子也是最多的, 而且由于STC89C51自带有EEPROM,其在程序中更是可以直接修改,断电之后也不会丢失数据。STC89C51单片机管脚图如图2.1所示:STC89C51单片机的引脚介绍:-VCC:供电电压-GND:接地   -P0口:P0口是一个8位双向I/O口,当每个引脚第一次被写1时,定义其为高阻态输入,此外P0能够用来作为外部程序数据存储器,为此它可以被定义为数据/地址的第八位,在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此外

10、P0作为数据口时,需外接上拉电阻。-P1口:P1口缓冲器能接收输出4TTL门电流,当P1口管脚写入1后,由于P1口是一个内部提供上拉电阻的8位双向I/O口,所以被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,正是由于内部上拉的缘故,在FLASH编程和校验时,P1口可以作为第八位地址接收;-P2口:P2口也是一个内部具有上拉电阻的8位双向I/O口,P2口缓冲器同样可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入,并因此在作为输入时,P2口的管脚被外部拉低,将输出电流,正是由于内部上拉的缘故,P2口当用于外部程序存储器或16位地址外部数据

11、存储器进行存取时,P2口输出地址的高八位,在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容,P2口在FLASH编程和校验时接收高八位地址信号和控制信号。    -P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流,当P3口写入“1”后,它们被内部上拉为高电平,并用作输入,作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。 此外P3口除了作为一般的I/O口外,更重要的用途是它还有复用功能,如下所示:§P3.0 RXD第二功能可作

12、为串行输入口;§P3.1 TXD第二功能可作为串行输出口;§P3.2 /INT0(外部中断0);§P3.3 /INT1(外部中断1);§P3.6/WR第二功能可作为外部数据寄存器写选通;§P3.7/RD第二功能可作为外部数据寄存器读选通;§P3口同时为闪烁编程和编程校验接受一些控制信号;§RST:复位输入,当振荡器复位时,要保持RST脚两个机器周期的高电平,当STC89C51通电,时钟电路开始工作,在RESET引脚上出现24个时钟周期以上的高电平,系统即初始复位;初始化后,程序计数器PC指向0000H,P0-P3输出口全部为

13、高电平,指针堆栈写入07H,其它专用的寄存器被写“0”,RESET由高转低时,单片机内部即从0000H地址开始执行,但是,初始复位不改变RAM(包括工作寄存器R0-R7)的状态。 表2.1 8051的初始态表 特殊功能寄存器 初始态 特殊功能寄存器 初始态 ACC 00H B 00H PSW 00H SP 07H DPH 00H TH0 00H DPL 00H TL0 00H IP xxx00000B TH1 00H IE 0xx00000B TL1 00H TMOD 00H TCON 00H SCON xxxxxxxxB SBUF 00H P0-P3 1111111B PCON 0xxxxx

14、xxB AALE/PROG:地址锁存允许的输出电平用于锁存地址的地位字节,当访问外部存储器时,在FLASH编程期间,此引脚用于输入编程脉冲;而在平常,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6,因此它可用作对外部输出的脉冲或用于定时目的,然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲,如想禁止ALE的输出可在SFR8EH地址上置0,此时ALE只有在执行MOVX,MOVC指令时ALE才起作用;另外,该引脚被略微拉高,如果微处理器在外部执行状态ALE禁止,置位无效1;-PSEN:外部程序存储器的选通信号,在由外部程序存储器取指期间,每个机器周期两次/PSEN

15、有效,但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现; -EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器,注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器,在FLASH编程期间,此引脚也用于施加12V编程电源(VPP);    -XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入;    -XTAL2:来自反向振荡器的输出;振荡器特性:XTAL1和XTAL2分别为反向放大器的输入和输出,该

16、反向放大器可以配置为片内振荡器,石晶振荡和陶瓷振荡均可采用,如采用外部时钟源驱动器件,XTAL2应不接,有余输入至内部时钟信号要通过一个二分频触发器,因此对外部时钟信号的脉宽无任何要求,但必须保证脉冲的高低电平要求的宽度1。 2.2显示模块设计 本设计显示模块采用不带字库PGLCD12864。2.2.1 PG12864LCD的特性介绍 PG12864LCD是像素可寻址的图形液晶显示屏模块,PG12864LCD特性如下: §工作电压为+5V,可自带驱动LCD所需的负电压; §全屏幕点阵,点阵数为128列*64行,可显示8行*4行个(16*16点阵)汉字,也可完成图像,字符的显

17、示3; §与CPU接口采用5条位控制总线和8位并行数据总线输入输出; §内部有显示数据锁存器,自带EL驱动; §简单的操作指令; §数据口可以采用串行传输与并行传输2.2.2 LCD12864引脚介绍 表2.2 LCD12864引脚管脚号管脚名称管脚功能描述1VSS接地2VDD接电压3V0液晶显示器驱动电压4RSRS=“H”表示DB7-DB0为显示数据;RS=“L”表示DB7-DB0为显示指令数据5R/WR/W=“H”,E=“H”数据被读到DB7-DB0R/W=“L”,E=“HL”数据被写到IR或DR6ER/W=“L”,E信号下降沿锁存DB7DB0R/W

18、=“H”,E=“H”DDRAM数据读到DB7DB07DB0数据线8DB1数据线9DB2数据线10DB3数据线11DB4数据线12DB5数据线13DB6数据线14DB7数据线15CS1H:选择芯片(右半屏)信号16CS2H:选择芯片(左半屏)信号17RET复位低电平有效18VOUT驱动负电压19LED+背光电源20LED-背光接地 通过DB0- DB7数据线和AT89C51IO口连接,对应的管脚必须有效,在显示的时候,要通过列驱动和行驱动来控制液晶屏显示,在驱动时,对应的都有相应的控制器来控制3,由于其显示分为左半屏和右半屏,当CS0为1时,左半屏开显示;CS1为1时,右半屏开显示,12864管

19、脚功能如表2-2所示。2.2.3 12864内部功能器件及相关功能§指令寄存器(IR)指令寄存器是用于寄存指令码,与数据寄存器数据相对应;当D/I=0时,在E信号下降沿的作用下,指令码写入指令寄存器。§数据寄存器(DR)数据寄存器是用于寄存数据的,与指令寄存器寄存指令相对应,当D/I=1时,在下降沿作用下,图形显示数据写入数据寄存器,或在E信号高电平作用下由数据寄存器读到DB0-DB7数据总线,DR和DDRAM之间的数据传输是12864模块内部自动执行的4。§忙标志(BF)BF标志提供内部工作情况,BF=1表示模块内部操作在忙状态,此时模块不接受外部指令和数据;B

20、F=0时,模块为准备状态,随时可接受外部指令和数据,利用STATUS READ指令,可以将BF读到DB7总线,从而检验模块工作状态。§显示控制触发器DFF 此触发器是用于模块屏幕显示开和关状态的控制,DFF=1为开显示(DISPLAY OFF),DDRAM的内容就显示在屏幕上;DFF=0为关显示(DISPLAY OFF),关闭屏幕,DDF的状态是由指令DISPLAY ON/OFF和RST信号控制的。§XY地址计数器 XY地址计数器是一个9位计数器,高3位是X地址计数器,低6位为Y地址计数器,XY地址计数器实际上是作为DDRAM的地址指针,X地址计数器为D

21、DRAM的页指针,Y地址计数器为DDRAM的列地址指针。X地址计数器是没有记数功能的,只能用指令设置;Y地址计数器具有循环记数功能,当数据写进去时,Y的地址数据就会自动加1,Y地址指针可以表示从0-63;§显示数据RAM(DDRAM)DDRAM是存储图形显示数据的。数据为1表示显示选择,数据为0表示显示非选择,DDRAM与地址和显示位置的关系见DDRAM地址表。§Z地址计数器Z地址计数器可以循环记数,共有六位,它是用于显示行扫描,当完成一行扫描,这个计数器的内容就会自动加1,并指向下一行数据扫描,当复位后Z地址计数器自动清0;Z地址计数器可以用DISPLAY START L

22、INE指令预置,所以,就由这条指令控制屏幕显示的起始行,因为DDRAM共64行,因此可以循环滚动显示64行5。各功能指令介绍如下显示开/关指令 R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB00000111111/0DB0为1时,LCD开显示;DB0为0,关闭显示。显示起始行(ROW)设置指令R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB00011显示起始行(063)该指令设置了屏幕最上一行显示RAM的行号,要想实现滚屏显示的效果,可以改变显示起始行设置指令R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB00010111页号

23、(07)4、列地址(Y Address)设置指令R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB00001显示列地址(063)显示RAM的64行可按8行为一页将其分为8页;设置了页地址和列地址,就唯一确定了显示RAM中的一个单元,这样CPU就可以用读、写指令读出该单元中的内容或向该单元写进一个字节的数据。读状态指令R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB010BUSY0ON/OFFREST0000该指令用来查询12864内部控制器的状态,各参量含义如下:BUSY:1-内部在工作,也就是忙状态;0-正常状态ON/OFF:1-显示关闭;0-显示打

24、开RESET:1-复位状态;0-正常状态在BUSY和RESET状态时,除读状态指令外,其它指令均对12864模块内部无效5,除此之外在操作之前要查询BUSY状态,以确定是否可以对12864模块进行操作。写数据指令R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB001写显示数据读数据指令R/WRSDB7 DB6 DB5 DB4 DB3 DB2 DB1 DB011读显示数据 要提醒的是,每次进行读数据之前,都要有一次空读操作,紧接着才会读出想要读的单元中的数据,而且每当完成一次读、写数据指令,内部的列地址就会自动加1, 2.2.4 12864液晶与单片机接口电路 在

25、实际编程时,12864与单片机的连接有并行和串行两种方式可以选择,串行模式占用引脚较少(2个),速度较慢;并行模式占用引脚较多(11个),但传输速度较快,因为一次传8位,速度自然就快,因此我们采用并行传输。12864的数据口DB0-DB7分别接单片机的P1.0-P1.7用来传输数据;控制口RS、RW、EN分别接P3.2、P3.1、P3.0。 顺便在此和大家分享一下调试中遇到的各种问题及如何应对: 一:硬件问题1:这种情况是新手最常碰到的问题,碰到这种情况首先要确定你的接线没有任何问题,如果是51单片机,用P0口一定要加10K的上拉电阻,不然程序正常了也显示不出来。2: 另外要注意第三脚VO的连

26、接方式,这个是对比度电位引脚,实际中常采用10k的可变电阻滑动端连接VO脚,固定端的一段接VCC,另外一端应根据实际硬件连接。如果用的是1602,另一端直接接到GND就可以了,但是对于12864就应该看18脚的标记了,如果写的是NC ,那么另一端直接接地,如果是VEE,那么就应该接到18脚,因为这时的18脚是负压输出端。 根据这点确定你的对比对调节电路接法正确无误。3:关于串并行选择的问题。串并行选择对于有字库的12864适用(1602的四线驱动也可以叫做串行驱动),如果有PSB引脚,那么你的屏应该可以支持串并行了。串并行的选择决定于PSB引脚的电位,一般是低电平为串行模式,高电平为并行模式。

27、有些同志在使用的时候对PSB进行了电位定义但是没有任何显示,这是你应该注意一下LCM板上焊点,尤其是和PSB引脚相连的那些起跳线作用的焊点。因为大多厂家在出厂的时候就预先设置为并行模式,也就是接到高电位上(VCC)。碰到这种情况把焊点跳线重新焊接一下,接到低电位上就可以了。模式选择错误不显示是小问题,由于屏电路的不同,可能你在驱动的时候损坏屏或者单片机,因为选择不对,定义的电位相当于短路。二:软件问题 软件问题一般也就是定义的引脚不对,这种情况出现于真正的初学者,在copy别人的程序或者屏本身的模板程序没有修改引脚的定义,这种情况比较简单,只需要把引脚对应的端口重新定义一下就可以了。三:显示不

28、清楚A:屏上的VO引脚(3脚)电位不对如果你按照上面的说法接了对比度电路,这时你只需要调节电位器的旋钮就可以了,最终可以得到你满意的对比度,使显示最清晰。一般这个脚的电压是 - 6.2V左右,这个电压的显示效果是最好的。B:电源问题很多同学在现成的实验板上做试验,电源取自电脑USB口,这种情况容易出现显示不清楚的情况,原因是供电电流不够,因为电脑的口为500mA供电。碰到此类情况,用外接电源,肯定可以解决。所谓的网上的那些个底层驱动程序,个人觉得没有必要,所谓知其然知其所以然,就是这个道理。 图2-3 12864接口电路引脚号12864引脚STC89C51引脚7-14DB0-DB7P1.0-P

29、1.75WRP3.14RSP3.26CEP3.017RST地表2.3 12864引脚分配 2.3设置模块设置模块采用三个按键与单片机与GND连接按键与单片机的接口电路如图2-4所示。图2-4 按键电路 按键一端与GND连接,另一端与单片机GPIO口连接(相应的引脚接到P3.0, P3.1. P3.3上),当I/O为低电平则按键按下;其中K1:模式选择键(正常计时与调节时间模式)K2:时分秒选择按键K3:调节时/分/秒大小。按键选用触动开关。 2.4 振荡电路图2-5 振荡电路振荡电路选为内部振荡方式。由于所要设计的时间由内部自带的定时器中断和软件计数相结合产生的,故从计算方便以及系统的效率角度

30、出发,设计选用12兆频率的晶振,其电路如图2-5所示。2.5 复位电路单片机采用高电平(I/O口为1时)复位。单片机选用12兆频率晶振,起振为一毫秒,所以两个机器周期的用时为两微秒。单片机单次上电复位所需的最短延时应该大于上电延时与单片机起振延时两者之和。延迟一个时间还太小,不能够促使单片机有一个较好的工作开始7。复位电路使单片机保持在复位状态并且维持一个延时,这样可以给电源电压从上升到稳定的一个等待时间;在电压稳定,再进行一个延时状态,给时钟振荡器由起振到稳定的一个延时;在单片机开始进入运行状态之前,至少推迟2个机器周期的延时间。当单片机RET端为高电平的时单片机复位,主要是复位电路由电阻、

31、电容晶振组成;电容充电的时RST端为高电平,此时单片机开始复位;当该电容电充满,此时单片机完成复位。 初始化i<2i=0 i=0开中断通过K2,K3调节时分秒否是是否图3-1系统图图2-6 复位电路 3系统软件设计 3.1总体软件设计软件设计是较难部分,利用keil软件编写程序,并生成Hex文件,下载到单片机。由于本程序涉及的模块较多,所以编写程序采用模块化设计,C语言具有编写灵活性好、移植方便、便于模块化设计的优点,所以采用如果时为12令是其为0 时加一分=60? 分加一秒=60?继续执行上面的步骤20次中断到没秒加一开相关中断,装初值开定时器,定时模式开始 中断次数计数图3-2 时钟

32、框图C语言给单片机编写程序。框图如图3-1所示。其中K1:模式选择键(正常计时与调节时间模式) K2:用于时/分/秒选择按键K3:用于调节时/分/秒大小按键i:用于统计K1键按下的次数3.2 时钟函数模块时钟定时由单片机内部定时器中断来完成。中断50ms来一次,20次为一秒。因此20次中断秒加一同时秒针转过一格。同理秒满60分加一同时分针转一格。当分满60时加一同时时针走一下6。时钟部分如图3-2所示。 3.3 指针时钟设计 3.3.1 实现功能实现指针时钟的动态显示,并且具有可以在LCD_12864显示器上画点以、画线以及画圆的功能。 3.3.2实现算法LCD_12864模拟时钟画图主要采用

33、Bresenham的算法。Bresenham算法是计算机图形学领域使用最广泛的直线扫描转换方法。Bresenham算法,可以说是DDA算法的简化,两者大致的异同:DDA算法,是某一个长的方向,每一次变化一个单位或者一个单位像素,另外一个方向的变化量可以通过浮点运算和四舍五入计算得到。而Bresenham算法对于下一个点的坐标的取值,则是通过判断一个反复迭代的误差因数是否大于零,而在迭代的计算误差因数的时候,只用到了整型数的加法和移位操作,计算量非常小,是最高效的单步画线算法。由于Bresenham算法仅用到了整形数的加法和移位操作,大大减少了计算机运算量,便于在小型的计算机系统中(例如单片机系

34、统等)实现其功能。也就是这个原因,Bresenham算法的运用更为广泛了。其原理是:通过各行、各列像素中心构造一组虚拟网格线,按直线从起点到终点的顺序计算直线各垂直网格线的交点,然后确定该列像素中与此交点最近的像素。该算法的优点在于可以采用增量计算,使得对于每一列,只要检查一个误差项的符号,就可以确定该列所求的像素。1)画直线LCD画直线,也就是确定直线光栅化后的一系列坐标,在LCD点阵中显示出来,也有人叫直线光栅化。实现这种光栅直线的算法有中点画线法Bresenham算法是DDA算法画线算法的一种改进算法。本质上它也是采取了步进的思想。不过它比DDA算法作了优化,避免了步进时浮点数运算,同时

35、为选取符合直线方程的点提供了一个好思路。首先通过直线的斜率确定了在x方向进行单位步进还是y方向进行单位步进:当斜率k的绝对值|k|<1时,在x方向进行单位步进;当斜率k的绝对值|k|>1时,在y方向进行单位步进。 下面以|k|<1时推导Bresenham算法的数学依据:已知有一直线y = kx+b,|k|<1。我们通过斜率确定了x方向为单位步进。当x = Xm时,y = Ym。那么当x 执行一个单位步进时(即x = Xm+1时),y等于Ym还是等于Ym+1更符合这个直线方程呢?单凭肉眼我们很难得出结论,最好的办法当然是比较Ym和Ym+1和真实的方程的y值的差是多少(即Y

36、real = k*(Xm+1)+b),看看哪一个更靠近真实的方程的y值。我们设 Dupper = Ym+1 - Yreal = Ym+1 - k*(Xm+1)+b); 表示Ym+1和方程真实值的差Ddown = Yreal - Ym = k*(Xm+1)+b)- Ym; 表示Ym和方程真实值的差那就是我们要比较Dupper和Ddown的大小。假设Diff = Dupper - Ddown = (Ym+1 - k*(Xm+1)+b) - (k*(Xm+1)+b)- Ym) 令X 为线段x方向的间距,Y 为线段y方向的间距。Pm = X* Diff = 2*X* Ym-2*Y*

37、 Xm-2*Y-X*(2b-1);那么Pm+1 = Pm+2*X*(Ym+1- Ym)-2*Y;其中Ym+1- Ym取0还是1,取决于Pm的符号。根据等式Diff = Dupper - Ddown = (Ym+1 - k*(Xm+1)+b) - (k*(Xm+1)+b)- Ym)以及k = Y/X,我们可以得出起始像素(x0,y0)的参数p0的值:P0 =X-2*Y;同理我们推出|k|>1的情况,Qm = 2*Xm*Y-2*Ym*X+(2b-2)*X+Y;Qm+1 = Qm+2*(Xm+1-Xm)*Y-2*X;其中Xm+1-Xm等于0还是1,取决于Qm的符号其中第一个参数Q0 = Y-2

38、*X; 明白了数学原理,我们很快能确定算法步骤:1. 输入线段的起点和终点。2. 判断线段的斜率是否存在(即起点和终点的x坐标是否相同),若相同,即斜率不存在,只需计算y方向的单位步进(Y+1次),x方向的坐标保持不变即可绘制直线。3. 计算线段的斜率k,分为下面几种情况处理a. k等于0,即线段平行于x轴,即程序只需计算x方向的单位步进,y方向的值不变b. |k|等于1,即线段的x方向的单位步进和y方向的单位步进一样,皆为1。直接循环X次计算x和y坐标。4. 根据输入的起点和终点的x、y坐标值的大小决定x方向和y方向的单位步进是1还是-16. 画出第一个点。7. 若|k| <

39、1,设m =0,计算P0,如果Pm>0,下一个要绘制的点为(Xm+单位步进,Ym),Pm+1 = Pm -2*Y;否则要绘制的点为(Xm+单位步进,Ym+单位步进)Pm+1 = Pm+2*X-2*Y;8. 重复执行第七步X-1次;9. 若|k| <1,设m =0,计算Q0,如果Qm>0,下一个要绘制的点为(Xm,Ym+单位步进),Pm+1 = Pm -2*X;否则要绘制的点为(Xm+单位步进,Ym+单位步进)Pm+1 = Pm+2*Y-2*X;10. 重复执行第9步Y-1次;2)画圆Bresenham画圆算法又称中点画圆算法,与Bresenham 直线算法一样,其基本的方法是

40、利用判别变量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就可以计算出来。为了简便起见,考虑一个圆心在坐标原点的圆,而且只计算八分圆周上的点,其余圆周上的点利用对称性就可得到。只需要知道了圆上的一个点的坐标 (x, y) ,利用八对称性,我们马上就能得到另外七个对称点的坐标。将圆平均分为8个部分1.只要画出1中1/8圆的圆周,剩下的就可以通过对称关系画出这个圆X变化从0->R那为什么不采用从-R->R呢,Y=+-sqrt(R2-x2);dy/dx=-x/(sqrt(R2-x2) =-x/y所以采用从-R到R,每次横坐标增1,计算量大,而且在(x=+-R,y=0)处

41、,x的很小变化就引起了y的很大变化。 所以不是采用x从-R->R变化。而是采用1/8画圆法。2.在2这1/8圆周上,x值单调增加,y值单调递减,且fabs(dx/dy)=fabs(-x/y)<=1;所以圆周上相应点的y值变化小于1,假设当前点为(x1,y1)这下个点为(x1+1,y1)或(x1+1,y1-1)d1=(x1+1)2+y12-R2;d2=R2-(x1+1)2-(y1-1)2;p=d1-d2 ,若p>0 选点(x1+1,y1-1)否则选点(x1+1,y1)接下来就是求p了,p=2(x1+1)2+2y12-2y1-2R2+1。P1=3-2R(坐标为x=0,y

42、=R)然后仿照线段算法得出p(i+1)=p(i)+4(Xi-Yi)+10(pi>0)否则P(i+1)=p(i)+4Xi+6这样就可以成功画出1/8圆弧了3.接下来的问题,是剩下的部分怎么处理存储器将前1/8的坐标存储起来,然后通过镜像求出其他圆弧坐标,调整顺序输出,即可得到。 3.3.3 函数设计1:实现功能从指定坐标处绘制一个点或擦除一个点2:实现依据通过LCD_set_XY确定坐标,然后根据擦除还是绘制再确定点在坐标的位置,再判断是擦除还是绘制,最后使用LCD_write_byte函数写入数据。图3.3为流程图。定位XY坐标向LCD绘/擦出点开始结束 图3-3 擦/绘点 确定线段两端

43、点的坐标关系沿两间的轨迹绘点或擦点开始结束图3-4 绘直线框图 2: void Line(uchar x1,uchar y1,uchar x2,uchar y2,bit Mode)第 13 页 共 26 页(1)实现功能在LCD_12864上绘制一条线段(2)实现依据利用两点式(直线方程)在直线点的轨迹上绘制/擦除点以完成绘线。(3)具体流程图如图3-4所示。 3:void Clock_Plate()(1)实现功能绘制一个指针式模拟时钟的圆盘。(2)实现依据利用圆的轨迹方程找到点的坐标,再根据点的坐标绘制图形。(3) 流程图图3-5所示。确定圆心坐标及其半径长度沿圆的轨迹进行绘点开始结束 图3

44、-5 绘制指针圆盘框图重绘秒针重绘分针开始结束重绘时针图3-7 重新绘制指针判断重新绘哪一条指针擦除指针上一秒状态开始结束图3-6 绘制指针框图 图3-8 随时间绘制指针绘制时针表盘开始读取时间根据时间绘制时分秒针结束4:void Repaint_A_Hand(uchar i)(1) 实现功能根据当前时间绘制对应的指针,并擦除上次显示的指针(2) 实现依据利用圆的弧度与时间的对应关系,由于圆的弧度随时间而变化,据此从圆心到圆弧对应时间的位置画出直线就是指针。(3) 绘制指针框图如图3-6所示。 5:void Display_HMS_Hand()第 15 页 共 26 页(1)实现功能重新绘制模

45、拟的秒针、分针、时针。 (2)实现依据调用Repaint_A_Hand函数设置当前参 数,据此绘制当前时间对应的指针。(3)重新绘制指针如图3-7所示。第 1 页 共 26 页 6:void Display_ClockZhizhen()(1)实现功能读取时间绘制指针时钟到LCD_12864上 (2)实现依据读取时间,由于指针随时间而变化,绘制的模拟指针时钟,另外判断调节按键的键值是否为退出键的键值,若是则返回菜单界面。 (3)流程图如图3-8所示。 3.4 显示函数模块通过LCD_Check_Busy()检测LCD是否忙碌,通过LCD_Write_Command向LCD发送写命令,通过void

46、 LCD_Write_Data向lcd发送写数据命令,通过LCD_Initialize初始化12864显示屏。由于用的LCD_12864是自带字库的,故可以直接显示字符和汉字,同时根据液晶显示屏的要求对应圆盘的大小都是可以规定的。1) lcd_12864写命令函数void writecmd(uchar cmd)/ LCD_12864液晶写命令 while(readstatus() & 0x80)!= 0x00); /LCD_12864液晶显示读状态 LCDDATA=0x00; RW=0; RS=0; EN=0; LCDDATA=cmd; delay(2); EN=1; delay(3)

47、; EN=0;2) lcd_12864写数据函数void writedate(uchar date) /LCD_12864液晶写数据 while(readstatus() &0x80 )!=0x00); LCDDATA=0x00; RW=0; RS=1; EN=0; LCDDATA=date; delay(2); EN=1; delay(3); EN=0;3) LCD_12864液晶显示读状态函数uchar readstatus()/LCD_12864液晶显示读状态 uchar i; LCDDATA=0xff; RW=1; RS=0; EN=0; delay(2); EN=1; del

48、ay(3); i=LCDDATA; delay(3); EN=0; return(i);4) LCD_12864液晶读数据函数uchar readdate()/LCD_12864液晶读数据 uchar i; while(readstatus() &0x80 )!=0x00); RW=1; RS=1; EN=0; delay(2); EN=1; delay(3); i=LCDDATA; delay(3); EN=0; return i; 5) LCD_12864液晶初始化函数void LCD_init()/ LCD_12864液晶初始化 writecmd(0x30); delayms(1

49、); writecmd(0x30); delayms(1); writecmd(0x0c); delayms(1); writecmd(0x01); delayms(1); writecmd(0x06); delayms(1);3.4.1实现功能通过LCD_12864显示指针式电子时钟。3.4.2 函数设计1:uchar LCD_Write_Command_P2(uchar cmd,uchar para1,uchar para2)(1)实现功能写双参函数(2)实现依据状态位char Status_BIT_01():用于判断是读/写指令还是读/写数据2:uchar LCD_Write_Comma

50、nd_P1(uchar cmd,uchar para1)(1)实现功能写单参数函数(2)实现依据通过态位char Status_BIT_01(),判断是读/写指令还是读/写数据3:uchar LCD_Write_Command(uchar cmd)(1)实现功能写无参数函数(2)实现依据状态位char Status_BIT_01():用于判断是读/写指令还是读/写数据4:uchar LCD_Write_Data(uchar dat)(1)实现功能写数据(2)实现依据通过判断状态位char Status_BIT_03(),数据是否为自动写状态5:void Set_LCD_POS(uchar ro

51、w,uchar col)reentrant(1)实现功能设置当前显示地址(2)实现依据通过调用写双参数函数,使LCD完成准备工作。6:void cls()(1)实现功能清屏(2)实现依据先调用双参数、无参数函数来配置地址指针,再判断状态位Status_BIT_3(),来判断是否要进行写数据,然后调用写数据(LCD_Write_Data())函数,当向LCD写好数据,再调用无参函数来完成自动写结束,最后在重置地址指针5。(3)流程图,如图3.9所示。设置正常显示模式置ROM为0000将RAM中写满0X00开始结束图3.9 设置当前地址7:char LCD_Initialise()(1)实现功能L

52、CD的初始化(2)实现依据通过双参数LCD_Write_Command_P2来在LCD上显示区首地址,文本区显示区宽度,图形显示区首地址,图形显示区宽度,通过LCD_Write_Command_P1()(写单参数函数)及无参函数实现光标形状,及显示方式设置。3.5中断服务函数模块通过单片机内部定时器定时50毫秒,中断20次为一毫秒。此时秒针加1,当满60,分加一;当分满60时加一;由于采用12进制计时,故时满12则清零。 3.5.1 功能 时分秒计时功能 3.5.2 函数void exter0() interrupt 1 /中断服务函数 TH0=(65536-50000)/256;/定时器装载初值约为50ms TL0=(65536-50000)%256; tt+

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论