天津科技大学微机接口原理课程设计.docx
《天津科技大学微机接口原理课程设计.docx》由会员分享,可在线阅读,更多相关《天津科技大学微机接口原理课程设计.docx(26页珍藏版)》请在冰点文库上搜索。
天津科技大学微机接口原理课程设计
2016-2017学年第一学期
《微机原理及接口技术课程设计》
基于C51单片机的万年历系统
学院:
计算机科学与信息工程学院
专业:
软件工程
学号:
141033
姓名:
日期:
2016年12月12日
目录
一、设计要求及目的3
(1)设计要求3
(2)实验目的3
二、实验环境3
三、主要元器件列表3
四、实验原理4
五、程序源代码6
六、总结18
一、设计要求及目的
万年历就是记录一定时间范围内的具体公历与农历日期的年历,方便有需要的人查询使用。
万年只是一种象征,表示时间跨度大,与机械时钟相比,电子万年历具有更高的精确性和直观性,使用寿命长。
因此广泛用于家庭、车站、码头和办公室等公共场所,成为人们日常生活中不可少的必需品。
下面介绍本人自做的一款基于单片机的电子万年历系统,能够实现年、月、日、时、分、秒、温度、星期的显示。
(1)设计要求
1.显示:
能够显示年、月、日、时、分、秒、温度、星期:
调用write_sfm(int,uchar)函数显示时分秒、调用write_nyr(int,uchar)函数显示年月日、调用write_week(week)函数星期数、调用write_temp(int,ReadTemperature())函数显示温度。
2.输入、输出:
能够读取系统时间,并在LM016L显示器显示出数据。
3.中断:
使用voidtimer()interrupt1中断函数,取得并显示日历和时间。
4.定时器、计数器:
在voidinit()函数中进行对定时器、计数器的设置。
5.通信技术:
与DS1302和DS18B20通信,获取时间与温度。
6.报警系统:
使用蜂鸣器。
(2)实验目的
掌握《微机原理及接口技术》课程所学理论知识,通过实践操作,实现对显示器、定时器、计数器、输入设备、输出设备、中断、通信等原理的综合运用。
二、实验环境
Windows10环境下:
KeiluVision4、Proteus7Professional。
三、主要元器件列表
编号
名称
参数
数量
1
单片机
AT89C51
1
2
时钟芯片
DS1302
1
3
温度传感器
DS18B20
1
4
液晶显示器
LM016L
1
表一主要元器件列表
四、实验原理
图一万年历1系统实验原理图及运行结果
图二万年历2系统实验原理图及运行结果
图三万年历2系统实验原理图及运行结果
五、程序源代码
万年历1系统的源码:
#include
#include"DS18B20.H"
#defineuintunsignedint
#defineucharunsignedchar
uchara,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;
//flag用于读取头文件中的温度值,和显示温度值
#defineyh0x80//LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
#defineer0x80+0x40//LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)
//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
sbitrs=P2^7;
sbiten=P2^5;
sbitrw=P2^6;
sbitled=P2^6;//LCD背光开关
//DS1302时钟芯片与C51之间的引脚连接定义
sbitIO=P2^1;
sbitSCLK=P2^0;
sbitRST=P2^2;
sbitACC0=ACC^0;
sbitACC7=ACC^7;
/************************************************************
ACC.O就是ACC的第0位。
Acc可以位寻址。
************************************************************/
//校时按键与C51的引脚连接定义
sbitkey1=P3^2;//设置键
sbitkey2=P3^3;//+键
sbitkey3=P3^4;//-键
sbitbuzzer=P2^4;//蜂鸣器。
通过三极管9012驱动,端口低电平响
/*****************************************************************/
ucharcodetabl[]={"2016-12-14"};//年显示的固定字符
ucharcodetab2[]={"15:
17:
03"};//时间显示的固定字符
voiddelay(uintxms)//延时函数,有参函数
{
uintx,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
write_1602com(ucharcom)//液晶写入指令函数
{
rs=0;//数据/指令选择置为指令
rw=0;//读写选择置为写
P0=com;//送入数据
delay
(1);
en=1;//拉高使能端,为制造有效的下降沿做准备,下降沿写代码
delay
(1);
en=0;//en由高变低,产生下降沿,液晶执行写代码命令
}
write_1602dat(uchardat)//液晶写入数据函数
{
rs=1;//数据/指令选择置为数据
rw=0;//读写选择置为写
P0=dat;//送入数据
delay
(1);
en=1;//en置高电平,为制造下降沿做准备
delay
(1);
en=0;//en由高变低,产生下降沿,液晶执行命令
}
//***液晶初始化函数***
lcd_init()
{
write_1602com(0x38);//设置液晶工作模式:
16*2行显示,5*7点阵,8位数据
write_1602com(0x0c);//开显示不显示光标
write_1602com(0x06);//整屏不移动,光标自动右移
write_1602com(0x01);//清显示
write_1602com(yh+1);//日历显示固定符号从第一行第1个位置之后开始显示
for(a=0;a<14;a++)
{
write_1602dat(tabl[a]);//向液晶屏写日历显示的固定符号部分
//delay(3);
}
write_1602com(er+2);
for(a=0;a<8;a++)
{
write_1602dat(tab2[a]);
//delay(3);
}
}
/******************DS1302有关的子函数*********************/
voidwrite_byte(uchardat)//写一个字节
{
ACC=dat;
RST=1;
for(a=B;a>0;a--)
{
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}
}
ucharread_byte()//读一个字节
{
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return(ACC);
}
voidwrite_1302(ucharadd,uchardat)//向1302芯片写函数,指定写入地址、数据
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0;
}
ucharread_1302(ucharadd)//从1302读数据函数,指定读取数据来源地址
{
uchartemp;
RST=0;
SCLK=0;
RST=1;
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
ucharBCD_Decimal(ucharbcd)//BCD码转十进制函数,输入BCD返回十进制
{
ucharDecimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0f));
}
voidds1302_init()//1302芯片初始化子函数
{
RST=0;
SCLK=0;
write_1302(0x8e,0x00);
write_1302(0x8e,0x80);
}
voidwrite_temp(ucharadd,uchardat)//向LCD写温度数据,并指定显示位置
{
uchargw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(er+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
write_1602dat(0xdf);
write_1602dat(0x43);
}
voidwrite_sfm(ucharadd,uchardat)//向LCD写时分秒
{
uchargw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(er+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
//年月日显示子函数
voidwrite_nyr(ucharadd,uchardat)//写年月日
{
uchargw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(yh+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
voidwrite_week(ucharweek)//写星期数
{
write_1602com(yh+0x0c);
switch(week)
{
case1:
write_1602dat('M');
write_1602dat('O');
write_1602dat('N');
break;
case2:
write_1602dat('T');
write_1602dat('U');
write_1602dat('E');
break;
case3:
write_1602dat('W');
write_1602dat('E');
write_1602dat('D');
break;
case4:
write_1602dat('T');
write_1602dat('H');
write_1602dat('U');
break;
case5:
write_1602dat('F');
write_1602dat('I');
write_1602dat('R');
break;
case6:
write_1602dat('S');
write_1602dat('T');
write_1602dat('A');
break;
case7:
write_1602dat('S');
write_1602dat('U');
write_1602dat('N');
break;
}
}
/***********键盘扫描有关函数************************/
/*
voidkeyscan()
{
{
if(key1==0)
{
delay(9);
if(key1==0)
{
buzzer=0;
delay(20);
buzzer=1;
while(!
key1);
key1n++;
if(key1n==9)
{
key1n=1;
switch(key1n)
{
case1:
TR0=0;
write_1602com(er+0x09);
write_1602com(0x0f);
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x80|temp);
write_1302(0x8e,0x00);
break;
case2:
write_1602com(er+6);
break;
case3:
write_1602com(er+3);
break;
case4:
write_1602com(yh+0x0e);
break;
case5:
write_1602com(yh+0x0a);
break;
case6:
write_1602com(yh+0x07);
break;
case7:
write_1602com(yh+0x04);
break;
case8:
write_1602com(yh+0x0c);
TR0=1;
temp=(miao)/10*16+(miao)%10;
write_1302(0x8e,0x00);
write_1302(0x80,0x00|temp);
write_1302(0x8e,0x80);
break;
}
}
}
}
}
}
*/
voidinit()//定时器、计数器设置函数
{
TMOD=0X11;
TH0=0;
TL0=0;
EA=1;
ET0=1;
TR0=1;
}
voidmain()//主函数
{
lcd_init();//初始化液晶
ds1302_init();//调用DS1302时钟的初始化子函数
init();//调用定时计数器的设置子函数
led=0;//打开LCD背光电源
buzzer=0;
delay(80);
buzzer=1;
/*
while
(1)
{
keyscan();
}
*/
}
voidtimer0()interrupt1//取得并显示日历和时间
{
flag=ReadTemperature();
miao=BCD_Decimal(read_1302(0x81));
fen=BCD_Decimal(read_1302(0x83));
shi=BCD_Decimal(read_1302(0x85));
ri=BCD_Decimal(read_1302(0x87));
yue=BCD_Decimal(read_1302(0x89));
nian=BCD_Decimal(read_1302(0x8d));
week=BCD_Decimal(read_1302(0x8b));
write_temp(35,flag);
write_sfm(8,miao);
write_sfm(5,fen);
write_sfm(2,shi);
write_nyr(9,ri);
write_nyr(6,yue);
write_nyr(3,nian);
write_week(week);
}
万年历2的源码:
#defineucharunsignedchar
#defineuintunsignedint
#defineDQP3_7
#include
uintsec=55;
uintmin=59;
uinthour=23;
uintday=14;
uintmonth=12;
uintyearl=16;
uintyearh=20;
uinttcnt;
uintcursor=0;
uchara=0xff;
ucharcodeSeg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
voiddelay(uintt)
{
uinti;
while(t--)
{for(i=0;i<125;i++);}
}
voidTdelay(unsignedinti)
{
while(i--);
}
voidKdelay()
{
uchari,j;
for(i=100;i>0;i--)
for(j=248;j>0;j--);
}
Init_DS18B20(void)
{
unsignedcharx=0;
DQ=1;
Tdelay(8);
DQ=0;
Tdelay(80);
DQ=1;
Tdelay(14);
Tdelay(20);
}
//读一个字节
ReadOneChar(void)
{
unsignedchari=0;
unsignedchardat=0;
for(i=8;i>0;i--)
{
DQ=0;
dat>>=1;
DQ=1;
if(DQ)
dat|=0x80;
Tdelay(4);
}
return(dat);
}
//写一个字节
WriteOneChar(unsignedchardat)
{
unsignedchari=0;
for(i=8;i>0;i--)
{
DQ=0;
DQ=dat&0x01;
Tdelay(5);
DQ=1;
dat>>=1;
}
}
//读取温度
ReadTemperature(void)
{
unsignedchara=0;
unsignedcharb=0;
unsignedintt=0;
floattt=0;
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0x44);
Init_DS18B20();
WriteOneChar(0xCC);
WriteOneChar(0xBE);
a=ReadOneChar();
b=ReadOneChar();
t=b;
t<<=8;
t=t|a;
tt=t*0.0625;
t=tt*10+0.5;
return(t);
}
voiddisplay(ucharL1,ucharL2,ucharL3,ucharL4,ucharL5,ucharL6,ucharL7,ucharL8,ucharL9,ucharL10,ucharL11,ucharL12,ucharL13,ucharL14,ucharL15,ucharL16)
{
P2=0x7F;P0=L1;delay
(1);//yearh
P2=0xBF;P0=L2;delay
(1);//yearh
if(cursor==6){P2=0xDF|a;P0=L3;delay
(1);}else{P2=0xDF;P0=L3;delay
(1);}//yearl
if(cursor==6){P2=0xEF|a;P0=L4;delay
(1);}else{P2=0xEF;P0=L4;delay
(1);}//yearl
if(cursor==5){P2=0xF7|a;P0=L5;delay
(1);}else{P2=0xF7;P0=L5;delay
(1);}//month
if(cursor==5){P2=0xFB|a;P0=L6;delay
(1);}else{P2=0xFB;P0=L6;delay
(1);}//month
if(cursor==4){P2=0xFD|a;P0=L7;delay
(1);}else{P2=0xFD;P0=L7;delay
(1);}//day
if(cursor==4){P2=0xFE|a;P0=L8;delay
(1);}else{P2=0xFE;P0=L8;delay
(1);}//day
P2=0xFF;
if(cursor==3){P1=0x7F|a;P0=L9;delay
(1);}else{P1=0x7F;P0=L9;delay
(1);}//hour
if(cursor==3){P1=0xBF|a;P0=L10;delay
(1);}else{P1=0xBF;P0=L10;delay
(1);}//hour
if(cursor==2){P1=0xDF|a;P0=L11;delay
(1);}else{P1=0xDF;P0=L11;delay
(1);}//min
if(cursor==2){P1=0xEF|a;P0=L12;delay
(1);}else{P1=0xEF;P0=L12;delay
(1);}//min
if(cursor==1){P1=0xF7|a;P0=L13;delay
(1);}else{P1=0xF7;P0=L13;delay
(1);}//sec
if(cursor==1){P1=0xFB|a;P0=L14;delay
(1);}else{P1=0xFB;P0=L14;delay
(1);}//sec
P1=0xFD;P0=L15;delay
(1);//temp
P1=0xFE;P0=L16;delay
(1);//temp
P1=0xFF;
}
main()
{
uinti;
TMOD=0x02;//设置模式为定时器T0的模式2(8位自动重装计数初值的计数值)
TH0=0x06;//设置计数器初值,靠TH0存储重装的计数值X0=256-250=6
TL0=0x06;
TR0=1;//启动T0
ET0=1;//开启定时器T0中断允许
EA=1;//开启中断总控制
while
(1)
{
if(P3_0==0)
{
Kdelay();
if(P3_0==0)
{
cursor++;
if(cur