基于51单片机的万年历设计.docx

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

基于51单片机的万年历设计.docx

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

基于51单片机的万年历设计.docx

基于51单片机的万年历设计

山东工商学院

SHANDONGINSTITUTEOFBUSINESSANDTECHNOLOGY

单片机课程实训

SCMPRACTICALTRAINING

 

实训设计题目

TitleOfTraining

  万年历设计_________________     

分院(系别)

Department

    信息与电子工程学院_____________      

专  业

Speciality

电子信息工程

班级

Class

 2013级1班  

设计作者

Author

XXX

完成日期

Date

2015年12月18日

组别

Team

   09______ 

指导教师

Advisor

XXX____  

第一部分课程设计任务书

一、课程设计题目

万年历的设计

二、课程设计时间

一周

三、实训提交方式

提交实训设计报告

四、设计要求

设计一台液晶显示屏显示的万年历,要求如下。

(1)显示年、月、日、时、分、秒和星期,并有相应的农历显示。

(2)可通过键盘自动调整时间。

(3)具有闹钟功能。

(4)能够显示环境温度,误差小于±1℃。

(5)计时精度:

月误差小于20秒。

第二部分课程设计报告

一、单片机发展概况

单片机诞生于20世纪70年代末,它的发展史大致可分为三个阶段:

第一阶段(1976-1978):

初级单片机微处理阶段。

该时期的单片机具有8位CPU,并行I/O端口、8位时序同步计数器,寻址范围4KB,但是没有串行口。

第二阶段(1978-1982):

高性能单片机微机处理阶段,该时期的单片机具有I/O串行端口,有多级中断处理系统,15位时序同步技术器,RAM、ROM容量加大,寻址范围可达64KB。

第三阶段(1982-至今)位单片机微处理改良型及16位单片机微处理阶段民用电子产品、计算机系统中的部件控制器、智能仪器仪表、工业测控、网络与通信的职能接口、军工领域、办公自动化、集散控制系统、并行多机处理系统和局域网络系统。

二、MCS-51单片机系统简介

MCS-51系列单片机产品都是以Intel公司最早的典型产品8051为核心构成的。

MCS-51单片机由CPU、RAM、ROM、I/O接口、定时器/计数器、中断系统、内部总线等部件组成。

MCS-51以其典型的结构和完善的总线专用寄存器的集中管理,众多的逻辑位操作功能及面向控制的丰富的指令系统,为以后的单片机的发展奠定了基础。

三、设计思想

以AT89C52单片机为核心,外接单片机复位电路,单片机晶振电路,蜂鸣器电路,温度传感器DS18B20,时钟芯片DS1302,按键电路,12864液晶显示电路,通过控制AT89C52单片机的接口来控制蜂鸣器电路,温度传感器DS18B20模块,时钟芯片DS1302模块,按键电路,12864液晶显示模块,使12864液晶能显示阳历年、月、日、时、分、秒和温度及相应的农历时间。

图为硬件系统设计框架

 

四、硬件电路设计

4.1电路原理图

4.2单片机控制模块

AT89C52是一个低电压,高性能CMOS8位单片机,片内含8kbytes的可反复擦写的Flash只读程序存储器和256bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,AT89C52单片机在电子行业中有着广泛的应用。

(1)复位电路

按键手动复位是通过使复位端经电阻与VCC接通而实现的。

(2)时钟振荡电路

基于系统运行速度,采用12MHZ的石英晶振,并使用两个小电容作为微调电容。

4.3温度模块

DS18B20温度传感器具有耐磨耐碰,体积小,使用方便,封装形式多样,适用于各种狭小空间设备数字测温和控制领域。

测温范围-55℃~+125℃,固有测温分辨率0.5℃,工作电源为3~5V。

DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。

采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。

4.4时钟模块

DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。

采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。

4.5液晶显示模块

本系统选择的LCD是AMPIRE128×64的汉字图形型液晶显示模块,可显示汉字及图形。

单片机P1口作为数据输出口,RS,R\W,E分别通过10K的上拉电阻连接到单片机的P0.0,P0.1,P0.2。

VDD接5V电源,VSS接地。

VEE为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。

RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。

R/W为读写信号线,高电平

(1)时进行读操作,低电平(0)时进行写操作。

E(或EN)端为使能(enable)端,下降沿使能。

DB0-DB7为双向数据总线,同时最高位DB7也是忙信号检测位。

BLA、BLK分别为显示器背光灯的正、负极。

4.6按键模块

本系统使用5个button元件分别设置为增加键、减小键、退出键、设置/OK键。

4个按键与一个4个驱动电阻相连,作为整个按键控制功能系统,以触发AT89C52中断为方式使用设置功能。

4.7蜂鸣器模块

本系统采用BUZZER元件和PNP型三极管及电阻组成了蜂鸣器电路。

五、软件设计框图

5.1主程序流程图

万年历的程序主要包括:

按键识别程序、时间设定程序、温度数据采集程序、时间数据采集程序、液晶屏数据显示程序、定时中断程序、阳历转阴历程序、闹钟设定程序、延时子程序等。

5.2温度数据模块设计

5.3时间数据模块设计

 

5.4闹钟设定模块设计

5.5阳历转阴历模块设计

5.6按键设置时间模块设计

 

六、程序源代

/****************************文件包含*************************************/

#include

#include

#include

#include

#include

#include

#include

/*****************************预定义**************************************/

#defineucharunsignedchar

#defineuintunsignedint

/****************************************************************************/

sbitbell=P2^0;//定义蜂鸣器端口

/*****************************************************************************

*名称:

Timer0_Service()inturrupt1

*功能:

中断服务程序

*入口参数:

*出口参数:

*****************************************************************************/

voidTimer0_Service()interrupt1

{

staticucharcount=0;

staticucharflag=0;//记录鸣叫的次数

count=0;

TR0=0;//关闭Timer0

TH0=0x3c;

TL0=0XB0;//延时50ms

TR0=1;//启动Timer0

count++;

if(count==20)//鸣叫1秒

{

bell=~bell;

count=0;

flag++;

}

if(flag==6)

{

flag=0;

TR0=0;//关闭Timer0

}

}

/*****************************************************************************

*名称:

Timer2_Servie()interrupt5

*功能:

中断服务程序

*入口参数:

*出口参数:

*****************************************************************************/

ucharHexNum_Convert(ucharHexNum)/*时间存储个位和十位的方式*/

{

ucharNumtemp;

Numtemp=(HexNum>>4)*10+(HexNum&0X0F);

returnNumtemp;

}

/******************************************************************************

*函数名称:

main()

*功能:

*入口参数:

*出口参数:

********************************************************************************/

voidmain(void)

{

ucharclock_time[6]={0X00,0X59,0X23,0X09,0X04,0X11};//定义时间变量秒分时日月年

ucharalarm_time[2]={10,06};//闹钟设置alarm_time[0]:

分钟alarm_time[1]:

小时

uchartemperature[2];//定义温度变量temperature[0]低8位temperature[1]高8位

Lcd_Initial();//LCD初始化

Clock_Fresh(clock_time);//时间刷新,proteus会调用当前系统时间

Clock_Initial(clock_time);//时钟初试化

/***********************中断初始化***************************/

EA=1;//开总中断

ET0=1;//Timer0开中断

ET2=1;//Timer2开中断

TMOD=0x01;//Timer0工作方式1

RCAP2H=0x3c;

RCAP2L=0xb0;//Timer2延时50ms

while

(1)

{

switch(Key_Scan())

{

caseup_array:

{

Key_Idle();

}

break;

casedown_array:

{

Key_Idle();

}

break;

caseclear_array:

{

Key_Idle();

}

break;

casefunction_array:

{

Key_Function(clock_time,alarm_time);

}

casenull:

{

Clock_Fresh(clock_time);//时间刷新

Lcd_Clock(clock_time);//时间显示

Sensor_Fresh(temperature);//温度更新

Lcd_Temperture(temperature);//温度显示

Calendar_Convert(0,clock_time);

Week_Convert(0,clock_time);

//闹钟报警

if(*alarm_time==HexNum_Convert(*(clock_time+1)))//分钟相吻合

if(*(alarm_time+1)==HexNum_Convert(*(clock_time+2)))//小时相吻合

{

bell=0;

TR2=1;//启动Timer2

}

}

break;

}

}

}

#ifndef_SUN_MOON

#define_SUN_MOON

/*************************************************************************/

#defineucharunsignedchar

#defineuintunsignedint

/********************************************************************************

*名称:

get_moon_day(ucharmonth_p,uinttable_addr)

*功能:

读取数据表中农历的大月或小月,如果大月返回1,小月返回0

*入口参数:

*出口参数:

*********************************************************************************/

bitget_moon_day(ucharmonth_p,uintcalendar_address)

{

uchartemp,temp1;

temp1=(month_p+3)/8;

temp=0x80>>((month_p+3)%8);

temp=year_code[calendar_address+temp1]&temp;

if(temp==0){return(0);}else{return

(1);}

}

/**************************************************************************

*名称:

voidCalendar_Convert(uchar*clock_time)

*功能:

输入BCD的阳历数据,输出BCD阴历数据(1901-2099)

*入口参数:

c_flag:

阳历的世纪标志clock_time:

时钟地址

*出口参数:

*说明:

c_flag=0:

21世纪c_flag=1:

19世纪

*****************************************************************************/

voidCalendar_Convert(ucharc_flag,uchar*clock_time)

{

bitflag_month,flag_year;

ucharyear,month,day,month_point;//定义年月天

uchartemp1,temp2,temp3;

uintcalendar_address;//定义农历地址

uintday_number;

ucharclock_moon[3];//定义阴历

clock_time+=3;//指向日

day=(*clock_time>>4)*10+(*clock_time&0x0f);//BCD转换十进制

clock_time++;//指向月

month=(*clock_time>>4)*10+(*clock_time&0x0f);//BCD转换十进制

clock_time++;//指向年

year=(*clock_time>>4)*10+(*clock_time&0x0f);//BCD转换十进制

//定位日历地址

if(c_flag==0)

calendar_address=(year+99)*3;

else

calendar_address=(year-1)*3;

//春节(正月初一)所在的阳历月份

temp1=year_code[calendar_address+2]&0x60;//Bit6~~Bit5:

春节所在的阳历月份

temp1>>=5;

//春节(正月初一)所在的阳历日期

temp2=year_code[calendar_address+2]&0x1f;//Bit4~~Bit0:

春节所在的阳历日期

//计算春节(正月初一)离当年元旦{1月1日(阳历)}的天数;春节只会在阳历的1月或2月

temp3=temp2-1;

if(temp1!

=1)temp3+=0x1f;

//计算阳历月离当年元旦{1月1日(阳历)}的天数

if(month<10)

{day_number=day_code1[month-1]+day;}

else

{day_number=day_code2[month-10]+day;}

//如果阳历的月大于2且该年的2月为闰月,天数加1

//闰年指的就是阳历有闰日或阴历有闰月的一年;

//阳历四年一闰,在二月加一天,这一天叫做闰日:

//农历三年一闰,五年两闰,十九年七闰,每逢闰年所加的一个月叫做闰月。

if((month<=2)||(year%0x04!

=0))day_number-=1;

//day_number++;

//if((month<2)||(year%0x04!

=0))

//day_number-=1;

//判断阳历日在春节(正月初一)之前还是之后

if(day_number>=temp3)//阳历在春节之后或者春节当日

{

day_number-=temp3;

month=1;

month_point=1;//month_point为月份指向,阳历日在春季前就是春季

flag_month=get_moon_day(month_point,calendar_address);//检查该阴历月的大小大月返回1小月返回0

flag_year=0;

if(flag_month==0){temp1=29;}else{temp1=30;}

//闰月所在的月分

temp2=year_code[calendar_address]&0xf0;

temp2>>=4;//提取高四位假如是0表示没有闰月

while(day_number>=temp1)

{

day_number-=temp1;

month_point++;

if(month==temp2)

{

flag_year=~flag_year;

if(flag_year==0)

month+=1;

}

else

month++;

flag_month=get_moon_day(month_point,calendar_address);

if(flag_month)

temp1=30;

else

temp1=29;

}

day=day_number+1;

}

else//阳历在春节之前使用以下代码进行运算

{

temp3-=day_number;

if(year==0)

{year=0xe3;c_flag=1;}

else

year-=1;

calendar_address-=3;

month=0xc;

temp2=year_code[calendar_address]&0xf0;

temp2>>=4;//提取高4位

flag_year=0;

if(temp2==0)

month_point=12;

else

month_point=13;

//flag_year=0;

flag_month=get_moon_day(month_point,calendar_address);

if(flag_month)

temp1=30;

else

temp1=29;

while(temp3>temp1)

{

temp3-=temp1;

month_point--;

if(flag_year==0)

month-=1;

if(month==temp2)

flag_year=~flag_year;

flag_month=get_moon_day(month_point,calendar_address);

if(flag_month)

temp1=0x1e;

else

temp1=0x1d;

}

day=temp1-temp3+1;

}

//HEX->BCD,运算结束后,把数据转换为BCD数据

temp1=year/10;

temp1<<=4;

clock_moon[2]=temp1|(year%10);

temp1=month/10;

temp1<<=4;

clock_moon[1]=temp1|(month%10);

temp1=day/10;

temp1<<=4;

clock_moon[0]=temp1|

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

当前位置:首页 > 解决方案 > 学习计划

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

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