一、定时器介绍
51单片机有2个16位的定时/计数器T0、T1,52单片机有3个16位定时/计数器T0、T1、T2。
定时/计数器顾名思义就是有定时和计数的功能,下面主要介绍定时器,对计数器不进行论述单片机的定时功能在日常的单片机编程中应用十分的广泛,同时定时中断也是单片机常用的中断之一,所以学好定时控制也是非常重要的,如果不理解中断的概念请查我的文章嵌入式中断的理解 http://blog.csdn.net/snyanglq/article/details/50238205
二、单片机的内部框图与定时器工作原理分析
大家请看上面的图,这是定时器T0和T1内部结构图,图中用不同颜色的线条标注了相互之间的工作关系,
从上面的图中红线可以看出由TMOD选择由那个定时器工作,工作于什么方式;
从上面的图中蓝线可以看出由TCON决定定时器是否启动;
从上面的图中黄线可以看出外部技术输入由TH和TL进行累计;
从上面的图中紫线可以看出当TH和TL计数溢出时会向TCON进行申请报告;
从上面的图中绿线可以看出所有的定时中断都由TCON向CPU进行中断申请;
从上面的图中黑线可以看出外部中断直接向CPU进行中断申请;
通过上面的图大家已经对CPU的定时中断内部结构图有一个清晰的理解,下面再看看单片机的工作原理图
从上图可以看出当作为定时器使用时,计时脉冲来自于外部晶振振荡频率后的12分频,当设置为计数器时则是直接外部脉冲作为计时脉冲,控制选择定时还是计数由C/T位控制,而控制定时器是否进行计时则由B控制,B是一个与门的输出端,与门的工作原理是有0出0,全1出1,可见定时器要启动TRx和A必须要为1,而A是或门的输出,或门的工作原理是有1出1,全0出0,所以需要输入端要任意一位为1方可,当所有条件符合,TH和TL开始定时计算,当两个计数器计数满溢出时,会令TF置位,最后由TF向CPU发出中断请求,处理中断程序,注意此时,单片机的计数器会清零,这是计数器内部设计决定的,所以定时需要再次使用时需要重载计数器初值
三、寄存器介绍
TCON:
TF0和TF1:定时器/计数器溢出标志位。
当定时器/计数器0(或定时器/计数器1)溢出时,由硬件自动使TF0(或TF1)置1,并向CPU申请中断。
CPU响应中断后,自动对TF1清零。TF1也可以用软件清零。
TR0和TR1:定时器/计数起运行控制位。
TR0(或TR1)=0,停止定时器/计数器0(或定时器/计数器1)工作。
TR0(或TR1)=1,启动定时器/计数器0(或定时器/计数器1)工作。
外部中断暂时不介绍
TMOD:
GATE:门控位。
GATE=0,只要用软件使TR0(或TR1)置1就能启动定时器/计数器0(或定时器/计数器1);
GATE=1,只有在(或)引脚为高电平的情况下,且由软件使TR0(或TR1)置1时,才能启动定时器/计数器0(或定时器/计数器1)工作。不管GATE处于什么状态,只要TR0(或TR1)=0定时器/计数器便停止工作。
C/T: 定时器/计数器工作方式选择位。
C/T =0,为定时工作方式;
C/T=1,为计数工作方式。
M0、M1:工作方式选择位,确定4种工作方式。
IE:
EA = 1, CPU开放总中断;
ET0 = 1,允许T0中断;
TR TL:定时器寄存器
注意:由于reg52.h的库定义了大部分的寄存器所以可以直接给TCON TMOD IE赋值操作或者是单独寄存器操作。
四、中断程序执行方法和定时计数公式
中断程序执行方法有直接中断和查询两种方法,查询即查询TF位是否置位为1
定时初值计算公式为:
定时时间=(计数最大值 – 计数初值)×机器周期
机器周期T = 12/晶振频率
或者是用取模的方式
TH0=(计数最大值 – 定时时间)/256;
TL0=(计数最大值 – 定时时间)%256;
首先解析为什么要设定初值?
当设定定时器为16为计数器时,则计数最大值为2^16 = 65536;
TH和TL分别为8位,即TL每逢256进一位,所以除掉256就能看出TH进了多少位,取模则是余下多少位
举个例子,2位计数器最大计数为4,要将初值6分到两个2位计数器,由于低位逢四进1所以剩下2
即TL = 2然后高位是1即TH=1,按照上面的方法:2^4 = 16,2^2 = 4; TH = (16-(16-6))/4=1(整型不算小数);
TL = (16-(16-6))%4=2;可见结果是一样的。
五、程序设计
例:利用数码管静态显示0到9,每1S钟加一,到9再加1回到0,使用中断程序实现。
分析:一秒钟加一即需要定时1S后才能动作,由于单片机最大定时也只是65536ms,
所以我们需要累加,为了计算方便我们累加20次定时50ms
#include
#define uchar unsigned char
#define uint unsigned int
uchar code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
uchar num,a;
void main()
{
TMOD=0x01; //设置定时器0为工作方式1[直接赋值]
TH0=(65536-50000)/256; //利用取模方式设置初值
TL0=(65536-50000)%256;
EA=1; //打开总中断开关[直接操作寄存器]
ET0=1; //打开定时器中断
a = 0; //初始化a、num为了程序严谨,也可以去掉
num = 0;
TR0=1; //启动定时器
while(1)
{
if(a==20)
{
a=0;
P1=smg_du[num];
num++;
if(num==10)
{
num=0;
}
}
}
}
void timer0 () interrupt 1
{
TH0=(65536-50000)/256; //初值重载,否则下次定时就是65535us而不是50ms
TL0=(65536-50000)%256;
a++; //50ms中断累加
}
上一篇:单片机控制串口通信
下一篇:单片机控制独立按键读入
推荐阅读最新更新时间:2024-03-16 16:10