单片机三级项目报告.docx
《单片机三级项目报告.docx》由会员分享,可在线阅读,更多相关《单片机三级项目报告.docx(37页珍藏版)》请在冰豆网上搜索。
单片机三级项目报告
单片机三级项目报告
基于单片机的智能电子钟系统仿真设计
DesignandSimulationOfElectronicClock
BasedonSingle-chipSystem
教务处
2015年10月
关键词:
89c51单片机、闹钟报警、Proteus、DS1302、时钟
前言
本三级项目要求基于MCS-51系列单片机利用Protues软件仿真设计一个具有时间显示、按键调时、闹钟报警、温度测量等功能的电子钟系统。
我们对电子钟的开发手段进行了分析,最终决定采用51系列单片机技术实现多功能智能电子钟系统,这种实现方法的优点是电路简单、性能可靠、实时性好、时间精确、操作简单、编程容易。
我们利用Proteus软件进行仿真设计,这样不用制作实际电路便可以得出结果,便于检验电路及软件正确性,可以为以后制作实际电路做准备。
另外这样制作出的电子钟系统可以应用到日常工作和生活中,也可以通过改装来提高性能或者进行功能扩充等操作。
该项目预期完成温度实时测量显示、时间实时显示、可设定闹钟、可调时、上下午指示、半秒指示等功能。
1、课程设计题目与要求
1.1设计题目
基于单片机的简单电子钟系统仿真设计。
1.2设计要求
要求基于51系列单片机利用Protues软件仿真设计一个具有时间显示、按键调时、闹钟报警、温度测量等功能的电子钟系统,可实现六项基本功能分别如下:
1)时间显示:
显示当前时间:
小时、分钟、秒。
2)温度显示:
显示当前环境温度。
3)上下午指示:
采用两个发光二极管来指示上下午。
4)半秒提示:
采用两个发光二极管,每隔半秒闪烁。
5)调时功能:
采用三个按键(K1-K3)来调整时间,步骤如下:
a)按下K1键,开始调小时,同时2个小时数码管闪烁。
b)按下K2键,小时加;按下K3键,小时减。
c)小时调整好后,再按下K1键,开始调分钟,同时分钟数码管闪烁。
d)按下K2键,分钟加;按下K3键,分钟减。
e)调整好分钟后,再按下K1键,调时结束。
6)闹钟功能:
采用三个按键(K2-K4)来调整闹钟,步骤如下:
a)按下K4键,开始调小时,同时2个小时数码管闪烁。
b)按下K2键,小时加;按下K3键,小时减。
c)小时调整好,再按下K4键,开始调分钟,同时分钟数码管闪烁。
d)按下K2键,分钟加;按下K3键,分钟减。
e)调整好分钟后,再按下K4键,定闹结束。
闹钟定时的时间到后,蜂鸣器/扬声器发出提示音。
用户需按K2-k4键来取消闹钟警告。
2、系统的功能分析与设计
2.1系统的主要功能
利用51单片机内部的定时/计数器、中断系统、以及按键和时钟芯片DS1302、DS18B20温度传感器、LCD1602液晶显示屏等元件,利用Protues软件仿真设计一个具有时间显示、按键调时、闹钟报警、温度测量等功能的电子钟系统。
2.2系统的设计方案
整个系统采用应用广泛的AT89C51作为控制芯片,利用DS1302获取时间,采用DS18B20实现温度的测量,利用LCD1602液晶显示屏显示温度,时间等参数,利用单片机内部的定时器来实现数据的定时刷新。
它的处理过程如下:
首先初始化定时器以及温度传感器和时钟芯片,设定单片机内部的一个定时器为50ms产生一次中断,对时间和温度参数实现周期性刷新,然后读取温度,将温度值与设置的闹钟值等参数进行比较,并做出相应的动作。
然后读取按键值,如果是设置键,则改变标志位,并进入相应项进行设置,若标志位为初始状态,则显示时间及温度参数。
在程序中,定时器采用中断方式工作,在中断服务程序中实现时间获取、温度获取、上下午判断、闹钟报警、以及半秒闪烁等功能。
在主程序中需要对定时器、DS1302、DS18B20、LCD1602进行初始化,然后循环进行按键检测并执行相应的功能。
2.3系统硬件设计
2.3.1原理框图
此设计原理框图如下图所示,此电路包括以下九个部分:
单片机,时钟电路,测温电路,按键电路,LED指示灯,复位电路,晶振电路,显示电路及蜂鸣器。
图2-3-1电子钟系统硬件电路组成框图
2.3.2Proteus电路图设计
我们利用Proteus软件进行电路仿真。
Proteus软件不仅具有其它EDA工具软件的仿真功能,而且还能仿真单片机及外围器件。
是目前比较好用的仿真单片机及外围器件的工具。
下图为我们设计的简单电子时钟的电路仿真图。
图2-3-2Proteus中设计的电子时钟系统原理图
3、系统模块设计
3.1主控模块AT89C51
AT89C51是美国Atmel公司生产的低功耗,高性能CMOS八位单片机。
片内ROM全部采用FLASHROM技术,片内含4KB的可系统编程的Flash只读程序存储器,器件采用Atmel公司的高密度、非易失性存储技术生产,完全兼容Intel公司生产的MCS-51系列单片机的指令系统及引脚。
图3-1-1AT89C51单片机
3.2时钟模块
我们采用DS1302实现时间显示,DS1302是一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。
采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。
芯片引脚及在系统中连接如下图
图3-2-1.DS1302芯片接线图
3.3温度显示模块
此模块我们采用DS18B20温度传感器,它是美国DALLAS公司推出的DS系列数字温度传感器,每一个DSl8B20包括一个唯一的64位长的序号,该序号值存放在DSl8B20内部的ROM(只读存储器)中,开始8位是产品类型编码(DSl8B20编码均为10H),接着的48位是每个器件唯一的序号,最后8位是前面56位的CRC(循环冗余校验)码,DSl8B20中还有用于贮存测得的温度值的两个8位存储器RAM,编号为0号和1号,1号存储器存放温度值的符号,如果温度为负,则1号存储器8位全为1,否则全为0;0号存储器用于存放温度值的补码,LSB(最低位)的1表示0.5,将存储器中的二进制数求补再转换成十进制数并除以2就得到被测温度值(-55º~125º)。
芯片引脚及在系统中连接如下图
图3-3-1DS18B20芯片接线图
3.4复位、指示灯和按键模块
3.4.1复位电路
复位电路主要由型号为10uF的电解电容和220的电阻以及微动开关构成,当开关按下时引脚RST为高电平1,断开时引脚为低电平0。
系统中复位电路连接如下图
图3-4-1复位电路
3.4.2半秒显示和上下午显示电路
指示灯电路主要由四个发光二极管组成,低电平有效,灯的亮灭显示控制端,P3.0口控制上午指示灯,P3.1口控制下午指示灯,P3.6口控制前半秒指示灯,P3.7口控制后半秒指示灯。
由于二极管压降小,承受电流能力弱。
所以加上一个1K的限流电阻,防止二极管被烧坏。
系统中指示灯电路连接如下图
图3-4-2指示灯电路
3.4.3按键电路
时钟、加、减、闹钟键分别接P3.2、P3.3、P3.4、P3.5端,时钟键(K1)选择设置的年、月、日、时、分、秒、星期,闹钟键(K4)对闹钟的定时的时、分、秒进行设置,加键(K2)对选中的项的数据加1,减键(K3)对选中的项的数据减1。
系统中按键电路连接如下图
图3-4-3按键电路
3.5闹钟模块
此模块我们利用扬声器电路为系统闹钟部分的发声部分,采用灌电流的方式,省去了外加驱动的麻烦,同时能够获得更大的驱动功率。
扬声器电路连接如下图
图3-5-1扬声器电路
4、软件设计
4.1主程序设计
在主程序中首先初始化定时器以及时钟芯片和温度传感器,设定单片机内部的一个定时器为50ms产生一次中断,以便对时间和温度参数实现周期性刷新。
然后读取按键值,如果是设置键,则改变标志位,并进入相应的项进行设置,若标志位为初始状态,则显示时间及温度参数。
主程序流程图:
图4-1-1系统程序流程图
4.2定时器中断子程序设计
定时器每隔50ms产生一次中断,调用一次中断子程序。
程序首先获取温度、时间、然后将计数器值加1,判断计数器值是否等于10,如果等于则清空计数器并将半秒指示灯取反。
然后判断时间是否等于定时时间,如果等于则使蜂鸣器响,否则关闭蜂鸣器。
然后判断是否为下午,如果为下午,则关闭上午指示灯,打开下午指示灯,否则关闭下午指示灯打开上午指示灯,之后返回主程序。
图4-2-1为中断子程序流程图。
图4-2-1中断子程序流程图
5、系统调试
5.1软件调试
KeilC51是美国KeilSoftware公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
Keil提供了包括C编译器、宏汇编、连接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(μVision)将这些部分组合在一起。
如果使用C语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会使得编程效率大大提高。
KeilC51进行程序编写调试
图5-1-1软件调试图
在软件调试上既没有错误也没有警告,说明我们的程序没有语法错误,逻辑问题需要进行软硬件联调仿真后可知。
5.2Proteus进行系统仿真
在ProteusISIS的Debug菜单中选择Execute,运行程序,系统仿真结果如下图所示:
图5-2-1系统联调仿真结果图
实验结果基本按照预期实现要求,在系统的显示中我们没有利用数码管,而是利用LCD1602进行显示。
虽然LCD1602驱动起来更加麻烦,但它显示的字符多,而且清晰,功能较为齐全,所以我们使用LCD1602进行显示。
6、设计总结
经过几周时间对单片机的知识学习及总结,通过该项目的实施使我们加深对单片机基础知识的理解,并初步具备运用所学知识进行电子钟系统设计的能力,相关标准、手册的查阅能力等,通过团队合作与沟通,培养我们的责任感和团队合作精神,以及项目组织与管理、交流表达能力。
在此过程中我们把项目分成了硬件和软件两大模块分工合作。
硬件部分好入手,电路也较简单,主要涉及的是简单的核心电路以及DS1302、DS18B20、LCD1602电路,连接起来并不复杂。
整个设计过程中遇到的最大问题是软件的编写,软件部分细分为了时钟芯片驱动程序、温度传感器驱动程序、显示模块驱动程序等几大难点,最后把几个模块整合在主程序模块中,最终实现了电子时钟的功能。
在此次过程中,我们将在课程中学到的理论知识运用到实际作品设计、操作中,更进一步地熟悉了单片机芯片的结构及掌握了其工作原理和具体的使用方法与相关元器件的参数计算方法、使用方法,了解了电路的开发和制作及课程设计报告的编写。
加深了对相关理论知识及专业知识的掌握度,增强自身的动手能力,锻炼及提高了理解问题、分析问题、解决问题的能力,更深刻的体会到了理论联系实际的重要性,在整个设计过程中还学到了团体合作精神和分析、解决问题的重要性。
7参考文献
[1]黄正谨.综合电子设计与实践[M].东南大学出版社.2002-3
[2]张毅刚《新编MSC-51单片机应用设计》,哈尔滨工业大学出版社,2003
[3]蔡希彪,曹洪奎; 单片机电子时钟系统的设计与仿真 [J];中国科技信息; 2007年04期
[4]杨欣等,《电子设计从零开始》,清华大学出版社,2005
[5] 胡汉才 单片机原理及其接口技术[M]. 北京:
清华大学出版社 , 1996.89~110.
8程序
#include"reg52.h"
#include"intrins.h"
#include"math.h"
#defineucharunsignedchar
#defineuintunsignedint
#defineLCD_DBP0//LCD1602液晶数据/地址引脚
sbitLCD_RS=P2^0;//LCD1602读
sbitLCD_RW=P2^1;//LCD1602写
sbitLCD_EN=P2^2;//LCD1602使能
sbitDSA=P1^3;//DS18B20温度传感器引脚
//时钟芯片引脚定义
sbitIO=P1^0;
sbitSCLK=P1^1;
sbitRST=P1^2;
//独立按键引脚定义
sbitKey_Chosen=P3^2;
sbitKEY_ADD=P3^3;
sbitKEY_SUB=P3^4;
sbitKey_Alarm=P3^5;
//第0位第八位位操作
sbitACC0=ACC^0;
sbitACC7=ACC^7;
//报警指示引脚定义
sbitRed=P3^6;//半秒指示灯
sbitGreen=P3^7;
sbitled_red=P3^0;//上下午指示灯
sbitled_green=P3^1;
sbitBeep=P1^4;//闹钟
//时钟芯片寄存器定义
#definewrite_second0x80
#definewrite_minute0x82
#definewrite_hour0x84
#definewrite_day0x86
#definewrite_month0x88
#definewrite_week0x8a
#definewrite_year0x8c
enumKEYSTART//按键状态
{
KEY_DOWN,
KEY_UP,
};
enumKEYCONFIG//按键键值
{
KEY_INIT,
KEY_YEAR,
KEY_MONTH,
KEY_DAY,
KEY_WEEK,
KEY_HOUR,
KEY_MINTH,
KEY_ALARH,
KEY_ALARM,
};
/**************************************逻辑变量定义*************************************/
uintTempVal=0,num=0,flag=0;//定义温度值变量
ucharYearData=0,MonthData=0,DayData=0,WeekData=0,HourData=0,MinuteData=0,AlarmH=0,AlarmM=0;//定义闹钟变量
ucharmiao=0,shi=0,fen=0,ri=0,yue=0,nian=0,week=0;//定义时间变量
/**************************************延时函数部分*************************************/
voidDelayus(uintn)//@12MHz晶振,n微秒精确软件延时
{
uinti=0;
for(i=n;i>0;i--)
{
_nop_();
_nop_();
_nop_();
_nop_();
}
}
voidDelayms(intn)//@12MHz晶振,n毫秒精确软件延时
{
inti,j;
for(i=n;i>0;i--)
{
i=12;
j=169;
do
{
while(--j);
}while(--i);
}
}
/************************************LCD1602函数部分**********************************/
voidLCD_wcmd(uchardat)//LCD1602写命令函数
{
Delayus(100);
LCD_RS=0;
LCD_RW=0;
LCD_EN=1;
LCD_DB=dat;
Delayus(100);
LCD_EN=0;
Delayus(100);
}
voidLCD_wdata(uchardat)//LCD1602写数据函数
{
Delayus(100);
LCD_RS=1;
LCD_RW=0;
LCD_EN=1;
LCD_DB=dat;
Delayus(100);
LCD_EN=0;
Delayus(100);
}
voidLCD_disp_char(ucharx,uchary,uchardat)//LCD1602写字符函数X:
0~15Y:
1,2
{
ucharaddress=0;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_wcmd(address);
LCD_wdata(dat);
}
voidLCD_disp_str(ucharx,uchary,uchar*str)//LCD1602写一串字符X:
0~15Y:
1,2
{
ucharaddress=0;
if(y==1)
address=0x80+x;
else
address=0xc0+x;
LCD_wcmd(address);
while(*str!
='\0')
{
LCD_wdata(*str);
str++;
}
}
voidLCD_init(void)//LCD1602液晶初始化
{
Delayus(100);
LCD_wcmd(0x38);
Delayus(100);
LCD_wcmd(0x0c);
Delayus(100);
LCD_wcmd(0x06);
Delayus(100);
LCD_wcmd(0x01);
Delayms
(1);
}
/*********************************温度传感器函数部分*******************************/
voidDS18B20_Delay(uintn)//温度传感器最小单位延时
{
inti=0,j=0;
for(i=n;i>0;i--)
for(j=120;j>0;j--);
}
voidDS18B20_Reset()//温度传感器复位操作
{
inti=0;
DSA=0;
i=103;
while(i>0)
i--;
DSA=1;
i=4;
while(i>0)
i--;
}
bitDS18B20_Readbit()//读温度传感器一位数据信息
{
uinti=0;
bitdat=0;
DSA=0;
i++;
DSA=1;
i++;
i++;
dat=DSA;
i=8;
while(i>0)
i--;
return(dat);
}
ucharDS18B20_Read()//读温度传感器八位数据信息
{
uchari=0,j=0,dat=0;
for(i=1;i<=8;i++)
{
j=DS18B20_Readbit();
dat=(j<<7)|(dat>>1);
}
return(dat);
}
voidDS18B20_Writebyte(uchardat)//写温度传感器八位数据信息
{
uinti=0;
ucharj=0;
bittestb=0;
for(j=1;j<=8;j++)
{
testb=dat&0x01;
dat=dat>>1;
if(testb)//写1
{
DSA=0;
i++;
i++;
DSA=1;
i=8;
while(i>0)
i--;
}
else
{
DSA=0;//写0
i=8;
while(i>0)
i--;
DSA=1;
i++;
i++;
}
}
}
voidDS18B20_Change()//温度转换
{
DS18B20_Reset();
DS18B20_Delay
(1);
DS18B20_Writebyte(0xcc);
DS18B20_Writebyte(0x44);
}
uintDS18B20_Get()//读取温度寄存器转换数据
{
floattt=0;
uchara=0,b=0;
uinttempA=0;
DS18B20_Reset();
DS18B20_Delay
(1);
DS18B20_Writebyte(0xcc);
DS18B20_Writebyte(0xbe);
a=DS18B20_Read();
b=DS18B20_Read();
tempA=b;
tempA<<=8;
tempA=tempA|a;
tt=tempA*0.0625;
tempA=tt*10+0.5;
returntempA;
}
/*********************************DS1302时钟芯片函数部分*******************************/
voidDS1302_wbyte(uchardat)//写时钟芯片八位数据信息
{
uchara=0;
ACC=dat;
RST=1;
for(a=8;a>0;a--)
{
IO=ACC0;
SCLK=0;
SCLK=1;
ACC=ACC>>1;
}
}
ucharDS1302_rbyte()//读时钟芯片八位数据信息
{
uchara=0;
RST=1;
for(a=8;a>0;a--)
{
ACC7=IO;
SCLK=1;
SCLK=0;
ACC=ACC>>1;
}
return(ACC);
}
voidDS1302_write(ucharadd,uchardat)//在时钟芯片指定位置写指定数据
{
RST=0;
SCLK=0;
RST=1;
DS1302_wbyte(add);
DS1302_wbyte(dat);
SCLK=1;
RST=0;
}
ucharDS1302_read(ucharadd)//读取时钟芯片指定地址的数据信息
{
uchartemp;
RST=0;
SCLK=0;
RST=1;
DS1302_wbyte(add);
temp=DS1302_rbyte();
SCLK=1;
RST=0;
return(temp);
}
ucharBCD_Decimal(ucharbcd)//时钟芯片数据转换
{
ucharDecimal;
Decimal=bcd>>4;
return(Decimal=Decimal*10+(bcd&=0x0F));
}
voidDS1302