找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 14947|回复: 2
收起左侧

基于STC11F02E单片机的可设置时间定时器设计

[复制链接]
ID:117761 发表于 2016-6-18 01:28 | 显示全部楼层 |阅读模式
前言

不知不觉上大学已经差不多一年了。这么长时间,我对大学有了更深的了解,深刻的认识到大学的高等教育跟以前的中学小学上课有着很大的不同。大学有着前所未有的自由度,在这自由的时光里,我们就可以在更大程度上支配我们的时间。因此在我的世界观里,大学是一个想学什么就学什么的地方。因为我们在修专业课程的同时,我们也有时间来学习我们的兴趣课程。对于我来说,单片机是我们大三的一门课程。而且在我认识它的过程中,发现它正是我感兴趣的东西。那时候我加入了我们学校航空工程系的飞行器创新实验室。由于我是唯一一个电子类专业的成员,所以我在实验室将来的主要任务就是为旋翼飞行器的主控制单元——单片机编写程序。所以负责这一块的学长希望我能够尽早掌握单片机的原理及应用,早日投入到旋翼机的设计工作中。学长给我手机里传了一本有关单片机学习的资料,在此之前我是从来没有听说过单片机这个名词的。听过学长的简单介绍之后,发现单片机真是一种很有意思的东西,你给它输入程序后,它会按照你的意愿去做,好像是你养的一只高智商宠物一样。你怎么说,它就怎么做,不过我得学会用它能够听得懂的语言——机器语言跟它交流。这就涉及到KEIL软件的使用和C程序设计问题。因此寒假期间我在家先看了一下C程序方面的简单知识,就开始了单片机的学习。寒假期间先后学习了KEIL软件的使用,简单的编程语句,数码管显示原理和数码管动静态显示,键盘检测原理和其作用,A/D,D/A工作原理,中断的概念,单片机内部定时器原理及应用。这时候我是很有成就感,当时唯一想做的就是买一块和那本书配套的单片机学习板,在其上进行编程控制。大一下学期一开学我就网购了一块那本书的配套单片机学习板,买回来之后我就迫不及待的在我的笔记本上装上了相关的软件,要说之前的都是理论学习,现在终于可以开始进行实践编程了。当我第一次把我写好的C程序代码转换为HEX文件,烧写进单片机,板子上的发光管按照我的意愿亮起来时。心中是万分喜悦,突然感觉那些高大上的高科技原来离我们这么近。那几天,除了上课,基本上都坐在电脑前边写C程序代码。看着板子上的器件我都基本上可以控制了,我就又想更进一步自己动手做一些自己的单片机作品。我在看那本书的配套视频里听郭天祥郭老师讲:假如你毕业了到别人公司应聘,人家问你会单片机吗?你说会。那你都做过些什么东西呢?然后你吭哧半天说不出一个作品,人家肯定不会看好你。听了这样的话我做东西的想法更加强烈了。接着我就按着书中提及到的东西买了很多各种各样的洞洞板和其它元件,还有就是各种工具:电烙铁、焊锡、吸锡器之类的。准备做一个最简单单片机最小系统,经历了数次失败之后我终于做好了我的第一个单片机作品——单片机最小系统。后来又做了一个红绿灯模型,这个定时器是我的第三个单片机作品。下面介绍一下这个可设置时间定时器。
一 绪论
1.1设计概述
这是一个基于STC11F02E单片机的可设置时间定时器。以STC11F02E单片机为中心控制单元,外扩两个独立按键作为时间输入设备,一个蜂鸣器和一个LED作为声光示警设备,一个四位共阴数码管配合一个74HC573锁存器执行时间显示任务,一个继电器作为最终执行终端。这个定时器的功能:输入一个小于等于99分钟59秒的时间,开始倒计时,时间到后,继电器闭合。这个定时器可以作为各种电压、电流较小的用电器(电流1A,交流电压120V,直流电压30V)的定时开关。
1.2 设计原因
我高中时候就想做一个定时炸弹,那时候简单的了解了三极管的接法和作用,后来就用一个三极管,一个电子表,一个去了玻璃壳的灯珠(灯丝)设想了一个定时炸弹,经过了好多次失败后,我就没有再做。后来我查资料,才发现三极管的应用远没有那么简单(我对三极管的学习从来没有放弃,这学期刚开始的时候我除了学习单片机,还着重看了有关三极管方面的知识,现在已经对三极管已经有了一定的了解,具体到其内部各区两种载流子的流动)。因此,我就放弃了。在一个月前突然想起了那时候的定时炸弹,一直对它不甘心,如今我学会了单片机的应用,我想验证一下我学习单片机的成果,再说假如成功了,也算实现了我的一个愿望吧。再有就是,广到制造工业、军工领域,狭到玩具、家用电器,定时器应该都能发挥一定作用,所以我这个定时器还是有一定用途的。
二 硬件
2.1 元件介绍
2.1.1蜂鸣器
蜂鸣器分为有源蜂鸣器和无源蜂鸣器两种 (外观如图a、b所示),这里的“源”并不是指电源,而是震荡源。这也是有源蜂鸣器直接接上额定电源(新的蜂鸣器在标签上都有注明)就可连续发声而无源蜂鸣器则和电磁扬声器一样,需要接在音频输出电路中才能发声的原因。
                                                 b639ad6d-59a6-406e-98e9-76c08d8f65aa.png
                                                                            a有源蜂鸣器 b无源蜂鸣器
一般来说,有源蜂鸣器比较贵一些,因为里面多个震荡电路。当然不是有源蜂鸣器就比无源蜂鸣器要好,而是要看应用场合了,有源蜂鸣器内部带震荡源,所以只要一通电就会叫,这种蜂鸣器多适用于提示或报警,而无源蜂鸣器则一般适用于需要发出不同音调声音的地方,即音乐或其它有音调变化的声音。这个定时器上的蜂鸣器是声音示警用的,所以用的是有源蜂鸣器。
2.1.2继电器
继电器是具有隔离功能的自动开关元件,广泛应用于遥控、遥测、通讯、自动控制、机电一体化及电力电子设备中,是最重要的控制元件之一。我觉得它的基本原理无非就是中学时候学的电磁铁的应用。
                                                                da9cb4e7-9e0d-4a8d-873e-da4b01f7a9d0.png 89fa09c9-4d72-4f69-9895-4250b19063c0.png
                                                                                                        实物图
2.1.3 数码管
数码管,我们可能在不只一处见到过它。价格便宜,使用简单,在各种仪表及家电上有着广泛的应用。比如,空调,热水器,万年历,冰箱上都能看到它的影子。它能够显示不同的数字,来告诉我们当前室内温度,现在的时间,饭卡内的余额等等。如下图所示,这是我们经常见到的七段显示数码管。
10792b2c-80ac-4ed3-8b5d-06dbb95c20bc.png
从图中,我们可以看得出来,它可以显示两个个数字,称之为二位数码管,相应的有一位、三位、四位的,这是从位数上分。从其内部构造上分,可为两种:共阴数码管和共阳数码管。
ffad1266-b423-4450-a681-b37e9f723fd0.png
说到内部结构,只有我们了结了其内部结构,我们才能知晓其显示原理。参照上图,其实,从图中a看出,一个八段数码管其实是八个发光二极管并联组合的,这八个发光二极管的连接方式有两种,如图b、c。b图是共阴式连接,c图是共阳式连接。分别对应的实物就是上边所说的共阴数码管和共阳数码管。欲使其显示出某个数字,则只需点亮相应的发光二极管即可。比如说,你想让其显示出阿拉伯数字“3”,就可以将发光二极管a.b.g.c.d点亮即可。数字的显示都是变化的,所以一般来讲数码管大多都需单片机之类的中央控制单元来控制其显示数字。图a中那个一位数码管有十个管脚,那么这十个管脚在数码管内部都是连接的什么呢?通过上边的介绍,我们知道了数码管的内部构造其实是几个LED成数字状排列的,连接方式是并联连接(如图b、c)。在图中,我们看到的线头其实就是数码管引出的管脚。一般来说一位数码管一般都是引出来十个管脚,有两个管脚(gnd)是一样的,就是说两个管脚其实就是一根分出了两支。这个数码管是共阴数码管,因为其公共端标注的是gnd。其他八个管脚就分别是八个发光二极管的阳极,这个gnd叫做数码管的位选端,那八个阳极叫做数码管的段选端。上边说到数码管显示数字的方法,知道内部结构后,具体讲,假如欲使数码管显示一个“3”,那么我们就将位选管脚接负极,段选管脚abgcd都接正极,最终就会在数码管上显示出来一个数字“3”,共阳数码管同理。上边介绍的是一位数码管,二位,多位数码管也都大同小异。只不过比一位数码管多了几个位选端而已。
2.2芯片简介
2.2.1 STC11F02E单片机
单片机有成千上万种,说实话,我目前接触过的单片机型号无非就三种89C52RC、89C51RC、11F02E,其实用起来都一样,都是51内核的单片机。只是某些功能上会略有差异,比如说89C51RC和89C52RC不一样在一个“1”,一个“2”上,这个“1”代表的是其芯片内部储存空间是4K,“2”是8K。后边的“RC”代表STC单片机内部RAM(随机读写存储器)为512B,有的后边不是“RC”而是“RD+”表示内部RAM为1280B。以上两种单片机都是40管脚的。其体积相对都比11F02E要大,本定时器用的是20管脚的单片机11F02E单片机,因为它体积较小,且IO口刚好够用 ,适合在较小的板子上集成,能满足成品体积尽量小的要求。这种单片机只有两组IO口,P1口,P3口。但是其内核和其他两个一样有4组IO口,只是引出来的只有两组罢了。还有之前有一点我不知道的就是,11F02E内部自带时钟电路。我的程序写好后烧进单片机时,惊奇的发现定时器倒计时的速度并不是每秒减一,后来才知道原来我是用的其内部的时钟电路而不是外部晶振。后来在网友的帮助下,才知道像这种自带内部时钟电路的单片机,在用下载器往单片机内烧写程序时需要进行相关设置。
2315d681-1892-41bd-8062-8edfa029af1b.png 54977d4c-90de-4b7e-a1cf-3bc7e0050d99.png
2.2.2 74HC573锁存器
下图是74HC573锁存器的实物图:
57aaa7f7-b4cc-4f38-ae12-634ba862cdd2.png
从图中可以看出,这个芯片是一个20脚的芯片。每个芯片都有每个芯片的作用,就比如单片机可以作为中央控制单元。那么这个锁存器在这个定时器上起一个什么作用呢?“锁存器”三字里边注意这个“锁”字。锁的是什么,锁的是数据。下面看它的引脚图和真值表。
06536d8c-f22d-48a7-8a6a-2db9ed62aaf6.png
总共是二十个管脚,Vcc、GND分别是该芯片的正极和地(负极)管脚,基本上每个芯片上都有这两个管脚。OE的专业术语为三态允许控制端(低电平有效),通常叫做输出允许端。LE叫做锁存控制端。1D~8D为数据输入端,1Q~8Q为数据输出端。
上面,我们了解了锁存器的管脚的定义,下面就介绍其“锁”的作用。真值表中L是低电平,H是高电平,Q0是上次的电平状态,X是任意电平,Z是高阻态,也就是既不是高电平也不是低电平,而它的输出状态与它相连接的其他器件(在这里与锁存器相连接的是单片机的IO口)的电平状态来决定。看真值表,当OE管脚为高电平时LE管脚和D管脚不论是什么电平状态,数据输出管脚Q的电平状态都为高阻态,即锁存器不起任何作用,相当于导线。所以,一般都要使OE端置低电平或直接接地。在OE为低电平的前提下,若LE端为低电平,数据输入端D不论是高还是低,数据输出端Q将保持上次的电平状态。既只要LE端电平保持低电平不曾改变,无论数据输入端的电平状态如何改变,数据输出端Q的电平状态将保持不变,通俗地讲,就是将数据输出端的输出的数据给锁住了不能改变。若想把“数据锁”打开换另外一组输出数据,直接将LE端置高即可。LE置高,置高期间将想要输出的数据直接送入数据输入端D,再将LE置低,数据就又被锁住。此时数据输出端输出的数据就是在“上锁”之前数据输入端输入的数据。该组数据在“上锁(LE为低电平时)”后不随数据输入端输入的数据的改变而改变。综上所述,锁存器的作用就是锁存一个字节(8位(Q1~Q8))的数据。它的应用一般都是为了节约IO口。但在本处的作用并不是为了节约IO 口,而是放大电流,这是锁存器的第二个作用。因为单片机的输出电流是不足以驱动发光二极管,所以在单片机驱动数码管时,需要在单片机和数码管之间加上电流放大器件,像实现单片机电流放大驱动数码管一般都采用三极管,但是为了简单起见我还是选择了锁存器。
2.3 制作过程
“凡事预则立,不预则废”。这句话很有道理,在做每一件事之前,没有充足的准备是不行的。我在焊接这个定时器之前,我也是斟酌再三,先是预算了一下所需元件的种类和数量,确定焊接这些东西所占面积最大可能是多少,确定了使用万用板的规格是5*7cm的。然后将洞洞板上的每一个孔都在纸上排列出来,再将每个元件的管脚布局和数量一一陈列出来,在纸上将各元件进行一次模拟焊接,最终做到跳线的数量尽可能的少。最后确定下最终方案。确定下来之后,就开始焊接。焊接完成后,往单片机里烧写一些简单的试验性程序,上电观察硬件的运行情况。运行不正常,开始查找硬件问题,找到问题后,调整原来方案继续检查。最终硬件没问题后,开始结合最终定形的硬件编写程序。编写程序前,以数码管和单片机的连接情况为依据为数码管显示进行编码,进而确定数码管的显示数组。再在草纸上大致规划一下整个程序的结构框图,使程序模块化,化整为零,使其结构更清晰,减小程序编写的繁琐程度。完成后,开始用KEIL软件编程,每一个模块完成后都要在硬件上试验一下,若有问题,继续调试,运行情况和预想一致后就可以进入下一个模块的编写。最终逐个击破,完成整个程序的编写。现在硬件软件结合,这个板子就成了有“灵魂”的硬件了,而不是一块洞洞板和一个蜂鸣器,两块芯片,一个数码管,两个按钮因为焊锡而粘连在一块的不知名的东西了。它的名字叫做可设置时间定时器。通俗的讲,这是几个各自有自己特殊功能的东西以某种连接方式连接到一起形成的集合。在我告诉它使命之后,它就按照我的命令工作的机器。
2.4 功能操作
它的名字叫做“可设置时间定时器”,顾名思义,它是用来定时的,且定时时间是可以人为设置的。
234c6d19-401c-4f91-a869-271bf7cbb5b4.png
定时器实物图
具体操作方法:插上5V电源后,按下总开关,此时数码管显示如右图所示。 fb1e65a4-3e66-46a3-a0a8-efba695c1436.png 此时,使用者就可以开始设置定时时间了,先按一次换位按键,数码管显示如下图所示。
050f23f9-fe8b-47ca-be2a-bbf1af7070de.png 显示正常,这时就可以开始设置定时时间分钟的十位数字,按下一次加数键,十位数字加一(第四位显示和第一位相同),到数字9后归零。若分钟十位数字设置完毕或不需要设置,直接按换位键选中下一位同第一位那样进行分钟个位数字设置,然后进行秒钟十位数字设置,最后进行最后一位设置,若现在觉得前边三位数字设置有不妥之处,可再次按下换位键便可再次回到第一位设置环节。需要注意的是,四位必须全部设置后才可以开始倒计时,也就是说,在开始倒计时的前一步一定是设置第四位数字环节。一切设置妥当之后,就可以启动倒计时了。启动的方式是:先按住换位键不放,然后按下加数键,此时加数键松开之后,倒计时就开始了。
2.5 电路描述
由于目前我还没有掌握任何一个软件来画电路图,所以我只能把我的电路描述一下了。以单片机为中心,从锁存器开始,锁存器Vcc端和LE端接正极,OE和GND接地,1D接P1.7,2D接P1.6,3D接P1.5,4D接P1.4,5D接P1.3,6D接P1.2,7D接P1.1,8D接P1.0;Q1~Q8分别接四位共阴数码管的8个段选;一位位选接P3.7,二位位选接P3.5,三位位选接P3.2,四位位选接P3.3;继电器(继电器的开关公共端引出2根排针,常闭端引出4根排针,常开端引出1根排针)的线圈端串联一个1K电阻一端接Vcc,另一端接单片机的P3.4,蜂鸣器阳极接Vcc,阴极直接接单片机的P3.0,发光二极管的阳极接Vcc阴极串联一个1K电阻然后接到单片机的P3.0(所以定时器工作时蜂鸣器响和二极管亮一直是同步的)。复位电路和时钟电路(晶振11.0592MHZ,两个起振电容用的是30PF瓷片电容)都是很典型的电路,就不再介绍了。
三 软件
3.1 程序设计流程
3208d21a-d397-4220-966e-5843e15fd2fd.PNG
3.2 C程序代码
#include
sbit key1=P3^0;
sbit key2=P3^1;
sbit go=P3^4;
int numt,fenshi=0,fenge=0,miaoshi=0,miaoge=0,a=0;
unsigned char code table[]={0xfa,0x22,0xb9,0xab,0x63,0xcb,0xdb,0xa2,0xfb,0xeb};
unsigned char code table1[]={0xfe,0x26,0xbd,0xaf,0x67,0xcf,0xdf,0xa6,0xff,0xef};
sbit wela1=P3^7;
sbit wela2=P3^5;
sbit wela3=P3^2;
sbit wela4=P3^3;
void delayms(int xms)//定义延时函数
{
int x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
}
void initial()//定时器初始化
{
TMOD=0x01;
EA=1;
ET0=1;
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
}
void main()
{
initial();
while(1)//等待换位键按下否则数码管保持初始显示----
{
P1=0x01;//初始显示----
wela1=wela2=wela3=wela4=0;
if(key1==0)
{
delayms(10);
if(key1==0)
while(!key1);
goto k0;//开始选中第一位
}
}
//输入设定时间并时时显示
k0: while(1)//选中第一位
{
if(key1==0)//检测是否换下一位
{
delayms(10);
if(key1==0)
while(!key1);
goto k1;
}
wela1=0; wela2=wela4=wela3=1;
P1=table[fenshi];
delayms(5);
wela1=1;wela4=wela3=wela2=0;
P1=0x01;
delayms(5);
if(key2==0)
{
delayms(10);
if(key2==0)
{
fenshi++;//归零
if(fenshi==10)
fenshi=0;
}
while(!key2);
}
} //while终止括号
k1: while(1)//选中第二位
{
if(key1==0)//检测是否换下一位
{
delayms(10);
if(key1==0)
while(!key1);
goto k2;//换下一位
}
wela1=0; wela2=1;wela3=1;wela4=1;
P1=table[fenshi];
delayms(5);
wela2=0;wela3=wela4=wela1=1;
P1=table1[fenge];
delayms(5);
wela1=wela2=1;wela3=wela4=0;
P1=0x01;
if(key2==0)
{
delayms(10);
if(key2==0)
{
fenge++;//归零
if(fenge==10)
fenge=0;
}
while(!key2);
}
}//while终止括号
k2:while(1)//选中第三位
{
if(key1==0)//检测是否换下一位
{
delayms(10);
if(key1==0)
while(!key1);
goto k3;//换下一位
}
wela1=0; wela2=1;wela3=1;wela4=1;
P1=table[fenshi];
delayms(5);
wela2=0;wela3=wela4=wela1=1;
P1=table1[fenge];
delayms(5);
wela1=wela2=1;wela3=0;wela4=1;
P1=table[miaoshi];
delayms(5);
wela1=wela2=wela3=1;wela4=0;
P1=0x01;
if(key2==0)
{
delayms(10);
if(key2==0)
{
miaoshi++;//归零
if(miaoshi==6)
miaoshi=0;
}
while(!key2);
}
}//while终止括号
k3:while(1)//选中第四位
{
if(key1==0)//检测是否做出开始倒计时动作
{
delayms(10);
if(key1==0)
{
while(!key1);
if(key2==0)
{
delayms(15);
if(key2==0)
goto k4;//程序跳到倒计时状态区
}
goto k0;//回去重新设置倒计时时间
}
}
wela1=0; wela2=1;wela3=1;wela4=1;
P1=table[fenshi];
delayms(5);
wela2=0;wela3=wela4=wela1=1;
P1=table1[fenge];
delayms(5);
wela1=wela2=1;wela3=0;wela4=1;
P1=table[miaoshi];
delayms(5);
wela1=wela2=wela3=1;wela4=0;
P1=table[miaoge];
delayms(10);
if(key2==0)
{
delayms(10);
if(key2==0)
{
miaoge++;//归零
if(miaoge==10)
miaoge=0;
}
while(!key2);
}
if(key1==0&&key2==0)
{
delayms(15);
if(key1==0&&key2==0)
while(!key1);
goto k4;
}
}//while终止括号
k4: while(1)//开始进入倒计时状态
{
TR0=1;//开总中断
wela1=0;wela2=wela3=wela4=1;//数码动态显示倒计时分钟秒钟
P1=table[fenshi];
delayms(5);
wela2=0;wela1=wela3=wela4=1;//分钟和秒钟之间的点闪烁
if(numt>=0&&numt<=10)
P1=table1[fenge];
else
P1=table[fenge];
delayms(5);
wela3=0;wela2=wela1=wela4=1;
P1=table[miaoshi];
delayms(5);
wela4=0;wela2=wela1=wela3=1;
P1=table[miaoge];
delayms(5);
if(fenshi==0&&fenge==0&&(miaoshi<1||miaoshi==1&&miaoge==0))//判断是否到达倒计时十秒内
a=1;
if(a==1&&numt%5==0)
key1=0;
else key1=1;
if(a==0&&numt>=0&&numt<=3)//蜂鸣器每秒响一次
key1=0;
if(miaoge==-1)//各位之间进制规则设定
{
miaoge=9;
miaoshi--;
}
if(miaoshi==-1)
{
miaoshi=5;
fenge--;
}
if(fenge==-1)
{
fenge=9;
fenshi--;
}
if(fenshi==0&&fenge==0&&miaoshi==0&&miaoge==0)//判断是否到定时时间
{
go=0;//继电器闭合
while(1);//一切都结束了
}
}
}
void T0time() interrupt 1//中断服务函数
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
numt++;
if(numt==20)
{
numt=0;
miaoge--;
}
}
我觉得程序是整个过程中最困难的地方,在做这个之前我甚至觉得,我还没有这个能力去写这个定时程序。看来我错了,有的东西看起来很难,其实实践过程是“车到山前必有路”,只要有恒心有毅力有信心,那都不是事儿!
四.整个过程遇到的问题和经验总结
1、有关内部自带时钟电路单片机使用外部晶振问题:可以将外部晶振接上,在下载器里选择下次上电使用外部晶振还是内部RC。若选择内部RC,外部晶振是不起作用的,也不会有什么影响。 但请注意,若正在使用内部RC但下载程序时选择了下次启动使用外部晶振,而你又没有外部晶振,那你除非焊上外部晶振,否则你单片机一旦断电,下次再上电就这个单片机就废了。
2、STC11F02E单片机的串口引脚在连接其他部件的同时是烧不进去程序的。
3、STC11F02E单片机的P3.6管脚(同时也是复位管脚)不能接其他部件,接其他部件时候,要置低电平,否则会复位,导致程序不正常执行。在11F02E单片机中复位管脚同时是该单片机P3口的一个IO口管脚,这个特殊的管脚用作复位还是IO口可以在下载器里进行设置如上图。



回复

使用道具 举报

ID:104838 发表于 2016-6-18 05:27 | 显示全部楼层
求原理图
回复

使用道具 举报

ID:72624 发表于 2017-2-11 15:33 | 显示全部楼层
程序里只有两只开关啊,但是你图上是三只,还有一只接在哪里呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表