基于AT89S51单片机的多功能电子万年历的方案设计书.docx
- 文档编号:9731500
- 上传时间:2023-02-06
- 格式:DOCX
- 页数:38
- 大小:160.39KB
基于AT89S51单片机的多功能电子万年历的方案设计书.docx
《基于AT89S51单片机的多功能电子万年历的方案设计书.docx》由会员分享,可在线阅读,更多相关《基于AT89S51单片机的多功能电子万年历的方案设计书.docx(38页珍藏版)》请在冰豆网上搜索。
基于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()。
WriteOneChar(0xCC)。
//跳过读
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 AT89S51 单片机 多功能 电子 万年历 方案设计