单片机课设论文.docx
《单片机课设论文.docx》由会员分享,可在线阅读,更多相关《单片机课设论文.docx(27页珍藏版)》请在冰豆网上搜索。
单片机课设论文
前言
20世纪末,电子技术获得了飞速的发展。
在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高。
同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。
时间对人们来说总是那么宝贵,工作的忙碌性和繁杂性容易使人忘记当前的时间。
忘记了要做的事情,当事情不是很重要的时候,这种遗忘无伤大雅。
但是,一旦重要事情,一时的耽误可能酿成大祸。
例如,许多火灾都是由于人们一时忘记了关闭煤气或是忘记充电时间。
所以有必要制作一个定时系统。
随时提醒这些容易忘记时间的人。
而钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。
诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、定时启闭电路、定时开关烘箱、通断动力设备,甚至各种定时电气的自动启用等等。
所有这些,都是以钟表数字化为基础的。
因此,研究数字钟及扩大其应用,有着非常现实的意义。
随着生活水平的提高,人们越来越追求人性化的事物。
传统的时钟已不能满足人们的需求。
而现代的时钟不仅需要模拟电路技术和数字电路技术而且更需要单片机技术,增加数字钟的功能。
利用软件编程尽量做到硬件电路简单稳定,减小电磁干扰和其他环境干扰,减小因元器件精度不够引起的误差,但是数字钟还是可以改进和提高如选用更精密的元器件。
但与机械式时钟相比已经具有更高的准确性和直观性,且无机械装置,具有更长的使用寿命,因此得到了广泛的使用。
数字钟通过数字电路实现时、分、秒。
数字显示的计时装置,广泛用于个人家庭、车站、码头办公室等公共场所成为人们日常生活中不可少的必需品。
由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度远远超过老式钟表。
多功能数字钟的应用非常普遍。
由单片机作为数字钟的核心控制器,通过它的时钟信号进行实现计时功能,将其时间数据经单片机输出,利用显示器显示出来。
通过键盘可以进行校时、定时等功能。
输出设备显示器可以用液晶显示技术和数码管来显示技术。
1、具有显示功能的定时闹钟整体分析
1.1需求分析
二十世纪末,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。
时间对人们来说总是那么宝贵,工作的忙碌性和繁杂性容易使人忘记当前的时间。
忘记了要做的事情,当事情不是很重要的时候,这种遗忘无伤大雅。
但是,一旦重要事情,一时的耽误可能酿成大祸。
例如,许多火灾都是由于人们一时忘记了关闭煤气或是忘记充电时间等造成的。
而钟表的数字化给人们生产生活带来了极大的方便。
数字钟是通过数字电路实现时,分,秒数字显示的计时装置,广泛用于个人家庭、车站、码头办公室等公共场所,成为人们日常生活中不可少的必需品。
由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表,钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能,诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烤箱、通断动力设备、甚至各种定时电气的自动启用等。
所有这些,都是以钟表数字化为基础的。
因此,研究具有显示功能的定时闹钟,并且以MCS-51单片机为核心,功能强大、价格低廉、低成本,有着非常现实的意义。
1.2应解决的主要问题及达到的技术要求
1.2.1应解决的主要问题
本设计应解决的主要问题有三大方面,即硬件电路设计、软件程序设计和proteus软件仿真三大方面。
其中硬件电路部分又可分为四个模块:
键盘模块、显示模块、计时模块和发声模块。
硬件电路部分致力于低成本、低功耗和易实现性。
软件程序设计部分则应做到代码的精简、准确、易读懂。
最后通过proteus软件实现数字钟的精确计时、校时、闹钟设置和定时报警功能。
1.2.2达到的技术要求
一旦时间到,发出声响,同时继电器启动,可控制家电开启和关闭。
程序执行后工作指示灯LED闪烁,表示程序开始执行,显示“00:
00:
00”,按下列顺序控制:
(1)K1键-----设置现在时间
(2)K2键------设置闹铃时间
(3)K3键------显示闹铃设置的时间
(4)K4键------定时“开始”按键,启动定时。
2、相关硬件的选型设计
2.1单片机型号的选择
通过对多种单片机性能的分析,最终认为AT89C51是最理想的电子时钟开发芯片。
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器,器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,而且它与MCS-51兼容,且具有4K字节可编程序存储器和1000次擦写循环,数据保留时间为10年,是最好的选择。
2.2按键的选择
方案一:
4×4矩阵式键盘。
如果选择此方案,那么在修改时钟或设置闹铃时间时就可以直接从键盘输入,方便、快捷,但程序较为复杂。
方案二:
独立式按键。
如果设置过多按键,将会占用较多I/O口,而且会给布线带来不便,因此,此方案适用于按键较少的情况。
如果选择此方案,由于按键较少,在修改时间或设置闹铃时间时就不能直接输入,只能通过加或减完成,稍为麻烦一些,但其程序简单。
由于并不需要经常修改时间和设置闹铃时间,而且方案二的程序简单,按键少、成本低,因此,选择方案二。
2.3显示器的选择
方案一:
液晶显示器。
如果选择此方案,将会降低系统的功耗,这样就可以用电池供电,便于携带。
但液晶显示器的驱动电路复杂,使用起来有一定的难度。
方案二:
用数码管作为显示器。
数码管的驱动电路简单,使用方便,如果选择了此方案,那么在夜间看时间的时候就不需要有光源,非常方便。
其缺点是功耗较大。
由于数码管使用起来较为方便,在夜间看时间也很方便,因此我选择了方案二。
2.4计时部分的选择
如果使用时钟芯片,系统就不怕掉电且时间精确。
但这种芯片比较贵,况且,设计本系统主要是为了学习单片机程序的编写和调试以及设计硬件电路的一些方法,因此采用软件的方法来计时而没有采用价格较高的时钟芯片。
2.5发音部分的设计
通过三极管放大后驱动蜂鸣器工作,再通过软件这时产生等时时间方波驱动蜂鸣器发出间断嘀声,这样就可以省去硬件振荡电路,降低成本。
2.6显示器驱动电路
由于通过数码管公共的电流较大且避免过多地使用分立元件,采用了一片74LS245来驱动段码,用P3口作位码驱动。
2.7电源的选择
如果是用电池供电,就比较方便携带,但是本系统,采用了数码管作为显示器,功耗较大,需要经常更换电池。
况且,本系统的体积较大,即使使用电池供电也不能随身携带,因此,用电池供电不大合适,所以用5V外部稳压电源来供电。
3、定时闹钟的设计原理和软件设计
3.1系统原理图
图3-1
3.2软件设计
3.3.1主程序部分的设计
程序部分主要采用了程序结构的模块化设计,避免了一些函数的不必要的重复书写,使程序变得简单易懂。
程序在执行时,主程序需要通过调用子函数就可完成相应的功能。
图3-2主程序流程
3.3.2中断定时器的设置
数字电子钟设计中主要使用定时器T0中断ET0,利用ET0中断行计时时间的自增,从而实现计时功能。
AT89C51有两个通用定时/计数器。
两者均可配置为定时器或事件计数器。
另外增加了定时器T0/T1,溢出时T0/T1脚自动翻转的功能选项。
用作“定时器”功能时,每经过一个机器周期,寄存器值加1。
用作“计数器”功能时,寄存器在对应的外部输入管脚T0/T1上每发生一次1到0的跳变时加1。
使用该功能时,外部输入每个机器周期被采样一次。
图3-3中断流程
3.3.3闹钟子函数
闹钟时间的判别主要是通过设定时间与实时时间对逐位对比确定是否进行闹铃。
3.3.4计时函数
计时函数部分,主要是通过单片机定时中断来计时,复产生一次中断标志位flag加1,当flag加满20次为1秒,然后把flag清0把秒存储单元加1。
然后再依次判断分、时。
图3-4
3.3.5时间和闹钟的设置
此部分主要是通过判断cnt在不同值时通过调用加1、减1子函数对时间和闹钟的时、分、秒进行设置。
在闹钟设置时,判断按键S4按下情况,进行闹钟的开启与关闭。
3.3.6程序
//***********************头文件***************************//
#include
#include
//***********************宏定义***************************//
#defineucharunsignedchar
#defineuintunsignedint
//***********************位声明***************************//
sbitkey1=P1^0;
sbitkey2=P1^1;
sbitkey3=P1^2;
sbitkey4=P1^3;
sbitfmq=P2^1;
//*******************数码管显示的数值********************//
ucharcodetable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
//012345
0x82,0xf8,0x80,0x90,0xbf,0x0ff};
//6789-灭
//***********************函数声明***********************//
voidjia();
voidjian();
//*************数组定义,数组内含有8个数值*************//
uchartable1[8],table2[8],table3[8],table4[8];
//*****************时间显示初始值***********************//
ucharshi=12,fen=0,miao=0;
//********************定义全局变量***********************//
ucharshi1,fen1,miao1,shi2,fen2,miao2,shi3,fen3,miao3;
ucharshi4,fen4,miao4;
ucharflag,flag1,wss,cnt,cnt1,alm1,alm2,alm3;
//1秒等时位闪次数校时闹1闹2闹3
uintflag2;
//蜂鸣
//***************延时函数,用于动态扫描数码管**************
voiddelay(uchari)
{ucharx,y;
for(x=i;x>0;x--)
for(y=120;y>0;y--);
}
//***************************初始化函数*********************
voidinit()
{TMOD=0x01;//工作方式1
TH0=0x3c;//定时时间为:
50ms(65536-50000)/256
TL0=0x0b0;//(65536-50000)%256
ET0=1;//打开定时器
EA=1;//开总中断
TR0=1;//启动定时器
}
//***************显示子函数,用于显示时间数值*************
voiddisplay()
{uchari,j;
if(cnt!
=10||wss==0)
{table1[0]=miao%10;//分离秒的个位与十位
table1[1]=miao/10;
}
else
{table1[0]=table1[1]=11;}
if(cnt!
=11||wss==0)
{table1[3]=fen%10;//分离分的个位与十位
table1[4]=fen/10;
}
else
{table1[3]=table1[4]=11;}
if(cnt!
=12||wss==0)
{table1[6]=shi%10;//分离时的个位与十位
table1[7]=shi/10;
}
else
{table1[6]=table1[7]=11;}
table1[2]=table1[5]=10;
j=0x7f;
for(i=0;i<=7;i++)//从秒到时的扫描
{P3=j;
P0=table[table1[i]];//显示数值
delay(10);
j=_cror_(j,1);//循环右移
}
}
//*************显示子函数,用于显示定时1时间************
voiddisplay1()
{uchari,j;
if(alm1==0)
{if(cnt!
=1||wss==0)
{table2[0]=miao1%10;//以下含义同上
table2[1]=miao1/10;
}
else
{table2[0]=table2[1]=11;}
if(cnt!
=2||wss==0)
{table2[3]=fen1%10;
table2[4]=fen1/10;
}
else
{table2[3]=table2[4]=11;}
if(cnt!
=3||wss==0)
{table2[6]=shi1%10;
table2[7]=shi1/10;
}
else
{table2[6]=table2[7]=11;}
}
else
table2[0]=table2[1]=table2[3]=table2[4]=table2[6]=table2[7]=10;
table2[2]=table2[5]=10;
j=0x7f;
for(i=0;i<=7;i++)
{P3=j;
P0=table[table2[i]];
delay(10);
j=_cror_(j,1);
}
}
//**************显示子函数,用于显示定时2时间****************
voiddisplay2()
{uchari,j;
if(alm2==0)
{if(cnt!
=4||wss==0)
{table3[0]=miao2%10;//以下含义同上
table3[1]=miao2/10;
}
else
{table3[0]=table3[1]=11;}
if(cnt!
=5||wss==0)
{table3[3]=fen2%10;
table3[4]=fen2/10;
}
else
{table3[3]=table3[4]=11;}
if(cnt!
=6||wss==0)
{table3[6]=shi2%10;
table3[7]=shi2/10;
}
else
{table3[6]=table3[7]=11;}
}
else
table3[0]=table3[1]=table3[3]=table3[4]=table3[6]=table3[7]=10;
table3[2]=table3[5]=10;
j=0x7f;
for(i=0;i<=7;i++)
{P3=j;
P0=table[table3[i]];
delay(10);
j=_cror_(j,1);
}
}
//*********显示子函数,用于显示定时3时间数值***************//
voiddisplay3()
{uchari,j;
if(alm3==0)
{if(cnt!
=7||wss==0)
{table4[0]=miao3%10;//分离秒的个位与十位
table4[1]=miao3/10;
}
else
{table4[0]=table4[1]=11;}
if(cnt!
=8||wss==0)
{table4[3]=fen3%10;//分离分的个位与十位
table4[4]=fen3/10;
}
else
{table4[3]=table4[4]=11;}
if(cnt!
=9||wss==0)
{table4[6]=shi3%10;//分离时的个位与十位
table4[7]=shi3/10;
}
else
{table4[6]=table4[7]=11;}
}
else
table4[0]=table4[1]=table4[3]=table4[4]=table4[6]=table4[7]=10;
table4[2]=table4[5]=10;
j=0x7f;//从秒到时的扫描
for(i=0;i<=7;i++)
{P3=j;
P0=table[table4[i]];//显示数值
delay(10);
j=_cror_(j,1);//循环右移
}
}
//******************时间子函数************************//
voidshijian()
{if(flag>=20)//判断是否到一秒
{wss=~wss;
flag=0;//到了,则标志位清零
if(cnt1!
=0)
{miao4++;//秒加1
if(miao4>59)//判断秒是否到60s
{miao4=0;//到了,则清零
fen4++;//分加1
if(fen4>59)//以下含义同上
{fen4=0;
shi4++;
if(shi4>23)
shi4=0;
}
}
}
else
{miao++;//秒加1
if(miao>59)//判断秒是否到60s
{miao=0;//到了,则清零
fen++;//分加1
if(fen>59)//以下含义同上
{fen=0;
shi++;
if(shi>23)
shi=0;
}
}
}
}
}
//********************键盘扫描子函数**********************//
voidkey_scan()
{if(key1==0)
{while(!
key1)//防止掉显
{if(cnt==1||cnt==2||cnt==3)
{display1();}
if(cnt==4||cnt==5||cnt==6)
{display2();}
if(cnt==7||cnt==8||cnt==9)
{display3();}
if(cnt==0||cnt==10||cnt==11||cnt==12||cnt==13)
{display();}
}
cnt++;//记下按键key1按下的次数
if(cnt==10&&cnt1==0)
{miao4=miao;
fen4=fen;
shi4=shi;
cnt1++;
}
if(cnt==13)
{cnt=0;
if(cnt1==1)
{miao=miao4;
fen=fen4;
shi=shi4;
}
cnt1=0;
}
}
if(key2==0)//判断key2是否按下
{while(!
key2)//防止掉显
{if(cnt==1||cnt==2||cnt==3)
{display1();}
if(cnt==4||cnt==5||cnt==6)
{display2();}
if(cnt==7||cnt==8||cnt==9)
{display3();}
if(cnt==0||cnt==10||cnt==11||cnt==12||cnt==13)
{display();}
}
jia();
}
if(key3==0)//判断key3是否按下
{while(!
key3)//防止掉显
{if(cnt==1||cnt==2||cnt==3)
{display1();}
if(cnt==4||cnt==5||cnt==6)
{display2();}
if(cnt==7||cnt==8||cnt==9)
{display3();}
if(cnt==0||cnt==10||cnt==11||cnt==12||cnt==13)
{display();}
}
jian();//调用减1子函数
}
if(key4==0)//判断key4是否按下
{while(!
key4)//防止掉
{if(cnt==1||cnt==2||cnt==3)
{alm1=~alm1;
display1();
}
if(cnt==4||cnt==5||cnt==6)
{alm2=~alm2;
display2();
}
if(cnt==7||cnt==8||cnt==9)
{alm3=~alm3;
display3();
}
if(cnt==0||cnt==10||cnt==11||cnt==12||cnt==13)
display();
}
}
}
//************************加1子函数***********************
voidjia()
{if(cnt==1)//判断key1按下的次数是否为1
{miao1++;//是,则秒加1
if(miao1>59)//判断秒是否大于60,是,则秒清零
miao1=0;
}
if(cnt==2)//以下含意同上
{fen1++;
if(fen1>59)
fen1=0;
}
if(cnt==3)
{shi1++;
if(shi1>23)
shi1=0;
}
if(cnt==4)
{miao2++;
if(miao2>59)
miao2=0;
}
if(cnt==5)
{fen2++;
if(fen2>59)
fen2=0;
}
if(cnt==6)
{shi2++;
if(shi2>23)
shi2=0;
}
if(cnt==7)
{miao3++;