多功能万年历设计单片机课程设计Word文档格式.docx
《多功能万年历设计单片机课程设计Word文档格式.docx》由会员分享,可在线阅读,更多相关《多功能万年历设计单片机课程设计Word文档格式.docx(37页珍藏版)》请在冰豆网上搜索。
AT89S52单片机
AT89S52是一种低功耗、高性能CMOS
8位微控制器,具有8K系统可编程Flash
存储器。
使用Atmel公司高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8位CPU和在系统可编程Flash,使得AT89S52在众多嵌入式控制应用系统中得到广泛应用。
这次设计采用的是P0和P2口:
P0口
P0口是一个8位漏极开路的双向I/O口。
作为输出口,每位能驱动8个TTL逻辑电平。
对P0端口写“1”时,引脚用作高阻抗输入。
当访问外部程序和数据存储器时,P0口也被作为低8位地址/数据复用。
在这种模式下,P0不具有内部上拉电阻。
在flash编程时,P0口也用来接收指令字节;
在程序校验时,输出指令字节。
程序校验时,需要外部上拉电阻。
P2口
P2口是一个具有内部上拉电阻的8位双向I/O口,P2输出缓冲器能驱动4个TTL逻辑电平。
对P2端口写“1”时,内部上拉电阻把端口拉高,此时可以作为输入口使用。
作为输入使用时,被外部拉低的引脚由于内部电阻的原因,将输出电流(IIL)。
在访问外部程序存储器或用16位地址读取外部数据存储器(例如执行MOVX@DPTR)时,P2口送出高八位地址。
在这种应用中,P2口使用很强的内部上拉发送1。
在使用8位地址(如MOVX@RI)访问外部数据存储器时,P2口输出P2锁存器的内容。
在flash编程和校验时,P2口也接收高8位地址字节和一些控制信号。
AT89S52引脚图PLCC封装
在DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1和X2是振荡源,外接32.768kHz晶振。
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;
其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc≥2.5V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK始终是输入端。
DS18B20,常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。
测温范围-55℃~+125℃,固有测温误差(注意,不是分辨率,这里之前是错误的)1℃。
工作电源:
3.0~5.5V/DC(可以数据线寄生电源)。
带中文字库的128X64是一种具有4位/8位并行、2线或3线串行多种接口方式,内部含有国标一级、二级简体中文字库的点阵图形液晶显示模块;
其显示分辨率为128×
64,
内置8192个16*16点汉字,和128个16*8点ASCII字符集.利用该模块灵活的接口方式和简单、方便的操作指令,可构成全中文人机交互图形界面。
可以显示8×
4行16×
16点阵的汉字,也可完成图形显示.低电压低功耗是其又一显著特点。
由该模块构成的液晶显示方案与同类型的图形点阵液晶显示模块相比,不论硬件电路结构或显示程序都要简洁得多,且该模块的价格也略低于相同点阵的图形液晶模块。
软件程序:
#include<
reg51.H>
intrins.h>
#defineuintunsignedint
#defineucharunsignedchar
sbitDS1302_CLK=P1^0;
//实时时钟时钟线引脚
sbitDS1302_IO=P1^1;
//实时时钟数据线引脚
sbitDS1302_RST=P1^2;
//实时时钟复位线引脚
sbitDQ=P3^3;
//温度传送数据IO口
sbitACC0=ACC^0;
sbitACC7=ACC^7;
ucharhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year;
//秒,分,时到日,月,年位闪的计数
sbitSet=P1^4;
//模式切换键对应实验板K5
sbitUp=P1^5;
//加法按钮对应实验板K6
sbitDown=P1^6;
//减法按钮对应实验板K7
sbitout=P1^7;
//立刻跳出调整模式按钮对应实验板K8
uchardone,count,temp,up_flag,down_flag;
uchartemp_value,temp1_value;
//temp_value温度值正数部分temp1_value温度值小数部分
ucharTempBuffer[8],week_value[3];
voidshow_time();
//液晶显示程序
//****************************************
//12864液晶显示部分子程序模
sbitrs=P2^0;
sbitrw=P2^1;
sbite=P2^2;
#definelcddataP0
sbitbusy=P0^7;
//lcdbusybit
voidwr_d_lcd(ucharcontent);
voidwr_i_lcd(ucharcontent);
voidclrram_lcd(void);
voidinit_lcd(void);
voidbusy_lcd(void);
voidrev_row_lcd(ucharrow);
voidrev_co_lcd(ucharrow,ucharcol,ucharmode);
voidclr_lcd(void);
voidwr_co_lcd(ucharrow,ucharcol,ucharlcddata1,ucharlcddtta2);
voidwr_row_lcd(ucharrow,char*p);
//**********************************
//液晶初始化
voidinit_lcd(void)
{
wr_i_lcd(0x06);
/*光标的移动方向*/
wr_i_lcd(0x0c);
/*开显示,关游标*/
}
//***********************************
//填充液晶DDRAM全为空格
voidclrram_lcd(void)
wr_i_lcd(0x30);
wr_i_lcd(0x01);
//对液晶写数据
//content为要写入的数据
voidwr_d_lcd(ucharcontent)
busy_lcd();
rs=1;
rw=0;
lcddata=content;
e=1;
;
e=0;
//********************************
//对液晶写指令
//content为要写入的指令代码
//*****************************
voidwr_i_lcd(ucharcontent)
rs=0;
//液晶检测忙状态
//在写入之前必须执行
voidbusy_lcd(void)
lcddata=0xff;
rw=1;
e=1;
while(busy==1);
e=0;
//指定要显示字符的坐标
//*******************************
voidgotoxy(unsignedchary,unsignedcharx)
if(y==1)
wr_i_lcd(0x80|x);
if(y==2)
wr_i_lcd(0x90|x);
if(y==3)
wr_i_lcd((0x80|x)+8);
if(y==4)
wr_i_lcd((0x90|x)+8);
//液晶显示字符串程序
voidprint(uchar*str)
while(*str!
='
\0'
)
{
wr_d_lcd(*str);
str++;
}
//DS1302时钟部分子程序模块
typedefstruct__SYSTEMTIME__
ucharSecond;
ucharMinute;
ucharHour;
ucharWeek;
ucharDay;
ucharMonth;
ucharYear;
ucharDateString[11];
ucharTimeString[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(uchard)
{
uchari;
ACC=d;
for(i=8;
i>
0;
i--)
DS1302_IO=ACC0;
//相当于汇编中的RRC
DS1302_CLK=1;
DS1302_CLK=0;
ACC=ACC>
>
1;
}
//*************************************
//实时时钟读取一字节(内部函数)
ucharDS1302OutputByte(void)
1;
//相当于汇编中的RRC
ACC7=DS1302_IO;
return(ACC);
//**************************************
//ucAddr:
DS1302地址,ucData:
要写的数据
voidWrite1302(ucharucAddr,ucharucDa)
DS1302_RST=0;
DS1302_RST=1;
DS1302InputByte(ucAddr);
//地址,命令
DS1302InputByte(ucDa);
//写1Byte数据
}
//读取DS1302某地址的数据
ucharRead1302(ucharucAddr)
ucharucData;
DS1302InputByte(ucAddr|0x01);
//地址,命令
ucData=DS1302OutputByte();
//读1Byte数据
return(ucData);
//******************************************
//获取时钟芯片的时钟数据到自定义的结构型数组
voidDS1302_GetTime(SYSTEMTIME*Time)
ucharReadValue;
ReadValue=Read1302(DS1302_SECOND);
Time->
Second=((ReadValue&
0x70)>
4)*10+(ReadValue&
0x0F);
//转换为相应的10进制数
ReadValue=Read1302(DS1302_MINUTE);
Minute=((ReadValue&
ReadValue=Read1302(DS1302_HOUR);
Hour=((ReadValue&
ReadValue=Read1302(DS1302_DAY);
Day=((ReadValue&
ReadValue=Read1302(DS1302_WEEK);
Week=((ReadValue&
0x10)>
ReadValue=Read1302(DS1302_MONTH);
Month=((ReadValue&
ReadValue=Read1302(DS1302_YEAR);
Year=((ReadValue&
0xf0)>
//将时间年,月,日,星期数据转换成液
//晶显示字符串,放到数组里DateString[]
voidDateToStr(SYSTEMTIME*Time)
uchartab[]={0XD2,0XBB,0XB6,0XFE,0XC8,0XFD,0XCB,0XC4,0XCE,0XE5,0XC1,0XF9,0XC8,0XD5};
if(hide_year<
2)
{
DateString[0]='
2'
;
DateString[1]='
0'
DateString[2]=Time->
Year/10+'
DateString[3]=Time->
Year%10+'
else
'
DateString[2]='
DateString[3]='
}
DateString[4]='
-'
if(hide_month<
2)
Time->
DateString[5]=Time->
Month/10+'
DateString[6]=Time->
Month%10+'
DateString[5]='
DateString[6]='
DateString[7]='
if(hide_day<
DateString[8]=Time->
Day/10+'
DateString[9]=Time->
Day%10+'
DateString[8]='
DateString[9]='
if(hide_week<
week_value[0]=tab[2*(Time->
Week%10)-2];
//星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
week_value[1]=tab[2*(Time->
Week%10)-1];
week_value[0]='
week_value[1]='
week_value[2]='
Time->
DateString[10]='
//字符串末尾加'
判断结束字符
//将时,分,秒数据转换成液晶
//显示字符放到数组TimeString[]
//*****************************************
voidTimeToStr(SYSTEMTIME*Time)
{if(hide_hour<
TimeString[0]=Time->
Hour/10+'
TimeString[1]=Time->
Hour%10+'
TimeString[0]='
TimeString[1]='
TimeString[2]='
:
'
if(hide_min<
TimeString[3]=Time->
Minute/10+'
TimeString[4]=Time->
Minute%10+'
TimeString[3]='
TimeString[4]='
TimeString[5]='
if(hide_sec<
TimeString[6]=Time->
Second/10+'
TimeString[7]=Time->
Second%10+'
TimeString[6]='
TimeString[7]='
TimeString[8