资源描述
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.中断:使用void timer()interrupt 1中断函数,取得并显示日历和时间。
4.定时器、计数器:在void init()函数中进行对定时器、计数器的设置。
5.通信技术:与DS1302和DS18B20通信,获取时间与温度。
6.报警系统:使用蜂鸣器。
(2)实验目的
掌握《微机原理及接口技术》课程所学理论知识,通过实践操作,实现对显示器、定时器、计数器、输入设备、输出设备、中断、通信等原理的综合运用。
二、实验环境
Windows 10环境下:
Keil uVision4、Proteus 7 Professional。
三、主要元器件列表
编号
名称
参数
数量
1
单片机
AT89C51
1
2
时钟芯片
DS1302
1
3
温度传感器
DS18B20
1
4
液晶显示器
LM016L
1
表一 主要元器件列表
四、实验原理
图一 万年历1系统实验原理图及运行结果
图二 万年历2系统实验原理图及运行结果
图三 万年历2系统实验原理图及运行结果
五、程序源代码
万年历1系统的源码:
#include <reg52.h>
#include "DS18B20.H"
#define uint unsigned int
#define uchar unsigned char
uchar a,miao,shi,fen,ri,yue,nian,week,flag,key1n,temp;
//flag用于读取头文件中的温度值,和显示温度值
#define yh 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)
#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)
//液晶屏的与C51之间的引脚连接定义(显示数据线接C51的P0口)
sbit rs=P2^7;
sbit en=P2^5;
sbit rw=P2^6;
sbit led=P2^6; //LCD背光开关
//DS1302时钟芯片与C51之间的引脚连接定义
sbit IO=P2^1;
sbit SCLK=P2^0;
sbit RST=P2^2;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
/************************************************************
ACC.O就是ACC的第0位。Acc可以位寻址。
************************************************************/
//校时按键与C51的引脚连接定义
sbit key1=P3^2; //设置键
sbit key2=P3^3;// + 键
sbit key3=P3^4;// - 键
sbit buzzer=P2^4;//蜂鸣器。通过三极管9012驱动,端口低电平响
/*****************************************************************/
uchar code tabl [] = {"2016-12-14 "};//年显示的固定字符
uchar code tab2 [] ={"15:17:03"};//时间显示的固定字符
void delay(uint xms)//延时函数,有参函数
{
uint x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
write_1602com(uchar com)//液晶写入指令函数
{
rs=0;//数据/指令选择置为指令
rw=0; //读写选择置为写
P0=com;//送入数据
delay(1);
en=1;//拉高使能端,为制造有效的下降沿做准备,下降沿写代码
delay(1);
en=0;//en由高变低,产生下降沿,液晶执行写代码命令
}
write_1602dat(uchar dat)//液晶写入数据函数
{
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有关的子函数*********************/
void write_byte(uchar dat)//写一个字节
{
ACC=dat;
RST=1;
for(a=B;a>0;a--)
{
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}
}
uchar read_byte()//读一个字节
{
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return (ACC);
}
void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址、数据
{
RST=0;
SCLK=0;
RST=1;
write_byte(add);
write_byte(dat);
SCLK=1;
RST=0;
}
uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址
{
uchar temp;
RST=0;
SCLK=0;
RST=1;
write_byte(add);
temp=read_byte();
SCLK=1;
RST=0;
return(temp);
}
uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD返回十进制
{
uchar Decimal;
Decimal=bcd>>4;
return (Decimal=Decimal*10+(bcd&=0x0f));
}
void ds1302_init()//1302芯片初始化子函数
{
RST=0;
SCLK=0;
write_1302(0x8e,0x00);
write_1302(0x8e,0x80);
}
void write_temp(uchar add,uchar dat)//向LCD写温度数据,并指定显示位置
{
uchar gw,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);
}
void write_sfm(uchar add,uchar dat)//向LCD写时分秒
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(er+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
//年月日显示子函数
void write_nyr(uchar add,uchar dat)//写年月日
{
uchar gw,sw;
gw=dat%10;
sw=dat/10;
write_1602com(yh+add);
write_1602dat(0x30+sw);
write_1602dat(0x30+gw);
}
void write_week(uchar week)//写星期数
{
write_1602com(yh+0x0c);
switch(week)
{
case 1:write_1602dat('M');
write_1602dat('O');
write_1602dat('N');
break;
case 2:write_1602dat('T');
write_1602dat('U');
write_1602dat('E');
break;
case 3:write_1602dat('W');
write_1602dat('E');
write_1602dat('D');
break;
case 4:write_1602dat('T');
write_1602dat('H');
write_1602dat('U');
break;
case 5:write_1602dat('F');
write_1602dat('I');
write_1602dat('R');
break;
case 6:write_1602dat('S');
write_1602dat('T');
write_1602dat('A');
break;
case 7:write_1602dat('S');
write_1602dat('U');
write_1602dat('N');
break;
}
}
/***********键盘扫描有关函数************************/
/*
void keyscan()
{
{
if(key1==0)
{
delay(9);
if(key1==0)
{
buzzer=0;
delay(20);
buzzer=1;
while(!key1);
key1n++;
if(key1n==9)
{
key1n=1;
switch(key1n)
{
case 1:
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;
case 2:write_1602com(er+6);
break;
case 3:write_1602com(er+3);
break;
case 4:write_1602com(yh+0x0e);
break;
case 5:write_1602com(yh+0x0a);
break;
case 6:write_1602com(yh+0x07);
break;
case 7:write_1602com(yh+0x04);
break;
case 8: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;
}
}
}
}
}
}
*/
void init()//定时器、计数器设置函数
{
TMOD=0X11;
TH0=0;
TL0=0;
EA=1;
ET0=1;
TR0=1;
}
void main()//主函数
{
lcd_init(); //初始化液晶
ds1302_init();//调用DS1302时钟的初始化子函数
init();//调用定时计数器的设置子函数
led=0;//打开LCD背光电源
buzzer=0;
delay(80);
buzzer=1;
/*
while(1)
{
keyscan();
}
*/
}
void timer0()interrupt 1//取得并显示日历和时间
{
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 的源码:
#define uchar unsigned char
#define uint unsigned int
#define DQ P3_7
#include<AT89X51.H>
uint sec=55;
uint min=59;
uint hour=23;
uint day=14;
uint month=12;
uint yearl=16;
uint yearh=20;
uint tcnt;
uint cursor=0;
uchar a=0xff;
uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
void delay(uint t)
{
uint i;
while(t--)
{for (i=0;i<125;i++);}
}
void Tdelay(unsigned int i)
{
while(i--);
}
void Kdelay()
{
uchar i,j;
for(i=100;i>0;i--)
for(j=248;j>0;j--);
}
Init_DS18B20(void)
{
unsigned char x=0;
DQ = 1;
Tdelay(8);
DQ = 0;
Tdelay(80);
DQ = 1;
Tdelay(14);
Tdelay(20);
}
//读一个字节
ReadOneChar(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0;
dat>>=1;
DQ = 1;
if(DQ)
dat|=0x80;
Tdelay(4);
}
return(dat);
}
//写一个字节
WriteOneChar(unsigned char dat)
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = dat&0x01;
Tdelay(5);
DQ = 1;
dat>>=1;
}
}
//读取温度
ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
float tt=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);
}
void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,uchar L8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16)
{
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()
{
uint i;
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(cursor>=7){cursor=0;}
}
}
if(P3_1==0)
{
Kdelay();
if(P3_1==0)
{
if(cursor==1){sec++;if(sec==60)sec=0;}
if(cursor==2){min++;if(min==60)min=0;}
if(cursor==3){hour++;if(hour==24)hour=0;}
if(cursor==4){day++;if(day==31)day=0;}
if(cursor==5){month++;if(month==12)month=0;}
if(cursor==6){yearl++;if(yearl==100)yearl=0;}
if(cursor==7){yearh++;if(yearh==30)yearh=20;}
}
}
if(P3_2==0)
{
Kdelay();
if(P3_2==0)
{
if(cursor==1){sec--;}
if(cursor==2){min--;}
if(cursor==3){hour--;}
if(cursor==4){day--;}
if(cursor==5){month--;}
if(cursor==6){yearl--;}
if(cursor==7){yearh--;}
}
}
i=ReadTemperature();
display(Seg[yearh/10],Seg[yearh%10],Seg[yearl/10],Seg[yearl%10],Seg[month/10],Seg[month%10],Seg[day/10],Seg[day%10],Seg[hour/10],Seg[hour%10],Seg[min/10],Seg[min%10],Seg[sec/10],Seg[sec%10],Seg[i/100],Seg[i/10%10]);
}
}
void t0(void)interrupt 1 using 0 //t0的中断程序
{
tcnt++;
if(tcnt==4000)//定时器的定时计数,4000次250us为1秒
{
tcnt=0;
P3_3=~P3_3;
a=~a;
sec++;
if(sec==60)
{
sec=0;
min++;
if(min==60)
{
min=0;
hour++;
if(hour==24)
{
hour=0;
day++;
if(month==2&&((yearl==0&&yearh%4==0)||(yearl!=0&&yearl%4==0))&&day==30)day=1;
else if(month==2&&day==29)day=1;
else if((month==4||month==6||month==9||month==11)&&day==31)day=1;
else if(day==32)day=1;
if(day==1)
{
month++;
if(month==13)
{
month=1;
yearl++;
if(yearl==100)
{
yearl=0;
yearh++;
if(yearh==100)
{
yearh=20;
}
}
}
}
}
}
}
}
}
六、总结
本系统以AT89C51单片机为控制核心,通过与DS1302与DS18B20通信获取实时时间和实时环境温度。并将得到的数据通过液晶显示器显示出来,同时通过相应的按键可以进行时间调整。系统总共包括五部分模块:显示模块、时钟模块、实施环境温度采集模块、报警模块、设置模块。较为充分、合理地运用课堂所学知识,将理论用于实践开发中。目 录
第一章 总 论 1
一、项目提要 1
二、可行性研究报告编制依据 2
三、综合评价和论证结论 3
四、存在问题与建议 4
第二章 项目背景及必要性 5
一、项目建设背景 5
二、项目区农业产业化经营发展现状 11
三、项目建设的必要性及目的意义 12
第三章 建设条件 15
一、项目区概况 15
二、项目实施的有利条件 17
第四章 建设单位基本情况 19
一、建设单位概况 19
二、研发能力 20
三、财务状况 20
第五章 市场分析与销售方案 21
一、市场分析 21
二、产品生产及销售方案 22
三、销售策略及营销模式 22
四、销售队伍和销售网络建设 23
第六章 项目建设方案 24
一、建设任务和规模 24
二、项目规划和布局 24
三、生产技术方案与工艺流程 25
四、项目建设标准和具体建设内容 26
五、项目实施进度安排 27
第七章 投资估算和资金筹措 28
一、投资估算依据 28
二、项目建设投资估算 28
三、资金来源 29
四、年度投资与资金偿还计划 29
第八章 财务评价 30
一、财务评价的原则 30
二、主要参数的选择 30
三、财务估算 31
四、盈利能力分析 32
五、不确定性分析 33
六、财务评价结论 34
第九章 环境影响评价 35
一、环境影响 35
二、环境保护与治理措施 35
三、环保部门意见 36
第十章 农业产业化经营与农民增收效果评价 37
一、产业化经营 37
二、农民增收 38
三、其它社会影响 38
第十一章 项目组织与管理 40
一、组织机构与职能划分 40
二、项目经营管理模式 42
三、技术培训 42
四、劳动保护与安全卫生 43
第十二章 可行性研究结论与建议 46
一、可行性研究结论 46
二、建议 47
展开阅读全文