原创 电子台历(PIC16F877)

2008-6-7 23:13 3546 6 7 分类: MCU/ 嵌入式

1 电子台历概述


   随着电子科技的不断发展,传统的挂历已被一些高档的电子台历所取代,与传统的挂历相比,电子台历融合了挂历和时钟的优点,能昼夜清晰显示,集年、月、日、时、分、秒、日期于一体,外观新颖,造型别具一格。除此之外由于挂历制作成本相对较高,挂历的销售价格也大多在15——30元之间,而一个电子台历的价格也在这之间,但是挂历只能用一年,而电子台历则不一样,由于它可以自动识别闰年、公历、农历、大小月份、农历,星期能自动对应公历无须调整。但考虑到其寿命原因,至少也可用58年。在价格相差不大的情况下,电子台历的性价比显然要高的多,就其阅读功能而言,电子台历阅读起来更加方便,这比传统的挂历要强大的多。其实现的方法也很简单,用一个单片机,DS1302实时时钟芯片和LCD液晶显示器就可以实现,由此可见,电子台历的市场经济开发价值要比挂历要高的多,电子台历取代传统的挂历已成为不可抵挡的趋势。


2设计任务


2.1基本要求


(1)                利用DS1302时钟芯片与PIC16F877单片机通信获取时间,并由显示器来显示;


(2)                具有调整时间功能:由键盘来实现,可对年,月,日,星期,小时,分,秒进行调整。


2.2扩展部分


(3)                显示器采用LCD 16*2显示器;


(4)                键盘采用4*4键盘。


3 系统主要功能


3.1时钟功能


对于时钟功能,需要在LCD显示器显示年,月,日,星期,小时,分钟和秒钟,因此,可以在内部存储空间分别定义它们的显示缓存空间,来存放年,月,日,星期,小时,分钟和秒钟的BCD码,各2个字节。


由于时钟是不能停止的,因此需要采用外部记数器DS1302自动计时,并与单片机SPI通信来获取时间,存储在单片机内部存储空间,再使用程序来不断进行时间数值的刷新。最后由单片机与LCD显示器进行并行通信在显示器上显示。


    3.2功能按键


若需调整时间,可采用4*4键盘对时间进行调整,每按键一次则相应调整年,月,日,星期,小时,分钟,秒,调整后的时间信息存储到单片机内部存储单元,然后再由单片机与DS1302通信对时钟芯片内部时间信息从新载入,最后再由单片机获取信息用LCD显示器显示。


第二节:理论分析及方案选择


1:实时时钟芯片的选择


  方案1: 实时时钟可以由单片机内部资源来控制;


方案2:  实时时钟由外围模块(如时钟芯片)来获取。


   两者都有优点,单片机内部资源的制作可以充分利用单片机内部资源,节省开支;外围模块,如时钟芯片,具有精确产生实时时钟,数据线连接简单,运用灵活方便,集成度高,价格便宜。


但由单片机内部资源制作的时钟准确度受限,而实时时钟芯片时间准确。DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。引脚少,与单片机联接简易,控制简易有自己内部的控制芯片。所以系统选择时钟芯片。


2:时钟芯片的介绍


DS1302是美国DALLAS公司推出的一种高性能、低功耗的实时时钟芯片,附加31字节静态RAM,采用SPI三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号和RAM数据。实时时钟可提供秒、分、时、日、星期、月和年,一个月小与31天时可以自动调整,且具有闰年补偿功能。工作电压宽达2.55.5V。采用双电源供电(主电源和备用电源),可设置备用电源充电方式,提供了对后背电源进行涓细电流充电的能力。DS1302的外部引脚分配如1所示及内部结构如2所示DS1302用于数据记录,特别是对某些具有特殊意义的数据点的记录上,能实现数据与出现该数据的时间同时记录,因此广泛应用于测量系统中。


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1028">


1   DS1302的外部引脚分配


 


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1029">


2   DS1302的内部结构


 


各引脚的功能为:


       Vcc1:主电源;Vcc2:备份电源。当Vcc2>Vcc1+0.2V时,由Vcc2DS1302供电,当Vcc2< Vcc1时,由Vcc1DS1302供电。


       SCLK:串行时钟,输入; 


       I/O:三线接口时的双向数据线;


       CE:输入信号,在读、写数据期间,必须为高。该引脚有两个功能:第一,CE开始控制字访问移位寄存器的控制逻辑;其次,CE提供结束单字节或多字节数据传输的方法。


    DS1302有下列几组寄存器:


DS1302有关日历、时间的寄存器共有12个,其中有7个寄存器(读时81h8Dh,写时80h8Ch),存放的数据格式为BCD码形式,如3所示。


 



3   DS1302有关日历、时间的寄存器


   小时寄存器(85h84h)的位7用于定义DS1302是运行于12小时模式还是24小时模式。当为高时,选择12小时模式。在12小时模式时,位5是,当为1时,表示PM。在24小时模式时,位5是第二个10小时位。


    秒寄存器(81h80h)的位7定义为时钟暂停标志(CH)。当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态;当该位置为0时,时钟开始运行。


控制寄存器(8Fh8Eh)的位7是写保护位(WP),其它7位均置为0。在任何的对时钟和RAM的写操作之前,WP位必须为0。当WP位为1时,写保护位防止对任一寄存器的写操作。


DS1302有关RAM的地址


    DS1302中附加31字节静态RAM的地址如图4所示。


 


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1031">


4


DS1302的工作模式寄存器


所谓突发模式是指一次传送多个字节的时钟信号和RAM数据。突发模式寄存器如图5所示。


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1032">


5


此外,DS1302还有充电寄存器等。


 


2 读写时序说明


DS1302SPI总线驱动方式。它不仅要向寄存器写入控制字,还需要读取相应寄存器的数据。


       要想与DS1302通信,首先要先了解DS1302的控制字。DS1302的控制字如6



6   控制字(即地址及命令字节)


 


控制字的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入到DS1302中。


6:如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;


5至位1A4A0):指示操作单元的地址;


0(最低有效位):如为0,表示要进行写操作,为1表示进行读操作。


控制字总是从最低位开始输出。在控制字指令输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从最低位(0位)开始。同样,在紧跟8位的控制字指令后的下一个SCLK脉冲的下降沿,读出DS1302的数据,读出的数据也是从最低位到最高位。数据读写时序如7



7   数据读写时序 


3 电路原理图:


电路原理图如图8DS1302与单片机的连接也仅需要3条线:CE引脚、SCLK串行时钟引脚、I/O串行数据引脚,Vcc2为备用电源,外接32.768kHz晶振,为芯片提供计时脉冲。


 


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1035">


8 此图为PIC16F877单片机与DS1302连接图


 


3  显示器的选择


       LED显示器不仅不直观,不能显示复杂的字母,而且模块占面大,做PCB板受到面积束缚,集成度小;而LCD显示器16*2类型的直观,字符型点阵式LCD模块能显示许多字母,占面小集成度大,功能强大。


4            LCD显示器的介绍


  我们所说的LCD为字符型点阵式LCD模块(liquid Crystal Display Module)简称LCM,或者是字符型LCD。字符型液晶显示模块是一类专门用于显示字母,数字,符号等的点阵式液晶显示模块。在显示器件上的电极图型设计,它是由若干个5*75*11等点阵符位组成。每一个点阵字符位都可以显示一个字符。点阵字符位之间有一空点距的间隔起到了字符间距和行距的作用。目前市面上常用的有16*1行,16*2行,20*2行和40*2行等的字符模块组。这些LCM虽然显示字数各不相同,但是都具有相同的 输入输出界面。我将以WINTECH 16*2字符型液晶显示模块WM-C1602N为例,详细介绍字符型液晶显示模块的应用技术。


9所示为16*2地的外观,表11LCM的接脚及功能。


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1036">0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1037">


   9:液晶显示模块WM-C1602N



10:液晶显示模块WM-C1602N规格


 



编号


符号


引脚说明


编号


符号


Data I/O


1


VSS


电源地


9


D2


Data I/O


2


VDD


电源正极


10


D3


Data I/O


3


VL


液晶显示偏压信号


11


D4


Data I/O


4


RS


数据/命令选择端(H/L


12


D5


Data I/O


5


 R/W


/写选择端


13


D6


Data I/O


6


E


使能信号


14


D7


Data I/O


7


D0


Data I/O


15


BLA


背光源正极


8


D1


Data I/O


16


BLK


背光源负极


 


           11:液晶显示模块WM-C1602N的接脚及功能


LCD的内部结构


液晶显示模块WM-C1602N的内部结构可以分成三部份:一为LCD控制器,二为LCD驱动器,三为LCD显示装置,如图示12所示:


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1039">


12LCM内部方块图


目前大多数的LCD液晶显示器的控制器都有采用一颗型号为HD44780的集成电路作控制器。HD44780是集控制器,驱动器于一体,专用于字符显示控制驱动集成电路。HD44780是字符型液晶显示控制器的代表电路。


HD44780集成电路的特点如下


1):HD44780不仅作为控制器而且还具有驱动40*16点阵液晶像素的能力,并且HD44780的驱动能力可通过外接驱动器扩展360列驱动。


2):HD44780的显示缓冲区及用户自定义的字符发生器CGRAM全部内藏在芯片内。


3):HD44780具有适用于M6800系列MPU的接口,并且接口数据传输可为8位数据和4位数据传输两种方式。


4):HD44780具有简单而功能较强的指令集,可实现字符移动,闪烁等显示功能。


如表13所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个HD44780内藏的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,固定的代码。比如数字“1”的代码是00110001B31H),又如大写的英文字母“A”的代码是01000001B41H)。



13:液晶显示模块WM-C1602NCGRAM字符图形代码对应表


液晶显示模块WM-C1602N在显示“a”时,则我们只需将ASCII61H存入DDRAM即可。显示时模块把地址31H中的点阵字符图形显示出来,我们就能看到字母“a”


DDRAM80bytes空间,共可显示80个字,地址与实际显示位置的排列顺序跟LCD的型号有关,液晶显示模块WM-C1602N的显示地址如图14所示。0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1041">


14:地址映射图


5     LCD的控制器指令


字符LCD的指令共有11条,如表15所示已有详细功能和用法:


15LCD的指令(注:表中的*号表示可以为10



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


1


光标


归位


0


0


1


0


0


0


0


0


0


1


*


 


 


1.64us



 



1;光标归位,即光标回到显示器的左上方


2:将地址计数器AC的植设为0


3DDRAM的内容不变


 


 



 


指令


序号


 


指令


动作


      


 


执行


时间     


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


2


进入模式设定


0


0


0


0


0


0


0


0


0


I/D


S


40us


 


 



 


 


 



 


 


设定每写入1byte治资料后,光标的移动方向,及设定每写入一个字符是否移动,根据I/DS两个未元的变化情况如下表所示。


 


I/D


S


        


0


0


光标左移一格而且AC的植减1


0


1


显示器的字符全部右移一格,但光标不动。


1


0


光标右移一格而且AC的植加1


1


1


显示器的字符全部左移一格,但光标不动。


 



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


 


3


显示器的


开关控制


0


0


0


0


0


0


0


0


D


C


B


 


 


40us



 



1;控制显示器的开关,D=1显示9D即(Display0 ) D="0"不显示,


2:控制光标开关,C=1显示光标(CCursor ) C="0"不显示


3:决定光标是否闪烁,B=1光标闪烁B=0时 光标不闪烁


 



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


4


功能设定


0


0


0


0


0


0


0


0


D


C


B


 


 


40us



 



1;设定资料的长度,DL=1 8元位( DB7-DB0DL=0 4元位( DB7-DB0


2:设定显示的行度,N=12行度( DB7-DB0N=0 1行显示


3:设定字符型的规格,F=1  5*10字型   F=0 5*7 字型


 



 


指令


序号


 


指令


动作


      


 


执行


时间     


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


5


光标移位方向


0


0


0


0


0


0


0


S/C


R/L


*


*


40us


 


 



 


 


 



 


 


令光标移位或令整个显示字符移位。根据S/CR/L 两位元的变化情况如下表所示:


S/C


 R/L


      


0


0


令光标左移一格,而且AC的植减1


0


1


令光标右移一格,且AC的植加1


1


0


显示器的字符全部左移一格,但光标不动。


1


1


显示器的字符全部右移一格,但光标不动。


 



 


指令


序号


 


指令动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


6


读忙


0


1


1


BF AC的内容7元位(AC0-AC6    


 


 


0 us



 



1:读取忙信号BF的内容,BF=1忙碌中,无法接受单片机送来的资料,BF=0可接受MPU送来的资料。


2:读取地址计数器AC的内容。


 



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


7


CGRAM地址设定


0


0


1


0


1


  CGRAM地址    


40us




设定下一个要存入资料的CGRAM地址


 



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


 


8


DDRAM地址


设定


 


 


 


1


DDRAM地址           


 


40us




设定下一个要存入资料的DDRAM地址


 



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


9


清屏


1


0


1


要写到LCM的资料D7- 8元位)        


 


 


40us



 



1:将字符码写入DDRAM以使让LCD显示相应的图形。


2:将使用者自创的图形存入CGRAM


 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


10


CRAMHUDDRAM读取资料


1


1


1


读出资料D7-D0 8元位


 


 


40us



 



 


读取RAMHUDDRAM的内容


 



 


指令


序号


 


指令


动作


      


 


执行


时间


RS


R/W


E


DB7


DB6


DB5


DB4


DB3


DB2


DB1


DB0


11


清屏


0


0


1


0


0


0


0


0


0


0


1


 


 


1.64us



 



1:清除显示器,即将DDRAM的内容全部写入空白ASCIIM20H


2:光标归位,即光标回到显示器的左上方。


3:将地址计数器AC的植设为0


第三节:系统开发软件环境


 1    系统开发工具介绍与安装


1.1 PIC系列单片机开发工具MPLAB的组成


MPLAB是一个集成了多种单片机应用开发工具软件于一体的、功能完备的软件包,是PIC单片机编程开发的重要工具。在此仅对其中的5种工具软件简要介绍如下:


⑴ Project Manager(工程项目管理器)


工程项目管理器是MPLAB的核心部分,用于创建和管理工程项目,为开发人员提供自动化程度高、操作简便的符号化(屏幕上的指令、指令地址、常数、变量、寄存器等均用表义性和可读性很强的符号代表和标识)调试工作平台。


⑵ MPLAB Editor(源程序编辑器)


源程序编辑器是一个全屏幕文本编辑器,用于创建和修改汇编语言源程序文件。源程序文件以纯文本格式保存,其文件扩展名为“.asm”。


⑶ MPASM Assembler(汇编器)


用于将汇编语言源程序文件(.asm)汇编成机器语言目标程序文件(.hex),并负责查找语法错误和格式错误等一些浅层次简单错误。


⑷ MPLAB-SIM Software Simulator(软件模拟器)


软件模拟器是一种代替价格较贵的Hardware Emulstor(硬件仿真器)的调试工具,也是一种非实时、非在线的纯软件的调试工具。借助这个在微机系统上运行的工具软件,我们可以不需要任何额外的附加硬件,仅用软件的手段,来模仿PIC系列单片机的指令的执行和信号的输入/输出,从而实现对用户自编单片机源程序的模拟运行、功能调试和深层次逻辑错误查找。因此可以说,这为学习和应用PIC系列单片机的人们提供一种虚拟的实战环境。对于单片机初学者来说,不用花钱也可以实现边学边练的梦想;对单片机开发者来说,可以缩短开发周期和降低成本。总之,它是一种许多其他型号系列单片机很少配备的、性能价格比较高的程序调试工具。不过,它也存在一定的局限性:一是它还不能模拟PIC<?xml:namespace prefix = st1 />16F87X片内少数功能特殊的外围模块;二是它不能帮我们查找目标板上的电路错误;三是它执行速度慢而只能适合调试那些实时性要求不高的程序。


MPLAB-ICD Debugger(在线调试工具ICD的支持程序)


这是一种专门与ICD配合使用的支持程序。ICDMicrochip公司专为PIC16F87X设计的一种廉价的在线调试工具套件。


另外,还包含一些其他工具软件。例如:程序模块连接器、库程序管理器、C语言编译器、硬件在线仿真器的支持程序、目标程序烧录器的支持程序、在DOS操作系统下运行的汇编器等等。


1.2   MPLAB的安装


为了使MPLAB能够顺利安装和可靠地运行,对于所用的微机系统有一个起码地要求。既安装和运行MPLAB所需的最小计算机配置为:


CPUIntel486或型号更先进的处理器;


操作系统为Microsoft Windows3.XWindows95/98;显示器为VGA(建议使用SVGA);内存容量应不小于8MB(建议32MB);可利用的硬盘空间不小于20MB                                            ﹡配有鼠标。


下面我们介绍在Windows98操作系统之下,安装MPLAB的过程。


首先将Microchip公司提供的光盘放入光驱内,点击“我的电脑”会出现光盘的标志符0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1042"> ,右击此标志符一次,再点击“打开”,找到了文件夹“tools”,右击此文件夹,点击打开,找到“download”的文件夹,右击打开此文件夹,找到mplab-ide的文件夹,同样右击打开此文件夹,会出现MPLV5XX的文件夹,再打开这个MPLV5XX的文件夹,就出现了Mp57full的安装文件,打开文件就进入了如图16的安装对话框。


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1043">


16进入MPLAB安装的对话框


    点击Next两次,进入了如图17所示的对话框,用鼠标点击去掉一些暂时用不到的程序左边的钩号。点击两次“Next”,就出现了图18的对话框,在这里点击“Browse”键即可选择你想安装MPLAB的地方,选择好后就点击“Next”,直到出现图19的准备好安装MPLAB的对话框,点击“Next”就开始安装了。


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1044">                17MPLAB组件选择对话框


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1045">


                  18选择安装MPLAB的路径


                                                                                         0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1046">


               19 准备好安装MPLAB的对话框


安装完成后,MPLAB会自动在Windows98“开始”按钮的“程序”组中,建立一个“Microchip MPLAB”程序组。至此MPLAB的系统文件已经安装完毕。用户可在硬盘驱动器C:﹨Program FilesMplab目录下,建立一个新的子目录Work作为我们的工作目录,存放我们在学习和操作过程中产生的各种文件。


如果日后不打算使用MPLAB,想清除其占用的硬盘空间,MPLAB自带了卸载程序C:﹨Program FilesMplabunwise32.exe,运行它即可将MPLAB全部彻底地自动删除干净。


1.3 MPLAB-ICD在线调试工具套件及其应用


MPLAB-ICDMicrochip公司针对其PIC系列单片机中,近期推出的具有片内FLASH程序存储器的PIC16F87X系列单片机,所研制的一套廉价的学习和开发工具套件。MPLAB-ICD可以用于实验阶段的评估和辅助调试。它既是一个编程器(即程序烧写器),又是一个实时在线调试器。用它可以代替在单片机应用项目的开发过程中常用的两种工具——硬件在线实时仿真器和程序烧写器。它利用了PIC16F87X片内集成的在线调试器(in-circuit debugger)能力和Microchip公司的在线串行编程技术(in-circuit serial programming)。MPLAB-ICD工作于MPLAB集成开发环境软件包之下,其仿真头直接连接到目标电路板上,如同将一片PIC16F87X插入到目标板内一样去运行用户编制的程序。


MPLAB-ICD套件中包括的部件有:MPLAB-ICD仿真头;MPLAB-ICD模块;及MPLAB-ICD演示板;RS-232串行通信电缆;连接插针:214脚插针和220脚插针;20cm长的6芯电缆;包含所有MPLAB软件包和文档资料的光盘;《MPLAB-ICD用户指南》的中文翻译版本;还有直流电源适配器。那么它的功能特点则有:


能以实时或单步方式运行用户程序;


断点设置功能;


在线调试功能;


在线编程功能;


工作电压范围为3.05.5 V;


可从目标板上获取工作电源;


工作频率范围为32kHz20kHz


可对源程序直接进行代码级的调试;


可以工作于MPLAB集成开发环境下;


RS-232串行接口方式与微机系统相连。


 


借助于MPLAB-ICD工具套件,用户可以实现:


在自己设计的PIC16F87X的应用电路中实时运行和调试自己的源程序——软件调试。


用自己编制的程序来调试和检验自制目标板上的电路——硬件调试;


利用在线串行编程技术将自己设计的目标程序烧写到插在目标板上的PIC16F87X单片机(又称目标单片机)中——程序固化。


对于这套小巧廉价的、电路简洁的MPLAB-ICD的开发工具套件,由于在实现在线调试和在线编程的过程中,采用了PIC16F87X集成在片内的在线调试功能和Microchip公司的在线串行编程协议,因此在用MPLAB-ICD仿真目标单片机时一定会存在一定的局限性。具体地说,MPLAB-ICD工作过程中将会占用目标单片机的片内和引脚中的部分资源。这部分资源用户就不能再使用了。不过,对于一般的项目开发没有太大的影响,并且与价格昂贵的专业级全功能在线实时仿真器相比,用它来调试和烧写PIC16F87X系列单片机,仍然是一套具有极高性能价格比的开发工具套件,所以它非常适合初级开发者的学习和实践。我们通过使用此套工具就可以很好的进行单片机的应用。                                                                                                                 


1.4     PROTEL 99SE 简介


1)随着计算机业的发展,从80年代中期计算机应用进入各个领域。在这种背景下,8788年由美国ACCEL Technologies Inc推出了第一个应用于电子线路设计软件包——TANGO,这个软件包开创了电子设计自动化(EDA)的先河。这个软件包现在看来比较简陋,但在当时给电子线路设计带来了设计方法和方式的革命,人们纷纷开始用计算机来设计电子线路,直到今天在国内许多科研单位还在使用这个软件包。 
  随着电子业的飞速发展,TANGO日益显示出其不适应时代发展需要的弱点。为了适应科学技术的发展,Protel Technology公司以其强大的研发能力推出了Protel For Dos作为TANGO的升级版本,从此Protel这个名字在业内日益响亮。
  八十年代末,Windows系统开始日益流行,许多应用软件也纷纷开始支持Windows操作系统。 Protel也不例外,相继推出了Protel For Windows 1.0Protel For Windows1.5等版本。这些版本的可视化功能给用户设计电子线路带来了很大的方便,设计者再也不用记一些繁琐的命令,也让用户体会到资源共享的乐趣。
  九十年代中,Win95开始出现,Protel也紧跟潮流,推出了基于Win953.X版本。3.X版本的Protel加入了新颖的主从式结构,但在自动布线方面却没有什么出众的表现。另外由于3.X版本的Protel16位和32位的混合型软件不太稳定。
  98年,Prote公司推出了给人全新感觉的Proel98Protel98以其出众的自动布线能力获得了业内人士的一直好评。
  99年,Protel公司又推出了最新一代的电子线路设计系统——Protel99。在Protel99中加入了许多全新的特色。
       2 Protel99组成
a.
原理图设计系统
  原理图设计系统是用于原理图设计的Advanced Schematic系统。这部分包括用于设计原理图的原理图编辑器Sch以及用于修改、生成零件的零件库编辑器SchLib
b.
印刷电路板设计系统
  印刷电路板设计系统是用于电路板设计的Advanced PCB。这部分包括用于设计电路板的电路板编辑器PCB以及用于修改、生成零件封装的零件封装编辑器PCBLib
c.
信号模拟仿真系统
  信号模拟仿真系统是用于原理图上进行信号模拟仿真的SPICE 3f5系统。
d.
可编程逻辑设计系统 Protel99内置编辑器
  可编程逻辑设计系统是基于CUPL的集成于原理图设计系统的PLD设计系统。这部分包括用于显示、编辑文本的文本编辑器Text和用于显示、编辑电子表格的电子表格编辑器Spread
     3 Protel99主要特色
   Protel99是基于Win95/Win NT/Win98/Win2000的纯32位电路设计制版系统。Protel99提供了一个集成的设计环境,包括了原理图设计和PCB布线工具,集成的设计文档管理,支持通过网络进行工作组协同设计功能。


4Protel99的主要特性如下:
   Protel99系统针对Windows NT4/9X作了纯32位代码优化,使得Protel99设计系统运行稳定而且高效。
   SmartTool(智能工具)技术将所有的设计工具集成在单一的设计环境中。
   SmartDoc(智能文档)技术将所有的设计数据文件储存在单一的设计数据库中,用设计管理器来统一管理。设计数据库以.ddb为后缀方式,在设计管理器中统一管理。 使用设计管理器统一管理的文档是在Protel99中新提出来的,以前版本中没有。
   SmartTeam(智能工作组)技术能让多个设计者通过网络安全地对同一设计进行单独设计,再通过工作组管理功能将各个部分集成到设计管理器中。 
   PCB自动布线规则条件的复合选项极大的方便了布线规则的设计。
   用在线规则检查功能支持集成的规则驱动PCB布线。
   继承的PCB自动布线系统最新的使用了人工智能技术,如人工神经网络、模糊专家系统、模糊理论和模糊神经网络等技术,即使对于很复杂的电路板其布线结果也能达到专家级的水平。
   对印刷电路板设计时的自动布局采用两种不同的布局方式,即Cluster Placer(组群式)和基于统计方式(Statistical Placer)。 在以前版本中只提供了基于统计方式的布局。
   Protel99新增加了自动布局规则设计功能,Placement标签页是在Protel99中新增加的,用来设置自动布局规则。
   增强的交互式布局和布线模式,包括“Push-and-shove”(推挤)。
   电路板信号完整性规则设计和检查功能可以检测出潜在的阻抗匹配、信号传播延时和信号过载等问题。Signal Integrity标签页也是在Protel99中新增加的,用来进行信号完整性的有关规则设计。
   零件封装类生成器的引入改进了零件封装的管理功能。
   广泛的集成向导功能引导设计人员完成复杂的工作。
   原理图到印刷电路板的更新功能加强了SchPCB之间的联系。
   完全支持制版输出和电路板数控加工代码文件生成。
   可以通过Protel Library Development Center升级广泛的器件库。
   可以用标准或者用户自定义模板来生成新的原理图文件。
   集成的原理图设计系统收集了超过60000元器件。
   通过完整的SPICE 3f5仿真系统可以在原理图中直接进行信号仿真。
   可以选择超过60中工业标准计算机电路板布线模板或者用户可以自己生成一个电路板模板。
   Protel99开放的文档功能使得用户通过API调用方式进行三次开发。
   集成的(Macro)宏编程功能支持使用Client Basic编程语言。


1.5   其他所用外围模块、电路及器件的简要介绍


DS1302时钟芯片与32768HZ晶振,单片机使用4 MHZ晶振,4*4键盘采用行列连接法。


第四节:系统结构及功能的实现


1 系统的基本结构及原理图


电子台历是用于获取时间并显示时间的系统,时间的值是不断变化的。所以它最起码的结构应有时钟芯片、显示器、单片机以及一些外部电路所需元件。这里的时间计数器我们用DS1302时钟芯片,PIC16F877兼作信号输入输出控制器及时间信息存储器和程序存储器,显示器用液晶显示模块WM-C1602NLCD


LCD电路图如下:



16LCD连接电路图


PIC16F877单片机电路图如下:


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1048">


               17PIC16f877单片机电路图



19    4*4键盘图


 


时钟芯片DS1302电路图如下:


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1050">


       20  时钟芯片DS1302原理图


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_i1051">


           21  DS1302与单片机连接图


  


2    系统功能的实现


  


                                  22  系统概图


1.1       时钟芯片DS1302与单片机SPI同步通信设计流程及源程序


          1) 说明:本方案通信方式为采用单字节传送通信


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_s1067">    


                                                                                                                                                        


 


           23   时钟芯片DS1302与单片机SPI同步通信设计流程


         2) 单字节写入DS1302程序


void write_ds1302_byte(uchar temp)      //写入字节“temp”的内容


{


 


  uchar i;


  for(i=0;i<8;i++)                      //单个BIT依次写入


     {


        sck = 0;


      io=(bit)(temp&0x01);              //判断信息是‘1’或‘0


      sck=1;                            //开串行时钟


      temp >>=1;                        //字节向右移动一个BIT


          


      }


}


void write_ds1302(uchar address,uchar dat)//写入时间地址的数据


{  


  ce=0;


  sck=0;


  ce=1;                                 //开启复位


  write_ds1302_byte(address);          //写入地址


  write_ds1302_byte(dat);              //写入数据


  ce=0;                                 //关闭复位


}


       3)单字节接受程序


unsigned char read_ds1302(uchar address)//address”是要接收时间信息地址


{


       uchar i,temp=0x00,dat1,dat2;


       ce=0;          


       sck=0;            


       ce=1; 


       write_ds1302_byte(address);


       TRISA = 0x01;                    // IO端口设为输入方向


       for(i=0;i<8;i++)                 //接受字节


       {


        


         if( io )                       //判断接收BIT是‘0’或‘1


          temp|=0x80;                   //若‘0’向右移动一位,接受字


         sck = 1;                       //节的最高位为‘0’,若‘1’则


     temp>>=1;                          //接受的字节向右移动一位,最高


     sck=0;                             //位为‘1


       }    


      ce=0;


     TRISA =0x00;                       //关闭IO接收端口


       dat1=temp;                       //将接收的BCD码转换为十进制


       dat2=dat1/16;                


       dat1=dat1%16;                  


       dat1=dat1+dat2*10;


       return (dat1);                   //将数据返回


}


(5)                DS1302初始化程序


void set(void)                    //分别写入DS1302内部时间地址的


{                                 //数据


 uchar i,j;


 j=0x80;


       write_ds1302(j,second);


        j=j+2;


       write_ds1302(j,minute);


        j=j+2;


       write_ds1302(j,hour);


        j=j+2;


       write_ds1302(j,day);


        j=j+2;


       write_ds1302(j,month);


        j=j+2;


       write_ds1302(j,xinqi);


        j=j+2;


       write_ds1302(j,year);


        j=j+2; 


}


void ds1302_init(void)


{


write_ds1302(0x8e,0x00);     //设置写保护位WP为‘1’,则才能写入数据


write_ds1302(0x80,0x00);     //设置时钟暂停标志CH为‘0’,时钟开始运行


       set();


write_ds1302(0x8e,0x80);     //关闭写入数据功能


}


1.2       LCD显示器与单片机并行通信


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_s1071">1


0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_s1070">




  


 



  


  

 




 


L


C


D

 
    

 


 


 


 


 


 


 


 


 


                    24   单片机与LCD通讯简易图


2LCD显示器驱动程序


    void LCD_delay()       //延时子程序


{  uchar i,j;


    for(i=0;i<10;i++)


   for(j=0;j<10;j++)


       ;


}


 


void LCD_command(uchar command)      //写入命令


{                                       


    XS=command; 


    RS=0;


    RW=0;


    EN=0;


    LCD_delay();


    EN=1;


}


void LCD_data(uchar dat)             //写入数据


{


    XS=dat;


    RS=1;


    RW=0;


    EN=0;


    LCD_delay();


    EN=1;


}


void LCD_write_char(uchar dat)      //写入字符


{


    LCD_data(dat);


}


void initlcd()


{


    LCD_command(0x01);       //数据指针清零,所有显示清零


    LCD_command(0x38);       //不检测忙信号  


    LCD_command(0x0c);       //开显示功能


    LCD_command(0x06);      //当读或写一个字符后地址指针加一,且光标指针加一


}






 


键盘扫描

 
2.3    4*4键盘流程及程序

1






将调整时间信息保存到单片机时间存储单元

 
0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_s1076">



单片机接收扫描码后,经判断执行任务

 
0 && image.height>0){if(image.width>=700){this.width=700;this.height=image.height*700/image.width;}}" v:shapes="_x0000_s1074">         

 


 


 


 2)程序


void delay()                      //延时子程序


{  uchar i;


  for(i=0;i<50;i++)


         {;}


}


uchar key1()


{


  unsigned char w1,w2,code;


  TRISB=0xff;


  w1=PORTB&0x0f;                 


  if(w1!=15)


  {


    w2=PORTB&0xf0;


    code=(w1|w2);                 //将行扫描码和列扫描码加在一起


   }


   else 


   code=0;


 return code;


}


void keyscan()


{   uchar key;                     //定义扫描码


   while(1)


      {


        key=key1();


        delay();


      switch(key)


       {                           //若遇按键时间各自加一


        case 0xee:second+=1;break;


        case 0xde:minute+=1;break;


        case 0xbe:hour+=1;break;


        case 0x7e:day+=1;break;


        case 0xed:month+=1;break;


        case 0xdd:xinqi+=1;break;


        case 0xbd:year+=1;break;


        deflaut:break;


       }


   }          


}


第五节            程序流程图及控制源程序


1        程序流程图



2        控制源程序


#include"pic.h"


#define uchar  unsigned char


#define io RA0                   //定义各端口


#define sck RA1


#define ce RA2


#define  XS  PORTD


#define  RS  RC0


#define  RW  RC1


#define  EN  RC2


uchar minute="0",second=0 ,hour=0,month=0 ,day=0 ,xinqi=0 ,year=0;//时间寄存器


void write_ds1302_byte(uchar temp)     //向时钟芯片写入字节子程序


{


 


  uchar i;


  for(i=0;i<8;i++)


     {


        sck = 0;


      io=(bit)(temp&0x01);


      sck=1;


      temp >>=1;


          


      }


}


void write_ds1302(uchar address,uchar dat)//向指定单元写入数据


{  


  ce=0;


  sck=0;


  ce=1;


  write_ds1302_byte(address);


  write_ds1302_byte(dat);


  ce=0;


}


unsigned char read_ds1302(uchar address)//接收DS1302发送的数据子程序


{


       uchar i,temp=0x00,dat1,dat2;


       ce=0;          


       sck=0;            


       ce=1; 


       write_ds1302_byte(address);


       TRISA = 0x01;


       for(i=0;i<8;i++)


       {


         if( io )


          temp|=0x80;


         sck = 1;


     temp>>=1;


     sck=0;


       }    


      ce=0;


     TRISA =0x00;                    //转换数据


       dat1=temp;


       dat2=dat1/16;                


       dat1=dat1%16;                   


       dat1=dat1+dat2*10;


       return (dat1);


}


void set_time(void)                  //设置时间子程序


{


 uchar j;


 j=0x80;


       write_ds1302(j,second);


        j=j+2;


       write_ds1302(j,minute);


        j=j+2;


       write_ds1302(j,hour);


        j=j+2;


       write_ds1302(j,day);


        j=j+2;


       write_ds1302(j,month);


        j=j+2;


       write_ds1302(j,xinqi);


        j=j+2;


       write_ds1302(j,year);


        j=j+2; 


}


void ds1302_init(void)                   //初始化DS1302


{


write_ds1302(0x8e,0x00);


write_ds1302(0x80,second&0x00);


       set_time();


write_ds1302(0x8e,0x80);


}


void LCD_delay()                        //LCD延时子程序


{  uchar i,j;


    for(i=0;i<10;i++)


   for(j=0;j<10;j++)


        ;


}


 


void LCD_command(uchar command)             //LCD命令子程序


{                                            


    XS=command; 


    RS=0;


    RW=0;


    EN=0;


    LCD_delay();


    EN=1;


}


void LCD_data(uchar dat)                 //写入LCD数据子程序


{


    XS=dat;


    RS=1;


    RW=0;


    EN=0;


    LCD_delay();


    EN=1;


}


void LCD_write_char(uchar dat)        //写入LCD字符子程序


{


    LCD_data(dat);


}


void initlcd()                        //初始化LCD


{


    LCD_command(0x01);     


    LCD_command(0x38);        


    LCD_command(0x0c);     


    LCD_command(0x06);


    //LCD_command(0x01);       


}


void time_menu()                    //显示控制子程序


{      


    LCD_command(0x01);


        LCD_command(0x80); 


    LCD_write_char('D');


    LCD_write_char('A');


    LCD_write_char('T');


        LCD_write_char('E');


        LCD_command(0xC0); 


    LCD_write_char('T');


    LCD_write_char('I');


    LCD_write_char('M');


        LCD_write_char('E');       


}


void read_time(void)                   //读取时间子程序


{


    uchar j;


    j=0x81;


     second=read_ds1302(j);


    j=j+2;


    minute=read_ds1302(j);


    j=j+2;


     hour=read_ds1302(j);


    j=j+2; 


    day= read_ds1302(j);


    j=j+2; 


   month=read_ds1302(j);


    j=j+2; 


    xinqi=read_ds1302(j);


    j=j+2;


   year=read_ds1302(j);


}


void showtime(void)                   //显示时间子程序


{


                      LCD_command(0x85);


                      //LCD_write_char('X');


                      //LCD_write_char('-');


                      //LCD_data(xinqi%10+0x30);


                      //LCD_write_char(' ');


                     LCD_write_char('Y');


                      LCD_write_char('-');


                      LCD_data(year/10+0x30);


                      LCD_data(year%10+0x30);


                      LCD_write_char(' ');


                      LCD_write_char('M');


                      LCD_write_char('-');


                      LCD_data(month/10+0x30);


                      LCD_data(month%10+0x30);


                      LCD_write_char(' ');


                      LCD_write_char('D');


                      LCD_write_char('-');


                      LCD_data(day/10+0x30);


                      LCD_data(day%10+0x30);


                    


                      LCD_command(0xc5);


                      LCD_data(hour/10+0x30);


                      LCD_data(hour%10+0x30);


                      LCD_write_char(':');


                      LCD_data(minute/10+0x30);


                      LCD_data(minute%10+0x30);


                      LCD_write_char(':');


                      LCD_data(second/10+0x30);


                      LCD_data(second%10+0x30);


}


void delay10ms(unsigned char time)      //按键延时子程序


{


   unsigned char a,b,c;


   for(a=0;a<time;a++)


   for(b=0;b<10;b++)


   for(c=0;c<120;c++)


     ;


}


 


uchar key1()                          //扫描按键码子程序


{


  unsigned char w1,w2,code;


  TRISB=0xff


  if(w1!=15)


  {w1=PORTB&0x0f;


    w2=PORTB&0xf0;


    code=(w1|w2);


   }


   else 


   code=0;


 return code;


}


void relax_key1()                   //等待按键松开子程序


{


   unsigned char keytemp,temp;


   while (1)


     {delay10ms(1);


       keytemp=0x0ff;


       temp=PORTB;


      if (keytemp==temp)


            {break;}


     }


}


void keyscan()                  //按键处理子程序


{   uchar key;


   while(1)


    {


        key=key1();


        relax_key1();


        delay10ms(1);


      switch(key)


       {


        case 0xee:second+=1;break;


        case 0xde:minute+=1;break;


        case 0xbe:hour+=1;break;


        case 0x7e:day+=1;break;


        case 0xed:month+=1;break;


        case 0xdd:xinqi+=1;break;


        case 0xbd:year+=1;break;


        deflaut:;break;


       }


        if(second==60)


        second=0;


       if(minute==60)


    minute=0;


    if(hour==25)


    hour=0;


        if(xinqi==8)


        xinqi=0;


        if(day==32)


        day=0;


        if(month==13)


        month=0;


        if(year==100)


        year=0;


      if(key==0xee)


       break;


       showtime();                      //调整时间后并显示


   }      


}


void time_fix()                        //调整时间并读入DS1302


{


   write_ds1302(0x80,0x80);


   keyscan();


   write_ds1302(0x80,second&0x7f);  


}


void main(void)


{


        TRISB=0xff;                  //端口方向设置


        TRISC=0x00;        


        TRISD=0x00;


        ADCON1=0X07;


        TRISA=0x00;


        RBPU=0; 


        initlcd();


        ds1302_init();


        time_menu();      


        while(1)


              {


                if(PORTB!=0xff) 


                {time_fix();


                ds1302_init();}


                read_time();


                showtime();


              }


     


}

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户377235 2012-12-2 14:18

对的 在塑封机里也有运用

用户186581 2008-10-12 03:01

大侠,图片怎么看不见啊?最近我在学习这个,能发一份完整的到我的邮箱么?nylql@163.com 不胜感激!谢谢!
相关推荐阅读
用户147756 2008-09-22 23:34
谁知道Dvicenet 协议中模拟量(A0)的访问流程
     弄明白大概的Devicenet协议,I/O与显式信息的流程。显式信息就是获得对象的属性,I/O就是传送数据的。我的程序就是采集模拟量的。A0就是模拟量的代称,我就不明白程序为什么不去访问模拟...
用户147756 2008-08-01 21:35
EEROM
     今天终于把一个51的程序完成了,都郁闷了一个月了。终于有点眉目了。不过等到最后发现EEROM读取数据不对头,弄了一下午郁闷得哟啊死。不甘心,晚上去回家找原因,结果仔细查看STC89C52RD...
用户147756 2008-06-30 19:55
devicenet连接对象
连接对象分类定义——分类ID号:5连接类将分配和管理与I/O及显式信息连接有关的内部资源。有连接类生成的特定的实例称连接实例或连接对象。重要说明:存在 通过显式信息连接的连接类外部可视接口。一个特定模...
用户147756 2008-06-30 19:54
devicenet分段协议
如果显式信息长度大于9字节,则必须在Devicenet哂纳感以分段方式传输。<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:...
用户147756 2008-06-12 19:52
一些芯片的的封装图
...
用户147756 2008-06-12 19:49
这个电源图的理论是怎样的呢?
 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> ...
EE直播间
更多
我要评论
1
6
关闭 站长推荐上一条 /3 下一条