基于AT89S51单片机的多功能电子万年历的设计.docx

上传人:b****7 文档编号:10139134 上传时间:2023-02-08 格式:DOCX 页数:37 大小:162.94KB
下载 相关 举报
基于AT89S51单片机的多功能电子万年历的设计.docx_第1页
第1页 / 共37页
基于AT89S51单片机的多功能电子万年历的设计.docx_第2页
第2页 / 共37页
基于AT89S51单片机的多功能电子万年历的设计.docx_第3页
第3页 / 共37页
基于AT89S51单片机的多功能电子万年历的设计.docx_第4页
第4页 / 共37页
基于AT89S51单片机的多功能电子万年历的设计.docx_第5页
第5页 / 共37页
点击查看更多>>
下载资源
资源描述

基于AT89S51单片机的多功能电子万年历的设计.docx

《基于AT89S51单片机的多功能电子万年历的设计.docx》由会员分享,可在线阅读,更多相关《基于AT89S51单片机的多功能电子万年历的设计.docx(37页珍藏版)》请在冰豆网上搜索。

基于AT89S51单片机的多功能电子万年历的设计.docx

基于AT89S51单片机的多功能电子万年历的设计

单片机应用系统设计

 

课题:

基于AT89S51单片机的多功能电子万年历的设计

姓名:

班级:

学号:

指导老师:

日期:

 

一、绪论:

现在是一个知识爆炸的新时代,新产品、新技术层出不穷,电子技术的发展更是日新月异。

可以毫不夸张的说,电子技术的应用无处不在,电子技术正在不断地改变我们的生活,改变着我们的世界。

近些年,随着科技的发展和社会的进步,人们对电子万年历的要求也越来越高,传统的电子万年历已不能满足人们的需求。

人们对多功能电子万年历的功能及工作顺序都非常熟悉,但是却很少知道它的内部结构以及工作原理。

由于单片机具有灵活性强、成本低、功耗低、保密性好等特点,还有,单片机是微型计算机的一个重要分枝,单片机是把中央处理器、随机存储器、只读存储器、定时器/计数器、并行接口接口、串行接口、A/D转换器等主要计算机部件,集中在一块集成电路芯片上。

虽然只是一个芯片,但从功能上它就相当于一台完整的微机。

随着科学技术的迅猛发展,单片计集成度高、体积小、运算速度快、功耗低、运行可靠、价格低廉等诸多优点,越来越显现出来。

在日常生活方面,我们使用彩电、录放机、VCD、照相机、手机等等可以说举不胜举。

所以多功能电子万年历一般都以单片机为核心,外加一些外围设备来实现。

由单片机作为多功能电子万年历的核心控制器,通过按键可以进行定时、校时功能。

输出设备显示器可以用液晶显示技术和数码管显示技术。

意义:

电子万年历作为电子类小设计不仅是市场上的宠儿,也是是单片机实验中一个很常用的题目。

因为它的有很好的开放性和可发挥性,因此对作者的要求比较高,不仅考察了对单片机的掌握能力更加强调了对单片机扩展的应用。

而且在操作的设计上要力求简洁,功能上尽量齐全,显示界面也要出色。

所以,电子万年历无论作为比赛题目还是练习题目都是很有价值。

二、系统总体方案设计:

1、共具备两个功能:

(1)显示年月日及分秒信息

(2)具有可调整日期和时间功能。

2、硬件电路的总体框图:

图1总体硬件框图

 

3、所用芯片

图2

 

三、硬件系统设计:

1、硬件原理图:

图3硬件原理

 

2、硬件原理:

在硬件电路中采用P0口作为6位液晶显示电路的驱动接口,这是由于P0口输出驱动电路工作处于开漏状态,它的驱动能力强,故只需外接上拉电阻便可以把LED数码管点亮。

因为共阴的LED数码管它的驱动电流是分开的,在单片机进行动态扫描的时候不会影响彼此的电流,故该电路中的8位LED数码管均用共阳阴极的数码管。

8位LED数码管的位选线分别由相应的P2.0~P2.5控制,而将其相应的段选线并联在一起,由一个8位的I/O口控制,即P0口。

P3口与八个校时按键相连,以成功实现万年历校时的功能。

四、系统软件设计:

1、程序流程框图:

图4程序流程框图

2、年调整程序流程图,月、日调整程序流程图类似。

图5年调整程序流程图

3、源程序代码:

#include

#include

//#include"LCD1602.h"

//#include"DS1302.h"

#defineuintunsignedint

#defineucharunsignedchar

charhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;//秒,分,时到日,月,年位闪的计数

chardone,count,temp,flag,Up_Key_flag,down_flag;

uchartemp_value;//温度值

ucharTempBuffer[5],week_value[2];

sbitDS1302_CLK=P1^7;//实时时钟时钟线引脚

sbitDS1302_IO=P1^6;//实时时钟数据线引脚

sbitDS1302_RST=P1^5;//实时时钟复位线引脚

sbitport01=P3^0;

sbitport02=P3^1;

sbitport03=P3^2;

sbitport04=P3^3;

sbitACC0=ACC^0;

sbitACC7=ACC^7;

sbitSet_Key=P2^0;//模式切换键

sbitUp_Key=P2^1;//加法按钮

sbitDown_Key=P2^2;//减法按钮

sbitout_Key_Key=P2^3;//立刻跳出调整模式按钮

sbitDQ=P1^0;//温度传送数据IO口

voidshow_time();//液晶显示程序

/***********1602液晶显示部分子程序****************/

//PortDefinitions**********************************************************

sbitLcdRs=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_Set_KeyDisplay(unsignedcharDisplayMode)

{

LCD_Write(LCD_COMMAND,0x08|DisplayMode);

}

//设置输入模式************************************************************

#defineLCD_AC_UP_KEY0x02

#defineLCD_AC_DOWN0x00//default

#defineLCD_MOVE0x01//画面可平移

#defineLCD_NO_MOVE0x00//default

voidLCD_Set_KeyInput(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_Set_KeyDisplay(LCD_SHOW|LCD_NO_CURSOR);//开启显示,无光标

LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN);//清屏

LCD_Set_KeyInput(LCD_AC_UP_KEY|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);//禁止写入

}

}

/***********ds18b20子程序*************************/

/***********ds18b20延迟子函数(晶振12MHz)*******/

voiddelay_18B20(unsignedinti)

{

while(i--);

}

/**********ds18b20初始化函数**********************/

voidInit_DS18B20(void)

{

unsignedcharx=0;

DQ=1;//DQ复位

delay_18B20(8);//稍做延时

DQ=0;//单片机将DQ拉低

delay_18B20(80);//精确延时大于480us

DQ=1;//拉高总线

delay_18B20(14);

x=DQ;//稍做延时后如果x=0则初始化成功x=1则初始化失败

delay_18B20(20);

}

/***********ds18b20读一个字节**************/

unsignedcharReadOneChar(void)

{

uchari=0;

uchardat=0;

for(i=8;i>0;i--)

{

DQ=0;//给脉冲信号

dat>>=1;

DQ=1;//给脉冲信号

if(DQ)

dat|=0x80;

delay_18B20(4);

}

return(dat);

}

/*************ds18b20写一个字节****************/

voidWriteOneChar(uchardat)

{

unsignedchari=0;

for(i=8;i>0;i--)

{

DQ=0;

DQ=dat&0x01;

delay_18B20(5);

DQ=1;

dat>>=1;

}

}

/**************读取ds18b20当前温度************/

voidReadTemp(void)

{

unsignedchara=0;

unsignedcharb=0;

unsignedchart=0;

Init_DS18B20();

WriteO

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 面试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1