基于单片机的电子万年历07届毕业设计.docx
- 文档编号:25074194
- 上传时间:2023-06-04
- 格式:DOCX
- 页数:28
- 大小:175.65KB
基于单片机的电子万年历07届毕业设计.docx
《基于单片机的电子万年历07届毕业设计.docx》由会员分享,可在线阅读,更多相关《基于单片机的电子万年历07届毕业设计.docx(28页珍藏版)》请在冰豆网上搜索。
基于单片机的电子万年历07届毕业设计
具体实现功能:
(1)显示年月日时分秒及星期信息
(2)具有可调整日期和时间功能
(3)与即时时间同步
1.4电路设计最终方案决定
综上各方案所述,对此次作品的方案选定:
采用AT89S52作为主控制系统;DS1302提供时钟;LCD液晶显示屏作为显示。
2系统的硬件设计与实现
2.1电路设计框图
AT89S52
主控制模块
图1系统原理图
图2主控制系统
图3DS1302的引脚图
图4LCD液晶显示屏显示模块
3系统的软件设计
3.1程序流程框图
图5主程序流程图
图6时间调整程序流程图
附录一:
系统电路图
附录二:
系统程序
#include
#include
//#include"LCD1602.h"
//#include"DS1302.h"
#defineuintunsignedint
#defineucharunsignedchar
sbitDS1302_CLK=P1^7;//实时时钟时钟线引脚
sbitDS1302_IO=P1^6;//实时时钟数据线引脚
sbitDS1302_RST=P1^5;//实时时钟复位线引脚
sbitACC0=ACC^0;
sbitACC7=ACC^7;
charhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;//秒,分,时到日,月,年位闪的计数
sbitSet=P2^0;//模式切换键
sbitUp=P2^1;//加法按钮
sbitDown=P2^2;//减法按钮
sbitout=P2^3;//立刻跳出调整模式按钮
chardone,count,temp,flag,up_flag,down_flag;
ucharTempBuffer[5],week_value[2];
voidshow_time();//液晶显示程序
1602液晶显示部分子程序
//PortDefinitionssbitLcdRs=P2^5;
sbitLcdRw=P2^6;
sbitLcdEn=P2^7;
sfrDBPort=0x80;//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口
//内部等待函数
unsignedcharLCD_Wait(void)
{LcdRs=0;
LcdRw=1;
_nop_();
LcdEn=1;
_nop_();
LcdEn=0;
returnDBPort;
}
//向LCD写入命令或数据
#defineLCD_COMMAND0//Command
#defineLCD_DATA1//Data
#defineLCD_CLEAR_SCREEN0x01//清屏
#defineLCD_HOMING0x02//光标返回原点
voidLCD_Write(bitstyle,unsignedcharinput)
{
LcdEn=0;
LcdRs=style;
LcdRw=0;
_nop_();
DBPort=input;
_nop_();//注意顺序
LcdEn=1;
_nop_();//注意顺序
LcdEn=0;
_nop_();LCD_Wait();
}
//设置显示模式
#defineLCD_SHOW0x04//显示开
#defineLCD_HIDE0x00//显示关
#defineLCD_CURSOR0x02//显示光标
#defineLCD_NO_CURSOR0x00//无光标
#defineLCD_FLASH0x01//光标闪动
#defineLCD_NO_FLASH0x00//光标不闪动
voidLCD_SetDisplay(unsignedcharDisplayMode)
{LCD_Write(LCD_COMMAND,0x08|DisplayMode);}
//设置输入模式
#defineLCD_AC_UP0x02
#defineLCD_AC_DOWN0x00//default
#defineLCD_MOVE0x01//画面可平移
#defineLCD_NO_MOVE0x00//default
voidLCD_SetInput(unsignedcharInputMode)
{LCD_Write(LCD_COMMAND,0x04|InputMode);}
//初始化LCD
voidLCD_Initial()
{LcdEn=0;
LCD_Write(LCD_COMMAND,0x38);//8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR);//开启显示,无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);//清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE);//AC递增,画面不动}
//液晶字符输入的位置
voidGotoXY(unsignedcharx,unsignedchary)
{if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}
//将字符输出到液晶显示
voidPrint(unsignedchar*str)
{while(*str!
='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}
//DS1302时钟部分子程序
typedefstruct__SYSTEMTIME__
{
unsignedcharSecond;
unsignedcharMinute;
unsignedcharHour;
unsignedcharWeek;
unsignedcharDay;
unsignedcharMonth;
unsignedcharYear;
unsignedcharDateString[11];
unsignedcharTimeString[9];
}SYSTEMTIME;//定义的时间类型
SYSTEMTIMECurrentTime;
#defineAM(X)X
#definePM(X)(X+12)//转成24小时制
#defineDS1302_SECOND0x80//时钟芯片的寄存器位置,存放时间
#defineDS1302_MINUTE0x82
#defineDS1302_HOUR0x84
#defineDS1302_WEEK0x8A
#defineDS1302_DAY0x86
#defineDS1302_MONTH0x88
#defineDS1302_YEAR0x8C
voidDS1302InputByte(unsignedchard)//实时时钟写入一字节(内部函数)
{unsignedchari;ACC=d;for(i=8;i>0;i--)
{DS1302_IO=ACC0;//相当于汇编中的RRC
DS1302_CLK=1;DS1302_CLK=0;ACC=ACC>>1;}}
unsignedcharDS1302OutputByte(void)//实时时钟读取一字节(内部函数)
{unsignedchari;for(i=8;i>0;i--)
{ACC=ACC>>1;//相当于汇编中的RRC
ACC7=DS1302_IO;DS1302_CLK=1;DS1302_CLK=0;}
return(ACC);}
voidWrite1302(unsignedcharucAddr,unsignedcharucDa)//ucAddr:
DS1302地址,ucData:
要写的数据
{DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr);//地址,命令
DS1302InputByte(ucDa);//写1Byte数据
DS1302_CLK=1;
DS1302_RST=0;
}unsignedcharRead1302(unsignedcharucAddr)//读取DS1302某地址的数据
{unsignedcharucData;
DS1302_RST=0;
DS1302_CLK=0;
DS1302_RST=1;
DS1302InputByte(ucAddr|0x01);//地址,命令
ucData=DS1302OutputByte();//读1Byte数据
DS1302_CLK=1;
DS1302_RST=0;
return(ucData);}
voidDS1302_GetTime(SYSTEMTIME*Time)//获取时钟芯片的时钟数据到自定义的结构型数组
{unsignedcharReadValue;
ReadValue=Read1302(DS1302_SECOND);
Time->Second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_MINUTE);
Time->Minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_HOUR);
Time->Hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_DAY);
Time->Day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_WEEK);
Time->Week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_MONTH);
Time->Month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);
ReadValue=Read1302(DS1302_YEAR);
Time->Year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);}
voidDateToStr(SYSTEMTIME*Time)//将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{if(hide_year<2)//这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为2007/07/22
{Time->DateString[0]='2';
Time->DateString[1]='0';
Time->DateString[2]=Time->Year/10+'0';
Time->DateString[3]=Time->Year%10+'0';}
else{Time->DateString[0]='';Time->DateString[1]='';
Time->DateString[2]='';Time->DateString[3]='';}
Time->DateString[4]='/';
if(hide_month<2)
{Time->DateString[5]=Time->Month/10+'0';
Time->DateString[6]=Time->Month%10+'0';}
else{Time->DateString[5]='';Time->DateString[6]='';}
Time->DateString[7]='/';
if(hide_day<2)
{Time->DateString[8]=Time->Day/10+'0';
Time->DateString[9]=Time->Day%10+'0';}
else{Time->DateString[8]='';Time->DateString[9]='';}
if(hide_week<2){
week_value[0]=Time->Week%10+'0';//星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示}
else{week_value[0]='';}
week_value[1]='\0';
Time->DateString[10]='\0';//字符串末尾加'\0',判断结束字符}
voidTimeToStr(SYSTEMTIME*Time)//将时,分,秒数据转换成液晶显示字符放到数组TimeString[];
{if(hide_hour<2)
{Time->TimeString[0]=Time->Hour/10+'0';
Time->TimeString[1]=Time->Hour%10+'0';}
else{Time->TimeString[0]='';Time->TimeString[1]='';}
Time->TimeString[2]=':
';
if(hide_min<2){Time->TimeString[3]=Time->Minute/10+'0';
Time->TimeString[4]=Time->Minute%10+'0';}
else{Time->TimeString[3]='';Time->TimeString[4]='';}
Time->TimeString[5]=':
';
if(hide_sec<2)
{Time->TimeString[6]=Time->Second/10+'0';
Time->TimeString[7]=Time->Second%10+'0';}
else{Time->TimeString[6]='';Time->TimeString[7]='';}
Time->DateString[8]='\0';}
voidInitial_DS1302(void)//时钟芯片初始化
{unsignedcharSecond=Read1302(DS1302_SECOND);
if(Second&0x80)//判断时钟芯片是否关闭
{Write1302(0x8e,0x00);//写入允许
Write1302(0x8c,0x07);//以下写入初始化时间日期:
07/07/25.星期:
3.时间:
23:
59:
55
Write1302(0x88,0x07);Write1302(0x86,0x25);
Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);
Write1302(0x80,0x55);Write1302(0x8e,0x80);//禁止写入}}
voidDelay1ms(unsignedintcount)
{unsignedinti,j;for(i=0;i /*延时子程序*/ voidmdelay(uintdelay) {uinti; for(;delay>0;delay--) for(i=0;i<62;i++)//1ms延时. } voidoutkey()//跳出调整模式,返回默认显示 { ucharSecond; if(out==0) {mdelay(8); count=0; hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0; Second=Read1302(DS1302_SECOND); Write1302(0x8e,0x00);//写入允许 Write1302(0x80,Second&0x7f); Write1302(0x8E,0x80);//禁止写入 done=0; while(out==0); } } voidUpkey()//升序按键 { Up=1; if(Up==0) mdelay(8); switch(count) { case1: temp=Read1302(DS1302_SECOND);//读取秒数 temp=temp+1;//秒数加1 up_flag=1;//数据调整后更新标志 if((temp&0x7f)>0x59)//超过59秒,清零 temp=0; break; case2: temp=Read1302(DS1302_MINUTE);//读取分数 temp=temp+1;//分数加1 up_flag=1; if(temp>0x59)//超过59分,清零 temp=0; break; case3: temp=Read1302(DS1302_HOUR);//读取小时数 temp=temp+1;//小时数加1 up_flag=1; if(temp>0x23)//超过23小时,清零 temp=0; break; case4: temp=Read1302(DS1302_WEEK);//读取星期数 temp=temp+1;//星期数加1 up_flag=1; if(temp>0x7) temp=1; break; case5: temp=Read1302(DS1302_DAY);//读取日数 temp=temp+1;//日数加1 up_flag=1; if(temp>0x31) temp=1; break; case6: temp=Read1302(DS1302_MONTH);//读取月数 temp=temp+1;//月数加1 up_flag=1; if(temp>0x12) temp=1; break; case7: temp=Read1302(DS1302_YEAR);//读取年数 temp=temp+1;//年数加1 up_flag=1; if(temp>0x85) temp=0; break; default: break;} while(Up==0);}} voidDownkey()//降序按键 { Down=1; if(Down==0) { mdelay(8); switch(count) { case1: temp=Read1302(DS1302_SECOND);//读取秒数 temp=temp-1;//秒数减1 down_flag=1;//数据调整后更新标志 if(temp==0x7f)//小于0秒,返回59秒 temp=0x59; break; case2: temp=Read1302(DS1302_MINUTE);//读取分数 temp=temp-1;//分数减1 down_flag=1; if(temp==-1) temp=0x59;//小于0秒,返回59秒 break; case3: temp=Read1302(DS1302_HOUR);//读取小时数 temp=temp-1;//小时数减1 down_flag=1; if(temp==-1) temp=0x23; break; case4: temp=Read1302(DS1302_WEEK);//读取星期数 temp=temp-1;//星期数减1 down_flag=1; if(temp==0) temp=0x7;; break; case5: temp=Read1302(DS1302_DAY);//读取日数 temp=temp-1;//日数减1 down_flag=1; if(temp==0) temp=31; break; case6: temp=Read1302(DS1302_MONTH);//读取月数 temp=temp-1;//月数减1 down_flag=1; if(temp==0) temp=12; break; case7: temp=Read1302(DS1302_YEAR);//读取年数 temp=temp-1;//年数减1 down_flag=1; if(temp==-1) temp=0x85; break; default: break; } while(Down==0); } } voidSetkey()//模式选择按键 { Set=1; if(Set==0) {mdelay(8); count=count+1;//Setkey按一次,count就加1 done=1;//进入调整模式 while(Set==0); } } voidkeydone()//按键功能执行 {ucharSecond; if(flag==0)//关闭时钟,停止计时 { Write1302(0x8e,0x00);//写入允许 temp=Read1302(0x80); Write1302(0x80,temp|0x80); Write1302(0x8e,0x80);//禁止写入 flag=1; } Setkey();//扫描模式切换按键 switch(count) { case1: do//count=1,调整秒 { out
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 单片机 电子 万年历 07 毕业设计