先前我们介绍了定时器/计数器的概念与作用原理,下面我通过两个应用案例来分别演示定时器和计数器的用法。
第一个案例是用数码管配合定时器中断制作秒表,同理也可以自己改变时间单位制作不同精度的电子钟,修改方式我已经附在代码注释中了。
#include <reg52.h>
unsigned char code Tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C};
unsigned char Dat[]={0,0}; //用数组储存数码管要显示的数字
unsigned char Second,t;void Delay() //为了消影需要延时函数,可以忽略延时带来的定时误差
{unsigned char i;for(i=0;i<50;i++);
}void main()
{EA = 1; //总中断允许ET0 = 1; //允许T0中断TMOD =0x01; //计时器0工作方式1TH0 = -50000/256; //高位赋初值,用表达式减少了计算的麻烦TL0 = -50000%256; //低位赋初值TR0 = 1; //开启计时器0while(1){ //进行数据分割Dat[0]=Second/10; //累计时间的十位存入数组Dat[1]=Second%10; //累计时间的各位存入数组P0=Tab[Dat[0]]; //读取数码管相应的数字段码P1=0xfe; //位选开启十位数码管,注意仿真图,十位接在P1.0上Delay();P1=0xff; //消影P0=Tab[Dat[1]]; //个位同理P1=0xfd;Delay();P1=0xff;}
}void intserv1 (void) interrupt 1 using 1
{TH0= -50000/256; //减法赋值的简写TL0= -50000%256;t++; //记录1s的二十分之一if(t==20) //累积到1s后置零,秒数加1{ //如果要更改秒表的精确程度,修改这里再添加一个用于显示精确位数的数码管即可/*if(t==2) //比如改为t==2,就是每0.1s在数码管显示一次,输出时再加一个用于显示十分位的数码管{t=0; //同时将second的归零值改为100,不过要注意两件事情num++; //一是变量在命名second容易出现语意不明,应改为num加注释说明if(Second>=600) Second=0;}*/ //二是带小数点显示的段码与先前用到的不同,需要重新设置数组t=0;Second++;if(Second>=60) Second=0; //到一分钟后重新开始}
}
仿真效果如下,为了让输出的电平更稳定,笔者采用了74LS245芯片,它是8路同相三态双向总线收发器,用来驱动LED或者其他的设备,可双向传输数据。
数码管定时秒表
为了不浪费太多时间,我在演示视频中剪去了中间计数的一部分,大家主要看1分钟自动置零的效果就可以了。
第二个案例是计数器,要求是双击按键切换灯光,再次双击切换另一种灯光。
#include <reg51.h>
unsigned char F=0;void Delay(unsigned int i)
{ unsigned int j; for(;i>0;i--) for(j=0;j<125;j++); }
void main( ) { //顺序可以调换,记住要配置TMOD、TCON、IE和初值TMOD=0x50; //设置定时器T1工作方式1TH1=0xff; //向TH1写入初值的高8位TL1=0xfe; //向TL1写入初值的低8位EA=1; //开启总中断允许ET1=1; //定时器T1中断允许 TR1=1; //启动定时器T1while(1){if(F==1) //第一次双击,灯光标志位为1,进入模式1 { P1=0xff; //LED全部闪烁 Delay(500) ; P1=0x00; Delay(500); }if(F==2) //第二次双击,灯光标志位为2,进入模式2 { P1=0xaa; //LED奇偶位交替闪烁 Delay(500) ; P1=0x55; Delay(500); }if(F==3) //第三次双击,清空标志位,关闭灯光{ F=0;P1=0xff;} }}void T1_int(void) interrupt 3 //计数器T1中断服务函数
{TH1=0xff; //重新赋值TL1=0xfe; F++; //灯光执行标志+1,中断只做赋值,不执行具体程序,可以有效减少运行时间
}
大家可以自行改变按键对应的执行程序,与其他外设组合,比如让数码管显示不同的图案,也可以更改标志位的复制逻辑,单双击赋予不同的意义。总的来说思路都相同,只是需要注意在中断服务函数里应尽量少执行操作,将重点的操作置于主函数内部,通过改变标志位的数值来执行不同的程序。
按键计数器控制LED点亮
今天和大家分享了两个定时器/计数器的应用,因为笔者所学专业对单片机要求不高,亟待分享的内容只剩下几个类似的应用,这个专栏也快要走到尾声了,感谢大家一路的陪伴,我们明天再见。