项目十-单片机简易万年历设计课件_第1页
项目十-单片机简易万年历设计课件_第2页
项目十-单片机简易万年历设计课件_第3页
项目十-单片机简易万年历设计课件_第4页
项目十-单片机简易万年历设计课件_第5页
已阅读5页,还剩103页未读 继续免费阅读

下载本文档

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

文档简介

一、学习目标1.了解红外线工作原理。2.掌握SPI总线协议。3.掌握DS1302驱动方法。4.掌握LCD128*64驱动显示中文的方法。二、学习任务随着电子技术的发展,人类不断研究,不断创新纪录。万年历目前已经不再局限于以书本形式出现。以电脑软件或者电子产品形式出现的万年历被称为电子万年历。与传统书本形式的万年历相比,电子万年历得到了越来越广泛的应用,采用电子时钟作为时间显示已经成为一种时尚。目前市场上各式各样的电子时钟数不胜数,但多数是只针对时间显示,功能单一不能满足人们日常生活需求。本项目任务分解为具体2个学习任务:任务一DS1302时钟数码管显示;任务二简易万年历设计。三、任务分解任务一DS1302时钟数码管显示【任务描述】随着社会、科技的发展,人类得知时间,从观太阳、摆钟到现在电子钟,不断研究、创新。为了在观测时间,能够了解与人类密切相关的信息,比如星期、日期等,电子时钟诞生了,它集时间、日期、星期等功能于一身,具有读取方便、显示直观、功能多样、电路简洁等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。使用实时时钟芯片DS1302,设计一简易万年历,显示日期和时间,做到可以调时。【任务分析】DS1302时钟芯片是美国DALLAS公司推出的具有涓细电流充电功能的低功耗实时时钟芯片,它可以对年、月、日、星期、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小;数字显示是采用的LED显示屏来显示,可以同时显示年、月、日、星期、时、分、秒和温度等信息。此外,该电子时钟还具有时间校准等功能。【相关知识】SPI总线SPI总线是串行外围设备接口,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线.SPI的通信原理很简单,它以主从方式工作,通常有一个主设备和一个或多个从设备,需要至少4根线。SDO–主设备数据输出,从设备数据输入SDI–主设备数据输入,从设备数据输出SCLK–用来为数据通信提供同步时钟信号,由主设备产生CS–从设备使能信号,由主设备控制SPI接口是全双工、同步、串口、单主机。SPI从机从主机获得时钟和片选信号,因此cs和sclk都是输入信号。SPI接口在内部硬件实际上是个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。

SPI从机的内部结构SPI总线如果一个SPI从机没有被选中,他的数据输出端SDO将处于高阻状态,从而与当前处于激活状态的隔离开。寻址:MOSI:Whenmaster,outline;whenslave,inlineMISO:Whenmaster,inline;whenslave,outlineSPI从机的内部结构SPI接口实际上是两个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。

上升沿发送,下降沿接收。(有的器件是上升沿接收,下降沿发送)D7....D0D0....D7SPI总线SPI总线在一次数据传输过程中,接口上只能有一个主机和一个从机能够通信。并且,主机总是向从机发送一个字节数据,而从机也总是向主机发送一个字节数据。

在SPI传输中,数据是同步进行发送和接收的。数据传输的时钟基于来自主处理器的时钟脉冲,当SPI接口上有多个SPI接口的单片机时,应区别其主从地位,在某一时刻只能由一个单片机为主器件。从器件只能在主机发命令时,才能接收或向主机传送数据。其数据的传输格式是高位(MSB)在前,低位(LSB)在SPI接口的一个缺点:没有应答机制确认是否接收到数据。如果只是进行写操作,主机只需忽略收到的字节;反过来,如果主机要读取外设的一个字节,就必须发送一个空字节来引发从机的传输。SPI总线SPI总线添加从器件:每个从器件需要一个单独的从选择信号。总信号数最终为n+3个,其中n是总线上从器件的数量。在SPI总线上添加新的从器件也不方便。对于额外添加的每个从器件,都需要一条新的从器件选择线上面的上表示上升沿、下表示下降沿,sdi、sdo相对于主机而言的。

一个完整的传送周期是16位,即两个字节,因为,首先主机要发送命令过去,然后从机根据主机的命令准备数据,主机在下一个8位时钟周期才把数据读回来。SPI总线的硬件接口电路

SPI接口的串行时钟芯片DS1302实时时钟,可对秒、分、时、日、周、月以及带闰年补偿的年进行计数;用于高速数据暂存的31×8RAM;

简单的SPI三线串口;/RST引脚:复位兼片选,读/写操作时必须为高电平。单片机与DS1302的接口DS1302的内部结构DS1302的工作原理单片机开始数据传送时,必须将DS1302的/RST置高,且把包含有地址和命令信息的8位数据发送给DS1302.数据在SCLK的上升沿入,下降沿串行出;单片机对DS1302的读/写是命令字来初始化的。命令字格式:命令字节的D7必须为1,若D7=0,写保护;D6=0,表示存取日历时钟数据;D6=1,表示存取RAM数据.D5~D1指示操作单元的地址;D0=0,表示写;D0=1,表示读;DS1302的寄存器数据在SCLK的上升沿入,下降沿串行出;单字节操作:每次对DS1302的写入或读出都由命令字节引导,每次只传送1字节数据。单字节写操作:单片机通过8个sclk下降沿传送写命令字节后,在接下来的8个sclk时钟的下降沿传送一字节数据。如果有更多的sclk周期,DS1302将会忽略。单字节读操作:单字节读操作每次需16个时钟,地址字节在前8个时钟周期的上升沿输入,而数据字节在后8个时钟周期的下降沿输出。.DS1302输出的第一位数据是在命令字节最后一位的第一个下降沿处,如果有更多的sclk周期,DS1302将重新发送数据字节。多字节操作多字节操作:每次对DS1302的写入或读出都由命令字节引导,然后对时钟寄存器的7个寄存器或31个RAM依次按顺序写入/读出。多字节写操作:单片机通过8个sclk下降沿传送命令字节后,在接下来的8个sclk时钟的下降沿传送一字节数据,以次类推。多字节读操作::单片机通过8个sclk下降沿传送命令字节后,在紧接着的的8个sclk时钟的下降沿DS1302传送一字节数据,以次类推。特殊寄存器在DS1302的时钟日历或RAM进行数据传送时,DS1302必须首先发送命令字节。若进行单字节传送,8位命令字节传送结束之后,在下8个SCLK周期的下降沿输出数据字节。DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;再一类为突发方式下的RAM寄存器,在此方式下可一次性读、写所有的RAM的31个字节。命令字为BEH和BFH

写保护寄存器:写保护寄存器命令字D7D6D5D4D3D2D1D08EH或8FHWP000,0000RAM单元命令字D7RAM/CKD5D4D3D2D1R/W0单元C0H或C1H1100,000R/W1单元C2H或C3H1100,001R/W2单元C4H或C5H1100,010R/W34........31单元C6H或C7H.C8H或C9H...............FCH或FDH.1100,011R/W1100,100R/W........1111,110R/W程序举例:初始化日历寄存器片内RAM说明68H(秒)0101,00105267H(分)0011,01003466H(时)1965H(日)0164H(星期)周三63H(月)1062H(年)1161H(写保护寄存器)00hDS1302的寄存器【任务实施】单片机驱动DS1302数码管显示对应的程序代码如下:#include<reg51.h>#include<intrins.h>#defineucharunsignedchar#defineuintunsignedintsbit

sck=P3^0;sbit

io=P3^1;sbit

rst=P3^2;unsignedchartable1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};unsignedchartable2[]={0xe0,0xc0,0xa0,0x80,0x60,0x40,0x20,0x00};uchartime_data[7]={10,6,4,17,11,58,30}; //年周月日时分秒ucharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};ucharread_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};uchardisp[8];voidwrite_ds1302_byte(uchardat);voidwrite_ds1302(ucharadd,uchar

dat);ucharread_ds1302(ucharadd);voidset_rtc(void);voidread_rtc(void);voidtime_pros(void);voiddisplay(void);voiddelay(unsigned

inta){while(a--);}voidwrite_ds1302_byte(uchardat)//写一字节子程序{ uchari;

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

sck=0;

io=dat&0x01;

dat=dat>>1;

sck=1; }}voidwrite_ds1302(ucharadd,uchar

dat)//向DS1302写数据{

rst=0; _nop_();

sck=0;_nop_();

rst=1; _nop_(); write_ds1302_byte(add); write_ds1302_byte(dat);

rst=0; _nop_();

io=1;

sck=1;}ucharread_ds1302(ucharadd)//读一字节数据{

uchar

i,value;

rst=0; _nop_();

sck=0; _nop_();

rst=1; _nop_(); write_ds1302_byte(add);//写地址

for(i=0;i<8;i++)//8次循环读出数据线上的数据

{ value=value>>1;

sck=0;

if(io) value=value|0x80;

sck=1; }

rst=0; _nop_();

sck=0; _nop_();

sck=1;

io=1; returnvalue;//返回读到的值}voidset_rtc(void) {

uchar

i,j;

for(i=0;i<7;i++) { j=time_data[i]/10;

time_data[i]=time_data[i]%10;

time_data[i]=time_data[i]+j*16; } write_ds1302(0x8e,0x00); //去除写保护

for(i=0;i<7;i++) { write_ds1302(write_add[i],time_data[i]); } write_ds1302(0x8e,0x80); //加写保护}voidread_rtc(void)//设置初始时间{

uchari;

for(i=0;i<7;i++) {

time_data[i]=read_ds1302(read_add[i]); } }voidtime_pros(void)//分离出数码管显示所需数据{ disp[0]=time_data[6]%16; disp[1]=time_data[6]/16; disp[2]=0x40; disp[3]=time_data[5]%16; disp[4]=time_data[5]/16; disp[5]=0x40; disp[6]=time_data[4]%16; disp[7]=time_data[4]/16; }voiddisplay(void)//数码管显示{

uchari;

for(i=0;i<8;i++) { P1=table2[i];

if(i==2||i==5){ P2=table1[10]; }else{ P2=table1[disp[i]]; } delay(200); }}voidmain(){while(1){read_rtc();time_pros();display();} }【进阶提高】将上面任务中的数码管改用液晶LCD1602显示。在Proteus软件中按下图所示,绘制电路图。main.c程序代码:#include<reg51.h>#include<lcd1602.h>#include<ds1302.h>#defineucharunsignedcharuchar

hour,minute,second,week,day,month,year;voidmain(){uchari;

Initial_LCD();//液晶初始化

Initial_DS1302();//DS1302初始化

set_rtc();//对时操作

while(1){ TimeToStr(); LCD_WRITE_COM(0x80);//液晶第一行显示

for(i=0;i<16;i++) {

LCD_WRITE_DATA(TimeString[i]); delay(5); }}}lcd1602.h文件代码:sbitLCD_E=P2^2;//液晶使能端sbitLCD_RS=P2^0;//液晶数据命令选择端sbitLCD_RW=P2^1;//液晶读写选择端voiddelay(unsignedcharz);//延时函数申明voidLCD_WRITE_COM(unsignedcharcom);//液晶写命令函数申明voidLCD_WRITE_DATA(unsignedchardate);//液晶写数据函数申明voidInitial_LCD();//液晶初始化函数申明/*****************************************LCD延时函数,不判断忙,延时机制操作LCD*****************************************/voiddelay(unsignedcharz)//延时函数{unsignedcharx,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);}/*****************************************LCD写命令函数*****************************************/voidLCD_WRITE_COM(unsignedcharcom)//写命令函数{LCD_RS=0;

LCD_RW=0;LCD_E=1;P0=com;delay(5);LCD_E=0;}/*****************************************LCD写数据函数*****************************************/voidLCD_WRITE_DATA(unsignedchardate)//写数据函数{LCD_RS=1;LCD_RW=0;LCD_E=1;P0=date;delay(5);LCD_E=0;}/*****************************************LCD初始化函数*****************************************/voidInitial_LCD()//液晶初始化函数{LCD_WRITE_COM(0x38);//设置16*2显示,5*7点阵,8位数据接口

LCD_WRITE_COM(0x0c);//设置开显示,不显示光标

LCD_WRITE_COM(0x06);//写一个字符后地址指针加1}ds1302.h文件代码:/*****************************************DS1302读写相关寄存器地址宏定义*****************************************/#defineWRITE_SECOND 0x80#defineWRITE_MINUTE 0x82#defineWRITE_HOUR 0x84#defineWRITE_DAY 0x86#defineWRITE_MONTH 0x88#defineWRITE_YEAR 0x8C#defineWRITE_PROTECT 0x8E#defineWRITE_WEEK 0x8A#defineWRITE_CURRENT0x90#defineREAD_SECOND 0x81#defineREAD_MINUTE 0x83#defineREAD_HOUR 0x85#defineREAD_DAY 0x87#defineREAD_MONTH 0x89#defineREAD_WEEK 0x8B#defineREAD_YEAR 0x8DsbitRST=P1^2;//DS1302片选sbitDIO=P1^1;//DS1302数据信号sbitSCLK=P1^0;//DS1302时钟信号sbitACC_7=ACC^7;//位寻址寄存器定义unsignedchartime_data[7]={10,6,4,17,11,58,59};//10年6周4月17日11时58分59秒unsignedcharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//年周月日时分秒写寄存器地址unsignedcharTimeString[16];unsignedcharhour,minute,second,week,day,month,year;voidInitial_DS1302();//DS1302初始化函数申明unsignedcharread_1302(unsignedcharaddr);//DS1302读数据函数申明voidwrite_1302(unsignedcharaddr,unsignedchardate);//DS1302写数据函数申明voidTimeToStr(void);/*****************************************DS1302写入函数*****************************************/voidwrite_1302(unsignedcharaddr,unsignedchardate)//地址、数据发送子程序{unsignedchari,temp;RST=0;//RST引脚为低,数据传送中止

SCLK=0;//清零时钟总线

RST=1;//RST引脚为高,逻辑控制有效

for(i=8;i>0;i--)//发送地址,循环8次移位

{ SCLK=0; temp=addr; DIO=(bit)(temp&0x01);//每次传送低字节

addr>>=1;//右移一位

SCLK=1;}

for(i=8;i>0;i--)//发送数据

{ SCLK=0; temp=date; DIO=(bit)(temp&0x01); date>>=1; SCLK=1;

}RST=0;}unsignedcharread_1302(unsignedcharaddr)//读取数据{unsignedchari,temp,date1,date2;RST=0;SCLK=0;RST=1;

for(i=8;i>0;i--)//循环8次移位,写入要读的寄存器地址

{ SCLK=0; temp=addr; DIO=(bit)(temp&0x01);//每次传送低字节

addr>>=1;//右移一位

SCLK=1;}

for(i=8;i>0;i--){ ACC_7=DIO; SCLK=1; ACC>>=1; SCLK=0;}RST=0;date1=ACC;date2=date1/16;//数据进制转换

date1=date1%16;//十六进制转十进制

date1=date1+date2*10;return(date1);}/*****************************************设置时间,对时函数*****************************************/voidset_rtc(void){unsignedchari,j;for(i=0;i<7;i++){j=time_data[i]/10;time_data[i]=time_data[i]%10;time_data[i]=time_data[i]+j*16;//拼接成BCD码}

write_1302(0x8e,0x00);//去掉写保护

for(i=0;i<7;i++){write_1302(write_add[i],time_data[i]);}write_1302(0x8e,0x80);//防止误操作,加上写保护}/*****************************************时间转字符串*****************************************/voidTimeToStr(void){

hour=read_1302(0x85);TimeString[5]=hour/10+'0';TimeString[6]=hour%10+'0';//分解2位数的十位和个位

TimeString[7]=':';minute=read_1302(0x83);TimeString[8]=minute/10+'0';TimeString[9]=minute%10+'0';TimeString[10]=':';second=read_1302(0x81);TimeString[11]=second/10+'0';TimeString[12]=second%10+'0';}/*****************************************初始化DS1302,暂停标志位CH置0,启动DS1302*****************************************/voidInitial_DS1302(){write_1302(WRITE_SECOND,read_1302(READ_SECOND)&0x7f);//把秒寄存器的暂停标志位CH置0,启动DS1302,为1的话,暂停}任务二简易万年历设计【任务描述】在许多的单片机系统中,通常进行一些与时间有关的控制,这就需要使用实时时钟。例如在测量控制系统中,特别是长时间无人值守的测控系统中,经常需要记录某些具有特殊意义的数据及其出现的时间。在系统中采用实时时钟芯片能很好的解决这个问题。本任务要求使用DS1302显示年月日,显示时分秒,并且做到可以调时。【任务分析】熟练使用液晶,按键等技术,使用单片机驱动DS1302调时并显示。【相关知识】要实现严格意义上的万年历,需要显示农历,那么需要显示中文,就需要用到点阵型LCD了。这里就点阵型LCD作一简要介绍:一、128*64点阵型LCD简介点阵式液晶显示模块(LCD)广泛应用于单片机控制系统,比数码管、段式液晶能模块显示更多、更直观的信息,如汉字、曲线、图片等。点阵液晶显示模块集成度很高,一般都内置控制芯片、行驱动芯片和列驱动芯片,点阵数量较大的LCD还配置RAM芯片,带汉字库的LCD还内嵌汉字库芯片,有负压输出的LCD还设有负压驱动电路等。单片机读写LCD实际上就是对LCD的控制芯片进行读写命令和数据。编程驱动LCD时,不需要对LCD的结构和点阵行列驱动原理深入了解,只要理解LCD接口的定义和LCD的控制芯片的读写时序和命令就可以了。1.概述FYD12864-0402B是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;其显示分辨率为128×64,内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。可以显示8×4行16×16点阵的汉字.也可完成图形显示.低电压低功耗是其又一显著特点。由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。2.方框图3.模块接口说明管脚号名称LEVEL功能1VSSOV电源地2VDD+5V电源正(3.0V—5.5V)3VO-对比度(亮度)调整4CSH/L模组片选端,高电平有效5SIDH/L串行数据输入端6CLKH/L串行同步时钟:上升延时读取SID数据15PSBLL:串口方式(见注释1)17/RESETH/L复位端,低电平有效(见注释2)19AVDD背光源电压+5V(见注释3)20KVSS背光源负端0V(见注释3)2)并行接口管脚信号如表管脚号管脚名称电平管脚功能描述1VSS0V电源地2VCC3.0+5V电源正3V0-对比度(亮度)调整4RS(CS)H/LRS=“H”,表示DB7——DB0为显示数据RS=“L”,表示DB7——DB0为显示指令数据5R/W(SID)H/LR/W=“H”,E=“H”,数据被读到DB7——DB0R/W=“L”,E=“H→L”,DB7——DB0的数据被写到IR或DR6E(SCLK)H/L使能信号7DB0H/L三态数据线8DB1H/L三态数据线9DB2H/L三态数据线10DB3H/L三态数据线11DB4H/L三态数据线12DB5H/L三态数据线13DB6H/L三态数据线14DB7H/L三态数据线15PSBH/LH:8位或4位并口方式,L:串口方式(见注释1)16NC-空脚17/RESETH/L复位端,低电平有效(见注释2)18VOUT-LCD驱动电压输出端19AVDD背光源正端(+5V)(见注释3)20KVSS背光源负端(见注释3)4.模块主要硬件构成说明(1)控制器接口信号说明:1)RS,R/W的配合选择决定控制界面的4种模式

RSR/W功能说明LLMCU写指令到指令暂存器(IR)LH读出忙标志(BF)及地址记数器(AC)的状态HLMCU写入数据到数据暂存器(DR)HHMCU从数据暂存器(DR)中读出数据E信号如表

E状态执行动作结果高——>低I/O缓冲——>DR配合/W进行写数据或指令高DR——>I/O缓冲配合R进行读数据或指令低/低——>高无动作

忙标志:BFBF标志提供内部工作情况.BF=1表示模块在进行内部操作,此时模块不接受外部指令和数据.BF=0时,模块为准备状态,随时可接受外部指令和数据.利用STATUSRD指令,可以将BF读到DB7总线,从而检验模块之工作状态.字型产生ROM(CGROM)字型产生ROM(CGROM)提供8192个此触发器是用于模块屏幕显示开和关的控制。DFF=1为开显示(DISPLAYON),DDRAM的内容就显示在屏幕上,DFF=0为关显示(DISPLAYOFF)。DFF的状态是指令DISPLAYON/OFF和RST信号控制的。显示数据RAM(DDRAM)模块内部显示数据RAM提供64×2个位元组的空间,最多可控制4行16字(64个字)的中文字型显示,当写入显示数据RAM时,可分别显示CGROM与CGRAM的字型;此模块可显示三种字型,分别是半角英数字型(16*8)、CGRAM字型及CGROM的中文字型,三种字型的选择,由在DDRAM中写入的编码选择,在0000H—0006H的编码中(其代码分别是0000、0002、0004、0006共4个)将选择CGRAM的自定义字型,02H—7FH的编码中将选择半角英数字的字型,至于A1以上的编码将自动的结合下一个位元组,组成两个位元组的编码形成中文字型的编码BIG5(A140—D75F),GB(A1A0-F7FFH)。字型产生RAM(CGRAM)字型产生RAM提供图象定义(造字)功能,可以提供四组16×16点的自定义图象空间,使用者可以将内部字型没有提供的图象字型自行定义到CGRAM中,便可和CGROM中的定义一样地通过DDRAM显示在屏幕中。地址计数器AC地址计数器是用来贮存DDRAM/CGRAM之一的地址,它可由设定指令暂存器来改变,之后只要读取或是写入DDRAM/CGRAM的值时,地址计数器的值就会自动加一,当RS为“0”时而R/W为“1”时,地址计数器的值会被读取到DB6——DB0中。5.指令说明相关指令说明:6.读写时序图下图为读取动作时序图:下图为写入动作时序图:二、液晶初始化【任务实施】main.c文件代码:#include<reg51.h>#include<lcd1602.h>#include<ds1302.h>#include<keyscan.h>#defineucharunsignedcharuchar

hour,minute,second,week,day,month,year;voidmain(){uchari;

Initial_LCD();//液晶初始化

Initial_DS1302();//DS1302初始化

set_rtc();//对时操作

while(1){

keyscan();//按键扫描

if(flag==0)//当标志位为0,允许读取DS1302数据,将数据送入液晶显示

{

TimeToStr();

DateToStr(); LCD_WRITE_COM(0x80+0x40);//液晶第二行显示

for(i=0;i<16;i++) {

LCD_WRITE_DATA(TimeString[i]); delay(5); } LCD_WRITE_COM(0x84);//液晶第一行显示

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

LCD_WRITE_DATA(DateString[i]);

delay(5); } }}}lcd1602.h文件代码:sbitLCD_E=P2^2;//液晶使能端sbitLCD_RS=P2^0;//液晶数据命令选择端sbitLCD_RW=P2^1;//液晶读写选择端voiddelay(unsignedcharz);//延时函数申明voidLCD_WRITE_COM(unsignedcharcom);//液晶写命令函数申明voidLCD_WRITE_DATA(unsignedchardate);//液晶写数据函数申明voidInitial_LCD();//液晶初始化函数申明/*****************************************LCD延时函数,不判断忙,延时机制操作LCD*****************************************/voiddelay(unsignedcharz)//延时函数{

unsignedcharx,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);}/*****************************************LCD写命令函数*****************************************/voidLCD_WRITE_COM(unsignedcharcom)//写命令函数{LCD_RS=0;

LCD_RW=0;LCD_E=1;P0=com;delay(5);LCD_E=0;}/*****************************************LCD写数据函数*****************************************/voidLCD_WRITE_DATA(unsignedchardate)//写数据函数{LCD_RS=1;LCD_RW=0;LCD_E=1;P0=date;delay(5);LCD_E=0;}/*****************************************LCD初始化函数*****************************************/voidInitial_LCD()//液晶初始化函数{LCD_WRITE_COM(0x38);//设置16*2显示,5*7点阵,8位数据接口

LCD_WRITE_COM(0x0c);//设置开显示,不显示光标

LCD_WRITE_COM(0x06);//写一个字符后地址指针加1}ds1302.h文件代码:/*****************************************DS1302读写相关寄存器地址宏定义*****************************************/#defineWRITE_SECOND 0x80#defineWRITE_MINUTE 0x82#defineWRITE_HOUR 0x84#defineWRITE_DAY 0x86#defineWRITE_MONTH 0x88#defineWRITE_YEAR 0x8C#defineWRITE_PROTECT 0x8E#defineWRITE_WEEK 0x8A#defineWRITE_CURRENT0x90#defineREAD_SECOND 0x81#defineREAD_MINUTE 0x83#defineREAD_HOUR 0x85#defineREAD_DAY 0x87#defineREAD_MONTH 0x89#defineREAD_WEEK 0x8B#defineREAD_YEAR 0x8DsbitRST=P1^2;//DS1302片选sbitDIO=P1^1;//DS1302数据信号sbitSCLK=P1^0;//DS1302时钟信号sbitACC_7=ACC^7;//位寻址寄存器定义unsignedchartime_data[7]={10,6,4,17,11,58,59};//10年6周4月17日11时58分59秒unsignedcharwrite_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};//年周月日时分秒写寄存器地址unsignedcharDateString[10];unsignedcharTimeString[16];unsignedcharhour,minute,second,week,day,month,year;voidInitial_DS1302();//DS1302初始化函数申明unsignedcharread_1302(unsignedcharaddr);//DS1302读数据函数申明voidwrite_1302(unsignedcharaddr,unsignedchardate);//DS1302写数据函数申明voidTimeToStr(void);voidDateToStr(void);/*****************************************DS1302写入函数*****************************************/voidwrite_1302(unsignedcharaddr,unsignedchardate)//地址、数据发送子程序{unsignedchari,temp;RST=0;//RST引脚为低,数据传送中止

SCLK=0;//清零时钟总线

RST=1;//RST引脚为高,逻辑控制有效

for(i=8;i>0;i--)//发送地址,循环8次移位

{ SCLK=0; temp=addr; DIO=(bit)(temp&0x01);//每次传送低字节

addr>>=1;//右移一位

SCLK=1;}

for(i=8;i>0;i--)//发送数据

{ SCLK=0; temp=date; DIO=(bit)(temp&0x01); date>>=1; SCLK=1;}RST=0;}unsignedcharread_1302(unsignedcharaddr)//读取数据{unsignedchari,temp,date1,date2;RST=0;SCLK=0;RST=1;

for(i=8;i>0;i--)//循环8次移位,写入要读的寄存器地址

{ SCLK=0; temp=addr; DIO=(bit)(temp&0x01);//每次传送低字节

addr>>=1;//右移一位

SCLK=1;}

for(i=8;i>0;i--){ ACC_7=DIO; SCLK=1; ACC>>=1; SCLK=0;}RST=0;date1=ACC;date2=date1/16;//数据进制转换

date1=date1%16;//十六进制转十进制

date1=date1+date2*10;return(date1);}/*****************************************设置时间,对时函数*****************************************/voidset_rtc(void){unsignedchari,j;for(i=0;i<7;i++){j=time_data[i]/10;time_data[i]=time_data[i]%10;time_data[i]=time_data[i]+j*16;//拼接成BCD码}write_1302(0x8e,0x00);//去掉写保护

for(i=0;i<7;i++){write_1302(write_add[i],time_data[i]);}write_1302(0x8e,0x80);//防止误操作,加上写保护}

/*****************************************时间和日期转字符串*****************************************/voidDateToStr(void){DateString[0]='2';DateString[1]='0';year=read_1302(0x8d);DateString[2]=year/10+'0';DateString[3]=year%10+'0';DateString[4]='-';month=read_1302(0x89);DateString[5]=month/10+'0';DateString[6]=month%10+'0';DateString[7]='-';day=read_1302(0x87);DateString[8]=day/10+'0';DateString[9]=day%10+'0';}voidTimeToStr(void){week=read_1302(0x8b);TimeString[0]='w';TimeString[1]='e';TimeString[2]='e';TimeString[3]='k';TimeString[5]=':';TimeString[6]=week+'0';hour=read_1302(0x85);TimeString[8]=hour/10+'0';TimeString[9]=hour%10+'0';//分解2位数的十位和个位

TimeString[10]=':';minute=read_1302(0x83);TimeString[11]=minute/10+'0';

TimeString[12]=minute%10+'0';TimeString[13]=':';second=read_1302(0x81);TimeString[14]=second/10+'0';TimeString[15]=second%10+'0';}/*****************************************初始化DS1302,暂停标志位CH置0,启动DS1302*****************************************/voidInitial_DS1302(){write_1302(WRITE_SECOND,read_1302(READ_SECOND)&0x7f);//把秒寄存器的暂停标志位CH置0,启动DS1302,为1的话,暂停}keyscan.h文件代码:sbitkey0=P3^2;//调时sbitkey1=P3^3;//增大sbitkey2=P3^4;//减小unsignedcharhour,minute,second,week,day,month,year;unsignedcharnum,flag;/*****************************************按键扫描子程序*****************************************/voidkeyscan(){if(key0==0)//确认调时按下

{ delay(20); if(key0==0)//调时确实按下

{ while(!key0);//释放

num++;//按下次数记录

switch(num) {case1:flag=1;//修改时间,液晶禁止从DS1302读数据LCD_WRITE_COM(0x0f);//光标开始闪烁LCD_WRITE_COM(0x80+6);//第一次按下,光标定位到年位置break;case2:LCD_WRITE_COM(0x80+9);//第二次按下,光标定位到月位置break;case3:LCD_WRITE_COM(0x80+12);//第三次按下,光标定位到日位置break;case4:LCD_WRITE_COM(0x80+0x40+6);//第四次按下,光标定位星期位置break; case5:LCD_WRITE_COM(0x80+0x40+8);//第五次按下,光标定位到时位置break;case6: LCD_WRITE_COM(0x80+0x40+11);//第六次按下,光标定位到分位置break;case7: LCD_WRITE_COM(0x80+0x40+14);//第七次按下,光标定位到秒位置break;case8: LCD_WRITE_COM(0x0c);//不显示光标 write_1302(WRITE_PROTECT,0x00);//禁止写保护write_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302write_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302write_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302write_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302write_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302write_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302write_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302write_1302(WRITE_PROTECT,0x80);//开写保护flag=0;//时间修改完毕,允许液晶从DS1302读数据num=0;//第八次按下,记录清零break; } }}

if(num!=0){ if(key1==0)//确认增大键按下

{ delay(20); if(key1==0)//增大键确实按下

{ while(!key1);

switch(num) {case1: year++;//调节年if(year==100)year=0; LCD_WRITE_NYR(6,year);LCD_WRITE_COM(0x80+6); break;case2:month++;//调节月if(month==13)month=0; LCD_WRITE_NYR(9,month);LCD_WRITE_COM(0x80+9);break; case3:day++;//调节日if(day==32)day=0; LCD_WRITE_NYR(12,day); LCD_WRITE_COM(0x80+12); break;case4:week++;if(week==8)week=0;LCD_WRITE_WEEK(week);//将调节后的星期送入液晶显示LCD_WRITE_COM(0x80+0x40+6);//光标回到指定处break;case5:hour++;if(hour==24)hour=0;LCD_WRITE_SFM(8,hour);//将调节后的小时送入液晶显示LCD_WRITE_COM(0x80+0x40+8);//光标回到指定处break; case6:minute++;if(minute==60)minute=0;LCD_WRITE_SFM(11,minute);//将调节后的分送入液晶显示LCD_WRITE_COM(0x80+0x40+11);//光标回到指定处break;case7:second++;if(second==60)second=0;LCD_WRITE_SFM(14,second);//将调节后的秒送入液晶显示LCD_WRITE_COM(0x80+0x40+14);//光标回到指定处break;default:break; } } }if(key2==0)//确认减小键按下{delay(20);if(key2==0)//减小键确实按下{while(!key2);switch(num){case1:year--;//调节年if(year==-1)year=99;LCD_WRITE_NYR(6,year);LCD_WRITE_COM(0x80+6);break;case2:month--;//调节月if(month==-1)month=12;LCD_WRITE_NYR(9,month);LCD_WRITE_COM(0x80+9);break;case3:day--;//调节日if(day==-1)day=31;LCD_WRITE_NYR(12,day);LCD_WRITE_COM(0x80+12);break;case4:week--;//调节星期if(week==0)week=7;LCD_WRITE_WEEK(week);LCD_WRITE_COM(0x80+0x40+6);break;case5:hour--;//调节时if(hour==-1)hour=23;LCD_WRITE_SFM(8,hour);LCD_WR

温馨提示

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

评论

0/150

提交评论