8051定时器的使用

8051定时器/计数器介绍:
8051有两个定时器/计数器,而8052则有三个定时器/计数器。定时器、计数器本质都是一样的,定时器通过对内部脉冲进行计数来达到计时的目的,而计数器是对外部输入脉冲进行计数,所以它们的本质都是一样的。

定时器/计数器的工作模式:
定时器/计数器0有四种工作模式,而定时器/计数器1只有三种工作模式,工作模式由TMOD寄存器的M1和M0位控制。
M1	M0	工作模式
0	0	0 13位定时器/计数器。	
0	1	1 16位定时器/计数器。
1	0	2  8位自动重装定时器/计数器。
1	1	3 模式3只能用于定时器/计数器0,T0被分为两个8位定时器/计数器,
		  TL0可以作为定时器/计数器来使用,由T0的控制位来控制,而TH0只
		  能用于计数器,有T1的控制位来控制。

GATE	GATE为0时,由TRx(软件控制)来控制定时器/计数器的启动和停止,当GATE为
	1时,定时器/计数器的启动由TRx和引脚INTx共同来控制(硬件来控制,仅当
	TRx=1并且引脚INTx输入高电平时才工作)。
C/T	定时器/计数器选择位,0工作在定时器模式,1工作在计数器模式。


TCON寄存器:
TFx	定时器/计数器溢出标志位,当定时器/计数器计数溢出时,由硬件自动置1,在
	编写程序时可以通过检测该位来判断是否达到定时时间,需要通过软件来清零。
	工作在中断方式下不需要清零,因为在执行中断服务程序时会自动给我们清零。
TRx	定时器/计数器运行控制位。


IE寄存器:
ETx	定时器/计数器中断使能位。
EA	全局中断使能位。


THx、TLx初值计算:
假设8051外接12MHz的晶振,由于8051的机器周期是时钟周期的12分频,所以8051的机器周期为1MHz,那么计数一次的时间刚好为1us,如果定时器工作在模式0下,那么可以最长计时为8192us,工作模式1可以最长计时为65536us。那么假设8051工作在模式1下,定时1ms,那么THx、TLx的初值应该为多少呢?如果定时1ms,也就意味着需要计数1000次,那么初值就应该为65536-1000=64536,也就是THx=0xFC,TLx=0x18。
根据上面可以总结出如下公式:
定时时间=(最大计数值-计数器初值)*机器周期=(最大计数值-计数器初值)*(12000000/晶振频率(Hz))(us);
计数器初值=(最大计数值-定时时间*(晶振频率(Hz)/12000000));
套用这个公式,初值=(65536-1000*(12000000/12000000))=64536=0xFC18,那么TH就应该为0xFC,TL为0x18。

整个程序如下:

/* timer.c */
#include <at89x52.h>

#define OSC_FREQ        12000000UL

#define TIMER_MODE0     0x00
#define TIMER_MODE1     0x01
#define TIMER_MODE2     0x02
#define TIMER_MODE3     0x03

void timer0_init(void)
{
        TMOD &= 0xF0;
        TMOD |= TIMER_MODE1;    /* Timer 0 work on 16-bit timer mode */
        TH0 = (65536-1000*(OSC_FREQ/12000000)) >> 8;
        TL0 = (65536-1000*(OSC_FREQ/12000000)) & 0x00FF;
        TR0 = 1;                /* Turn on timer 0 */
}

void delayms(unsigned int n)
{
        while (n--) {
                while (!TF0);
                TF0 = 0;
                TH0 = (65536-1000*(OSC_FREQ/12000000)) >> 8;
                TL0 = (65536-1000*(OSC_FREQ/12000000)) & 0x00FF;
        }
}


/* timer.h */
#ifndef __TIMER_H
#define __TIMER_H

extern void timer0_init(void);
extern void delayms(unsigned int n);

#endif /* __TIMER_H */

/* main.c */
#include <at89x52.h>

#include "timer.h"

#define led1 P2_0

void main(void)
{
        timer0_init();

        while (1) {
                led1 = 0;
                delayms(1000);
                led1 = 1;
                delayms(1000);
        }
}

8051定时器的使用

上一篇:利用nf_conntrack机制存储路由,省去每包路由查找


下一篇:关于生活质量与购物