基于DS1302和LCD1602的可调数字钟.doc_第1页
基于DS1302和LCD1602的可调数字钟.doc_第2页
基于DS1302和LCD1602的可调数字钟.doc_第3页
基于DS1302和LCD1602的可调数字钟.doc_第4页
基于DS1302和LCD1602的可调数字钟.doc_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

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

文档简介

作者 张小波学习情境5-可调式数字钟之 基于DS1302和LCD1602的可调数字钟 点名,复习1、 DS1302的引脚及其功能,以及DS1302与单片机的硬件连接?2、 如何对DS1302读写数据,如何得到DS1302的时钟? 新课讲授5.3 基于DS1302与LCD1602设计的可调数字钟上堂课程我们学会了使用DS1302,知道了如何在单片机系统中的连接,也详细的学习了如何得到DS1302的时钟,并且我们使用了16个数码管把年月日和时分秒实时地显示出来。但数码管的显示毕竟有其自身的缺陷,现在在工业控制的各个环节,都使用液晶进行人机联系。在日常生活中,我们对液晶显示器并不陌生。液晶显示模块已作为很多电子产品的通用器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED数码管、液晶显示器。发光管和LED数码管比较常用,软硬件都比较简单, 在单片机系统中应用晶液显示器作为输出器件有以下几个优点:(1)显示质量高,由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。因此,液晶显示器画质高且不会闪烁。(2)数字式接口,液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。(3)体积小、重量轻,液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。(4)功耗低,相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。5.3.1 LCD1602技术资料5.3.1.1 液晶显示简介1、液晶显示原理:液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形。液晶显示器具有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式电脑、数字摄像机、PDA移动通信工具等众多领域。2、液晶显示器的分类:液晶显示的分类方法有很多种,通常可按其显示方式分为段式、字符式、点阵式等。除了黑白显示外,液晶显示器还有多灰度有彩色显示等。如果根据驱动方式来分,可以分为静态驱动(Static)、单纯矩阵驱动(Simple Matrix)和主动矩阵驱动(Active Matrix)三种。3、液晶显示器各种图形的显示原理:线段的显示:点阵图形式液晶由MN个显示单元组成,假设LCD显示屏有64行,每行有128列,每8列对应1字节的8位,即每行由16字节,共168=128个点组成,屏上6416个显示单元与显示RAM区1024字节相对应,每一字节的内容和显示屏上相应位置的亮暗对应。例如屏的第一行的亮暗由RAM区的000H00FH的16字节的内容决定,当(000H)=FFH时,则屏幕的左上角显示一条短亮线,长度为8个点;当(3FFH)=FFH时,则屏幕的右下角显示一条短亮线;当(000H)=FFH,(001H)=00H,(002H)=00H,(00EH)=00H,(00FH)=00H时,则在屏幕的顶部显示一条由8段亮线和8条暗线组成的虚线。这就是LCD显示的基本原理。字符的显示:用LCD显示一个字符时比较复杂,因为一个字符由68或88点阵组成,既要找到和显示屏幕上某几个位置对应的显示RAM区的8字节,还要使每字节的不同位为“1”,其它的为“0”,为“1”的点亮,为“0”的不亮。这样一来就组成某个字符。但由于内带字符发生器的控制器来说,显示字符就比较简单了,可以让控制器工作在文本方式,根据在LCD上开始显示的行列号及每行的列数找出显示RAM对应的地址,设立光标,在此送上该字符对应的代码即可。汉字的显示:汉字的显示一般采用图形的方式,事先从微机中提取要显示的汉字的点阵码(一般用字模提取软件),每个汉字占32B,分左右两半,各占16B,左边为1、3、5右边为2、4、6根据在LCD上开始显示的行列号及每行的列数可找出显示RAM对应的地址,设立光标,送上要显示的汉字的第一字节,光标位置加1,送第二个字节,换行按列对齐,送第三个字节直到32B显示完就可以LCD上得到一个完整汉字。5.3.1.2、1602字符型LCD简介字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。一般1602字符型液晶显示器实物如图(1):图(1) 1602字符型液晶显示器实物图1602LCD分为带背光和不带背光两种,基控制器大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别。 1602LCD主要技术参数:显示容量:162个字符;芯片工作电压:4.55.5V;工作电流:2.0mA(5.0V);模块最佳工作电压:5.0V;字符尺寸:2.954.35(WH)mm引脚功能说明:1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表1所示:第1脚:VSS为地电源。第2脚:VDD接5V正电源。第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。第714脚:D0D7为8位双向数据线。第15脚:背光源正极。第16脚:背光源负极。表1 1602LCD引脚接口说明编号符号引脚说明编号符号引脚说明1VSS电源地9D2数据2VDD电源正极10D3数据3VL液晶显示偏压11D4数据4RS数据/命令选择12D5数据5R/W读/写选择13D6数据6E使能信号14D7数据7D0数据15BLA背光源正极8D1数据16BLK背光源负极5.3.1.3、 1602LCD的指令说明及时序1602液晶模块内部的控制器共有11条控制指令,如表2所示:表2:控制命令表序号指令RSR/WD7D6D5D4D3D2D1D0功能1复位显示器0000000001清屏,光标归位2光标返回000000001*设置地址计数器清零,DDRAM数据不变,光标移到左上角3字符进入模式00000001I/DS设置字符进入时的屏幕移位方式4显示开/关控制0000001DCB设置显示开关,光标开关,闪烁开关5光标或字符移位000001S/CR/L*设置字符与光标移动6功能设置00001DLNF*设置DL,显示行数,字体7设置字符发生存贮器地址0001字符发生存贮器地址设置6位的CGRAM地址以读/写数据8设置数据存贮器地址001显示数据存贮器地址设置7位的DDRAM地址以读/写数据9读忙标志或地址01BF计数器地址读忙标志及地址计数器10写数据到CGRAM或DDRAM)10写入一字节数据,需要先设置RAM地址向CGRAM/DDRAM写入一字节的数据11从CGRAM或DDRAM读数据11读取入一字节数据,需要先设置RAM地址从CGRAM/DDRAM读取一字节的数据I/D =1 递增,I/D=0 递减。S=0 时显示屏不移动,S=1时,如果I/D =1且有字符写入时显示屏左移,否则右移。D=1 显示屏开,D=0 显示屏关。C=1 时光标出现在地址计数器所指的位置,C=0时光标不出现。B=1 时光标出现闪烁,B=0时光标不闪烁。S/C=0 时,RL=0则光标左移,否则右移。S/C=1 时,RL=0则字符和光标左移,否则右移。DL=1 时数据长度为8位,DL=0 时为使用D7-D4共4位,分两次送一字节。N=0为单行显示,N=1时为双行显示。F=1 时为510点阵字体,F=0 时为57点阵字体。BF=1 时LCD忙,BF=0 时LCD就绪。1602液晶模块的读写操作、屏幕和光标的操作都是通过指令编程来实现的。(说明:1为高电平、0为低电平)指令1:清显示,指令码01H,光标复位到地址00H位置。指令2:光标复位,光标返回到地址00H。指令3:光标和显示模式设置 I/D:光标移动方向,高电平右移,低电平左移 S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。指令4:显示开关控制。 D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示 C:控制光标的开与关,高电平表示有光标,低电平表示无光标 B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。指令5:光标或显示移位 S/C:高电平时移动显示的文字,低电平时移动光标。指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线 N:低电平时为单行显示,高电平时双行显示 F: 低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。指令7:字符发生器RAM地址设置。指令8:DDRAM地址设置。指令9:读忙信号和光标地址 BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。指令10:写数据。指令11:读数据。与HD44780相兼容的芯片时序表如下: 表 3:基本操作时序表读状态输入RS=L,R/W=H,E=H输出D0D7=状态字写指令输入RS=L,R/W=L,D0D7=指令码,E=高脉冲输出无读数据输入RS=H,R/W=H,E=H输出D0D7=数据写数据输入RS=H,R/W=L,D0D7=数据,E=高脉冲输出无读写操作时序如图3和 4所示:图3 读操作时序图4 写操作时序5.3.1.4 1602LCD的RAM地址映射及标准字库表 液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志位,如果该位为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图5是1602的内部显示地址。图5 1602LCD内部显示地址 例如第二行第一个字符的地址是40H,那么是否直接写入40H就可以将光标定位在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位D7恒定为高电平1所以实际写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H)。在对液晶模块的初始化中要先设置其显示模式,在液晶模块显示字符时光标是自动右移的,无需人工干预。每次输入指令前都要判断液晶模块是否处于忙的状态。1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,如图6所示,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”图6 字符代码与图形对应图5.3.2 硬件电路设计 硬件主要使用了DS1302和LCD1602,电路结构简单,具体如下图所示: 图 7 硬件电路5.3.3 软件设计 软件设计中主要是针对DS1302芯片和LCD1602进行程序的设计,而DS1302的驱动程序在上个项目中我们已经作了详细介绍,在此不再赘述。我们主要编制LCD的驱动程序。根据对LCD资料的分析,程序编制主要有:读取LCD的状态,忙检查,向LCD写入命令,向LCD写入数据,LCD初始化,设置LCD液晶的显示位置,显示字符等,具体如下: 1、读取LCD的状态 /-读取LCD的状态-*/uchar Read_LCD_State() uchar state; RS=0; RW=1; EN=1; DelayMS(2); state=P0; EN=0; DelayMS(2); return state; 2、忙检查 /-忙检查-*/void LCD_Busy_Wait() while(Read_LCD_State()&0x80)=0x80);DelayMS(5); 3、向LCD写入命令 /-写LCD命令-*/void Write_LCD_Command(uchar cmd) LCD_Busy_Wait(); RS=0; RW=0; EN=0; P0=cmd; EN=1; DelayMS(2); EN=0; 4、向LCD写入数据 /-向LCD写入数据-*/void Write_LCD_Data(uchar dat) LCD_Busy_Wait(); RS=1; RW=0; EN=0; P0=dat; EN=1; DelayMS(2); EN=0; 5、LCD初始化 /-LCD初始化-*/void Initialize_LCD1602() /液晶初始化函数 Write_LCD_Command(0x38);DelayMS(2);/功能设置,数据长度为8位,双行显示57点/阵字体 Write_LCD_Command(0x01);DelayMS(2);/清屏 Write_LCD_Command(0x06);DelayMS(2); /字符进入模式:屏幕不动,字符后移 Write_LCD_Command(0x0c);DelayMS(2); / 显示开,关光标 6、设置LCD液晶的显示位置 /-设置液晶显示位置-*/void Set_LCD_Position(uchar pos) Write_LCD_Command(pos|0x80); /设置7位的DDRAM地址值 7、显示字符 /-在LCD上显示字符串-*/void LCD_Display(uchar p,uchar *str) uchar i; Set_LCD_Position(p); for(i=0;i16;i+) Write_LCD_Data(stri); DelayMS(2); 除此之外,还有年、月、日、时、分等的设置函数,显示函数,键盘处理函数等,在此不在详细介绍,同学们可参考完整程序中的代码。 完整程序代码1、LCD1602.c源程序/-LCD1602.c-/液晶控制与显示驱动程序/-#include #include #define uchar unsigned char#define uint unsigned intsbit RS=P20; / LCD寄存器选择sbit RW=P21; / LCD读写控制sbit EN=P22; / LCD启动/*-延时子程序-*/void DelayMS(uint K) uchar i; while(K-) for(i=0;i120;i+); /-读取LCD的状态-*/uchar Read_LCD_State() uchar state; RS=0; RW=1; EN=1; DelayMS(2); state=P0; EN=0; DelayMS(2); return state;/-忙检查-*/void LCD_Busy_Wait() while(Read_LCD_State()&0x80)=0x80);DelayMS(5);/-写LCD命令-*/void Write_LCD_Command(uchar cmd) LCD_Busy_Wait(); RS=0; RW=0; EN=0; P0=cmd; EN=1; DelayMS(2); EN=0;/-向LCD写入数据-*/void Write_LCD_Data(uchar dat) LCD_Busy_Wait(); RS=1; RW=0; EN=0; P0=dat; EN=1; DelayMS(2); EN=0; /-LCD初始化-*/void Initialize_LCD1602() /液晶初始化函数 Write_LCD_Command(0x38);DelayMS(2); /功能设置,数据长度为8位,双行显示,57点阵字体 Write_LCD_Command(0x01);DelayMS(2);/清屏 Write_LCD_Command(0x06);DelayMS(2); /字符进入模式:屏幕不动,字符后移 Write_LCD_Command(0x0c);DelayMS(2); / 显示开,关光标/-设置液晶显示位置-*/void Set_LCD_Position(uchar pos) Write_LCD_Command(pos|0x80); /设置7位的DDRAM地址值/-在LCD上显示字符串-*/void LCD_Display(uchar p,uchar *str) uchar i; Set_LCD_Position(p); for(i=0;i16;i+) Write_LCD_Data(stri); DelayMS(2);2、main.c源程序/-/ 名称: 用DS1302和1602液晶显示的实时时钟/-/说明:本程序运行时会以PC时间为默认时间开始运行,运行过程中可以通过K1按键选择调节对象,用K2、K3/ 按键进行加减,用K4按键保存。/-#include #include #include #define uchar unsigned char#define uint unsigned intvoid Initialize_LCD1602(); /液晶初始化函数void LCD_Display(uchar p,uchar *str);sbit SDA=P10; /DS1302数据线sbit CLK=P11; /DS1302时钟线sbit RST=P12; / DS1302复位线sbit k1=P33; / 选择按键sbit k2=P34; / 加sbit k3=P35; /减sbit k4=P36; /确定uchar tcount=0;uchar MonthsDays=0,31,0,31,30,31,30,31,31,30,31,30,31; / 一年中每个月的天数,二月的天数由年份决定uchar *Week=SUN,MON,TUS,WEN,THU,FRI,SAT; /周日,周一到周六/ LCD显示缓冲uchar LCD_DSY_BUFFER1=DATE 00-00-00 ;uchar LCD_DSY_BUFFER2=TIME 00:00:00 ;uchar DateTime7;/所读取的日期时间char Adjust_Index=-1; /当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,6)uchar Change_Flag=-MHDM-Y;/(分,时,日,月,年)不调节秒和周/函数声明void Write_Byte_TO_DS1302(uchar X); / 向DS1302写入一个字节uchar Read_Byte_FROM_DS1302();/从DS1302中读取一个字节uchar Read_Data_FROM_DS1302(uchar addr); /从DS1302指定位置读取数据, 读数据void Write_Data_TO_DS1302(uchar addr,uchar dat); / 向DS1302指定位置写入数据, 写数据void SET_DS1302(); / 设置时间void GetTime(); / 读取当前时间void Initialization(); /初始化函数/-/ 主程序/-void main() Initialization(); while(1) if(Adjust_Index=-1) GetTime();/*-初始化函数-*/void Initialization() Initialize_LCD1602(); /调用液晶初始化函数 IE=0x83; /允许中断 外部0中断和T0中断 IP=0x01; / 设置中断优先级 IT0=0x01; / 设置外部中断的脉冲触发方式 TMOD=0x01; / 设置定时器的工作方式,为方式1 TH0=-50000/256; / 写入初值 TL0=-50000%256; / 写入初值 TR0=1; / 启动定时器/*-写字节函数,向DS1302写入一个字节-*/ void Write_Byte_TO_DS1302(uchar X) / 向DS1302写入一个字节 uchar i; for(i=0;i=1; /*-读字节函数,从DS1302读取一个字节-*/uchar Read_Byte_FROM_DS1302()/从DS1302中读取一个字节 uchar i,byte,t; for(i=0;i=1; t=SDA; byte|=t7; CLK=1; CLK=0; /BCD码转换 return byte/16*10+byte%16; /- /从DS1302指定位置读取数据, 读数据 /- uchar Read_Data_FROM_DS1302(uchar addr) /从DS1302指定位置读取数据, 读数据 uchar dat; RST=0; CLK=0; RST=1; Write_Byte_TO_DS1302(addr); /向DS1302写入一个地址 dat=Read_Byte_FROM_DS1302(); /在上面写入的地址中读取数据 CLK=1; RST=0; return dat; /- /向DS1302指定位置写入数据, 写数据 /- void Write_Data_TO_DS1302(uchar addr,uchar dat) / 向DS1302指定位置写入数据, 写数据 CLK=0; RST=1; Write_Byte_TO_DS1302(addr); Write_Byte_TO_DS1302(dat); CLK=1; RST=0; /- / 设置时间 /- void SET_DS1302() / 设置时间 uchar i; Write_Data_TO_DS1302(0x8E,0x00); /写控制字,取消写保护 / 分,时,日,月,年依次写入 for(i=1;i7;i+) / 分的起始地址是10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递增2 Write_Data_TO_DS1302(0x80+2*i,(DateTimei/104)|(DateTimei%10); Write_Data_TO_DS1302(0x8E,0x80); /写控制字,加写保护 /-/ 读取当前时间/-void GetTime() / 读取当前时间 uchar i; for(i=0;i7;i+) DateTimei=Read_Data_FROM_DS1302(0x81+2*i);/-/日期与时间值转换为数字字符/-void Format_DateTime(uchar d,uchar *a) a0=d/10+0;a1=d%10+0;/-/ 判断是否为闰年/-uchar Is_Leapyear(uint year) return (year%4=0&year%100!=0)|(year%400=0) ;/-/ 求自2000.1.1开始的任何一天是星期几?/-void Refresh_Week_Day() uint i,d,w=5; /已知1999年12.31是星期五 for(i=2000;i2000+DateTime6;i+) d=Is_Leapyear(i)?366:365;w=(w+d)%7; d=0; for (i=1;iDateTime4;i+) d+=MonthsDaysi; d+=DateTime3; /保存星期,0-6表示星期日,星期一至星期六,为了与DS1302的星期格式匹配,返回值需要加1 DateTime5=(w+d)%7+1;/-/年,月,日和时,分+/-/-void Datetime_Adjust(char X) switch(Adjust_Index) case 6: /年调整,00-99 if(X=1&DateTime60) DateTime6-; /获取2月天数 MonthsDays2=Is_Leapyear(2000+DateTime6)?29:28; /如果年份变化后当前月份的天数大于上限则设为上限 if(DateTime3MonthsDaysDateTime4) DateTime3=MonthsDaysDateTime4; Refresh_Week_Day(); /刷新星期 break; case 4: /月调整 01-12 if(X=1&DateTime41) DateTime4-; /获取2月天数 MonthsDays2=Is_Leapyear(2000+DateTime6)?29:28; /如果年份变化后当前月份的天数大于上限则设为上限 if(DateTime3MonthsDaysDateTime4) DateTime3=MonthsDaysDateTime4; Refresh_Week_Day(); /刷新星期 break; case 3: / 日调整00-28或00-29或00-30或00-31 /调节之前首先根据当前年份得出该年中2月的天数 MonthsDays2=Is_Leapyear(2000+DateTime6)?29:28; /根据当前月份决定调节日期的上限 if(X=1&DateTime30) DateTime3-; Refresh_Week_Day(); /刷新星期 break

温馨提示

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

评论

0/150

提交评论