51单片机定时器/计数器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/little_white__/article/details/70245887

1.基本概念:

89C51有两个计数器T0和T1,每个计数器都是由两个8位的RAM 单元组成的,即每个计数器都是16 位的计数器,最大的计数容量是2的6次方=65536,记住是从0-65535。

定时器的本质也是计数器,只不过定时器的脉冲来自内部的晶振,而计数器的脉冲来自外部,当检测的脉冲的下降沿时,计数寄存器加一,直到溢出,然后单片机产生一个中断。所以需要定时时,先给计数寄存器设定一个初值,每有一个内部的脉冲时钟信号(相当与一段时间),计数器加一,直到溢出,一次定时完成。之后继续循环上述步骤。

2.内部结构:

这里写图片描述

3.相关寄存器:

  1. 定时/计数器方式寄存器TMOD(只能段寻址)
    这里写图片描述
    GATE—门控制位。
    GATE=0,定时器/计数器启动与停止仅受TCON寄存器中TRX(X=0,1)来控制。
    GATE=1,定时器计数器启动与停止由TCON寄存器中TRX(X=0,1)和外部中断引脚(INT0或INT1)上的电平状态来共同控制
    C/T—定时器和计数器模式选择位。
    C/T=1,为计数器模式;C/T=0,为定时器模式。
    M1M0—工作模式选择位。
    这里写图片描述
  2. 定时器/控制器控制寄存器TCON(可以位寻址)
    这里写图片描述
    IT0:外部中断0触发方式控制位
    当IT0=0时,为电平触发方式(低电平有效)
    当IT0=1时,为边沿触发方式(下降沿有效)
    IE0:外部中断0中断请求标志位 (硬件自动完成)
    IT1:外部中断1触发方式控制位(同IT0)
    IE1:外部中断1中断请求标志位 (同IE0)
    TF0:定时/计数器T0溢出中断请求标志位
    TF1:定时/计数器T1溢出中断请求标志位
    TR1:定时器1运行控制位。
    由软件清0关闭定时器1。当GATE=1,且INIT为高电平时,TR1置1启动 定时器1;当GATE=0时,TR1置1启动定时器1。
    TR0—定时器0运行控制位,其功能及操作方法同TR1。
  3. 计数寄存器TH0/TL0(8位) , TH1/TL1(8位)
    关于如何设初值,首先要明白几个周期的概念:

     ***时钟周期:***
    

时钟周期也叫振荡周期或晶振周期,即晶振的单位时间发出的脉冲数,一般有外部的振晶产生,比如12MHZ=12×10的6次方,即每秒发出12000000个脉冲信号,那么发出一个脉冲的时间就是时钟周期,也就是1/12微秒。通常也叫做系统时钟周期。是计算机中最基本的、最小的时间单位。

        ***机器周期:***

在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。例如,取指令、存储器读、存储器写等,这每一项工作称为一个基本操作。完成一个基本操作所需要的时间称为机器周期。8051单片机的机器周期由12个状态周期组成。

在标准的51单片机中,一般情况下,一个机器周期等于12个时钟周期,也就是机器周期=12*时钟周期,(上面讲到的原因)如果是12MHZ,那么机器周期=1微秒。单片机工作时,是一条一条地从RoM中取指令,然后一步一步地执行。单片机访问一次存储器的时间,称之为一个机器周期,这是一个时间基准。

机器周期不仅对于指令执行有着重要的意义,而且机器周期也是单片机定时器和计数器的时间基准。例如一个单片机选择了12MHZ晶振,那么当定时器的数值加1时,实际经过的时间就是1us,这就是单片机的定时原理。

接下来就是如何设初值了:

一般我们取12M晶振时,一个周期刚好是1us,计数1000个就是1ms,这是因为标准的51单片机是12时钟周期的(STC有6时钟和1时钟方式)。那么,如果我们晶振是12M,就比较好算,如果是其它的,就用12去除好了。比如是6M的,那么就是12/6=2,每个计数是2us,那么你要定时1ms就只要计数500个即可以。

定时器的初值跟定时器的工作方式,跟晶振频率都有关系。一个机器周期Tcy=晶振频率X12,计数次数N=定时时间t/机器周期Tcy,那么初值就X=65536-N,得出的数化成十六进制就行了。这里是用定时器O工作方式1做例子,如果是其它工作方式,就不能是65535了。工作方式0是8192,方式2,3是256。这里有一个公式:

TH=(65536-time/(12/ft))/256

其中,time就是要延时的100ms(要取100000us),ft是晶振频率。这个式子又可以简化成

TH=(65536-time*ft/12)/256

TL=(65536-time*ft/12)%256

4.实例分析:

通常定时器初始化过程如下:
(1)对TMOD赋值,以确定T0和 T1的工作方式。
(2)计算初值,并将初值写入TH0、TL0或TH1、TL1。
(3)中断方式时,则对IE赋值,开放中断。
(4)使TR0和TR1置位,启动定时器/计数器定时或计数。

这里写图片描述

    产生一个1khz的方波

主程序:

采用定时器0的模式1

#include <reg51.h>
#include <intrins.h>

#define uint unsigned int 

sbit led = P1^0 ;

void Time0_Init(void)
{
    TMOD = 0x1 ;  //定时器0模式1,C/T = 0 , GATE0 = 0 ;
    TH0 = (65536 - 500)/256 ;  //设初值
    TL0 = (65536 - 500)%256 ;
    ET0 = 1 ;        //开定时器0中断
    EA = 1 ;        //开总中断
    TR0 = 1 ;      // 开定时器0
}

void Time0() interrupt 1
{
    TH0 = (65536 - 500)/256 ; //重新设初值
    TL0 = (65536 - 500)%256 ;
    led = ~led ;
}
void main(void)
{
    Time0_Init() ; // 定时器0初始化
    led = 0 ;

    while(1)
    {

    }
}

采用定时器0的模式2:

#include <reg51.h>
#include <intrins.h>

#define uint unsigned int 

sbit led = P1^0 ;

uint T0_count = 0 ;

void Time0_Init(void)
{
    TMOD = 0x2 ;  //定时器0模式2 ,C/T = 0 ,GATE0 = 0 ;
    TH0 = 256 - 100;  //设初值
    ET0 = 1 ;
    EA = 1 ;
    TR0 = 1 ;      // 开定时器0
}

void Time0() interrupt 1
{
    T0_count ++ ;//每次0.1ms加一
    if(T0_count == 5)
    {
        led = ~led ;
        T0_count = 0 ;
    }
}
void main(void)
{
    Time0_Init() ; // 定时器0初始化
    led = 0 ;
    while(1)
    {
    }
}

感觉自己水水的,请多指教。

猜你喜欢

转载自blog.csdn.net/little_white__/article/details/70245887