51单片机和DS1302时钟芯片和LCD1602液晶显示的数字时钟.docx
PRoTEUS仿真图:KEILC程序:include<REGX52.H>include"LCD1602.h"include"DS1302.h"voidDelaylms(unsignedintcount)(unsignedinti,j;for(i=0;i<count;i+)for(j=0;j<120;j+);)main()(SYSTEMTIMECurrentTime;1.CDJnitiaIO;lnitial_DS1302();GotoXY(0,0);Print("tianmadianzi");GotoXY(OzI);Print("Time:");while(l)(DS1302_GetTime(&CurrentTime);TimeToStr(StCurrentTime);GotoXY(64);Print(CurrentTimeJimeString);Delaylms(400);)#ifndefLCD_CHAR_1602_2005_4_9ftdefineLCD_CHAR_1602_2005_4_9#include<intrins.h>/PortDefinitionS*sbitLcdRs=P20;sbitLcdRw=P21;sbitLcdEn=P22;sfrDBPort=0×80;Po=OX80,Pl=OX90,P2=0xA0,P3=0xB0.数据端口内部等待函数*unsignedcharLCD_Wait(void)1.cdRs=O;1.cdRw=I;_nop_();1.cdEn=I;_nop_();while(DBPort&0x80);在用PrOteUS仿真时,注意用屏蔽此语句,在调用GOtOXY()时,会进入死循环,可能在写该控制字时,该模块没有返回写入完备命令,即DBPort&0x80=0x80实际硬件时翻开此语句1.cdEn=O;returnDBPort;LCD/*ftdefine LCD_COMMANDftdefine LCD_DATA#define LCD_CLEAR_SCREEN#define LCD HOMING1OxOl0/ Command/ Data /清屏 0x02/光标返回原点voidLCD_Write(bitstyle,unsignedcharinput)1.cdEn=O;1.cdRs=StyIe;1.cdRw=O;_nop_();DBPOrt=input;JIOP_();注意顺序1.cdEn=I;_nop_();注意顺序1.cdEn=O;_nop_();1.CD_Wait();)设置显示模式*#define LCD_SHOW#define LCD_HIDEftdefine LCD,CURSOR#define LCD_NO_CURSOR#define LCD_FLASHftdefine LCD NO FLASH0x04显示开OxOO显示关0x02 显示光标0x00 无光标0x01 光标闪动0x00 光标不闪动voidLCD_SetDisplay(unsignedcharDispIayMode)1.CD_Write(LCD.COMMAND,0x081DispIayMode);)设置输入模式*#define LCD_AC_UP#define LCD_AC_DOWN#define LCD_MOVEftdefine LCD NO MOVE0x02OxOOOxOlOxOO/ default画面可平移/defaultvoidLCD_Setlnput(unsignedcharInputMode)1.CD_Write(LCD.COMMAND,0x041InputMode);移动光标或屏幕*#defineLCD_CURSOR0x02#defineLCD_SCREEN0x08ftdefineLCD_LEFT0x00#defineLCD_RIGHT0x04voidLCD_Move(unsignedcharobject,unsignedchardirection)(if(object=LCD_CURSOR)1.CD_Write(LCD_COMMAND,OxlOIdirection);if(object=LCD_SCREEN)1.CD_Write(LCD_COMMAND,Oxl81direction);)*/初始化LCD*voidLCDJnitiaIO(1.cdEn=O;1.CD_Write(LCD_C。MMAND,0x38);位数据端口,2行显示,5*7点阵1.CD_Write(LCD.COMMAND,0x38);1.CD_SetDisplay(LCD_SHOWLCD_NO_CURSOR);开启显示,无光标1.CD_Write(LCD_COMMANDzLCD_CLEAR_SCREEN);清屏1.CD_Setlnput(LCD_AC_UPLCD_NO_MOVE);Ae递增,画面不动)y*Mt*voidGotoXY(unsignedcharx,unsignedchary)(if(y=O)1.CD_Write(LCD.COMMAND,0x801x);if(y=i)1.CD_Write(LCD_COMMAND,0x80|(x-0x40);)voidPrint(unsignedchar*str)(while(*str!=,0,)(1.CD_Write(LCD.DATA,*str);str+;)*voidLCD_LoadChar(unsignedcharuser8,unsignedcharplace)unsignedchari;LCD_Write(LCD_COMMAND,0x40|(place*8);for(i=0;i<8;i+)1.CD_Write(LCD_DATA,useri);)*/*«*«*#endif#ifndef_REAL_TIMER_DS1302_2003_7_21_#defineREALTIMERDS13022003721sbitDS1302_CLK=P16;sbitDS1302_IO=P17;sbitDS1302_RST=P15;sbitACCO=ACC0;sbitACC7=ACC7;typedefstruct_SYSTEMTIME_实时时钟时钟线引脚实时时钟数据线引脚实时时钟复位线引脚unsignedcharSecond;unsignedcharMinute;unsignedcharHour;unsignedcharWeek;unsignedcharDay;unsignedcharMonth;unsignedcharYear;unsignedcharDateString9;unsignedcharTimeString9;SYSTEMTIME;定义的时间类型ftdefineAM(X)XftdefinePM(X)(×+12)#defineDS1302_SECOND0x80#defineDS1302_MINUTE0x82#defineDS1302_HOUR0x84ftdefineDS1302_WEEK0x8A#defineDS1302_DAY0x86#defineDS1302_MONTH0x88#defineDS1302_YEAR0x8CftdefineDS1302-RAM(X)(0×C0+(X)*2)voidDS1302lnputByte(unsignedchard)(unsignedchari;ACC=d;for(i=8;i>0;i-)/转成24小时制用于计算DS1302_RAM地址的宏实时时钟写入一字节(内部函数)DS1302JO=ACCO;DS1302CLK=1:相当于汇编中的RRCDS1302_CLK=O;ACC=ACC»1;)unsignedcharDS1302OutputByte(void)实时时钟读取一字节(内部函数)(unsignedchari;for(i=8;i>0;i-)(ACC=ACC»1;相当于汇编中的RRCACC7=DS1302JO;DS13O2_CLK=1;DS13O2_CLK=0;)return(ACC);)voidWritel302(unsignedcharucAddrzunsignedcharucDa)ucAddr:DS13O2地址,ucData:要写的数据(DS13O2_RST=0;DS13O2_CLK=0;DS13O2_RST=1;DS13O2lnputByte(ucAddr);/土也址,命令DS13O2lnputByte(ucDa);/写IByte数据DS13O2_CLK=1;DS13O2_RST=0;)unsignedcharReadl302(unsignedcharucAddr)读取DS13O2某地址的数据(unsignedcharucData;DS13O2_RST=0;DS13O2_CLK=0;DS13O2_RST=1;DS13O2lnputByte(ucAddrOxOl);/地址,命令ucData=DS1302OutputByte();/读IByte数据DS13O2_CLK=1;DS13O2_RST=O;return(ucData);)voidDS1302_SetProtect(bitflag)是否写保护(讦(flag)Writel302(0x8E,0xl0);elseWritel302(0x8E,0x00);/设置时间函数)voidDS13O2_SetTime(unsignedcharAddress,unsignedcharValue)(DS1302_SetProtect(0);Writel302(Address,(Value10)<<4(Value%10);)voidDS13O2_GetTime(SYSTEMTIME*Time)(unsignedcharReadVaIue;ReadVaIue=Readl302(DS1302_SECOND);Time->Second=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);ReadVaIue=Readl302(DS1302_MINUTE);Time->Minute=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);ReadVaIue=Readl302(DS1302_HOUR);Time->Hour=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);ReadVaIue=Readl302(DS1302_DAY);Time->Day=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);ReadVaIue=Readl302(DS1302_WEEK);Time->Week=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);ReadVaIue=Readl302(DS1302_MONTH);Time->Month=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);ReadVaIue=Readl302(DS1302_YEAR);Time->Year=(ReadValue&0x70)»4)*10+(ReadValue&OxOF);)voidDateToStrISYSTEMTIME*Time)(Time->DateStringO=Time->Year10+,01;Time->DateStringl=Time->Year%10+'0,;Time->DateString2=Time->DateString3=Time->Month10+,0'Time->DateString4=Time->Month%10+'0'Time->DateString5=Time->DateString6=Time->Day10+,01;Time->DateString7=Time->Day%10+'0,;Time->DateString8=,0')voidTimeToStrISYSTEMTIME*Time)(Time->TimeStringO=Time->Hour10+'0'Time->TimeStringl=Time->Hour%10+,0'Time->TimeString2=Time->TimeString3=Time->Minute10+,0'Time->TimeString4=Time->Minute%10+'0'Time->TimeString5=Time->TimeString6=Time->Second10+'0,;Time->TimeString7=Time->Second%10+,0'Time->DateString8=,O')voidlnitial_DS1302(void)(unsignedcharSecond=Readl302(DS1302_SECOND);if(Second&0x80)DS1302-SetTime(DS1302-SECOND,0);)*voidBurstWritel3O2(unsignedchar*pWCIock)往DS1302写入时钟数据(多字节方式)unsignedchari;/控制命令,WP=O,写操作? Oxbe:时钟多字节写命令/8Byte = 7Byte 时钟数据 + IByte 控制Writel302(0x8e,0x00);DS1302_RST=0;DS1302_CLK=0;DS13O2_RST=1;DS1302lnputByte(0xbe);for(i=8;i>0;i-)DS1302lnputByte(*pWCIock);/写IByte数据pWCIock+;)DS1302_CLK=1;DS1302_RST=0;)voidBurstReadl302(unsignedchar*pRCIock)读取DS1302时钟数据(时钟多字节方式)(unsignedchari;DS1302_RST=0;DS1302_CLK=0;DS1302_RST=1;DS1302lnputByte(0xbf);/OXbf:时钟多字节读命令for(i=8;i>0;i-)(*pRCIock=DS1302OutputByte();/读IByte数据pRCIock+;)DS1302_CLK=1;DS1302_RST=0;voidDS1302_TimeStop(bitflag)/是否将时钟停顿(unsignedcharData;Data=Readl302(DS1302_SECOND);DS1302_SetProtect(0);讦(flag)Writel302(DS1302-SECONDzData10x80);elseWritel302(DS1302-SECONDzData&0x7F);)*/#endif