简介
 
C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器或者计数器使用。
确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。
 
标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2。
 
 
 
时钟周期与机器周期
 
定时器的本质原理就是:每经过1个机器周期,计数存储器的值就加1。因此当使用定时器时,就必须掌握时钟周期和机器周期的关系。
 
时钟周期 :晶振频率的倒数。如果使用的是11.0592M的晶振,那么就是 1 / (11.0592x10^6) 秒   
注:1MHz = 10^6Hz
 
 
机器周期 :标准51下,机器周期 =12倍的时钟周期。即:12 / (11.0592x10^6) 秒 。有的增强51单片机,1个机器周期等于4倍的时钟周期,还有的更短。
 
 
 
计数存储寄存器THx&TLx
 
定时器和计数器工作,都依赖于 计数。计数则是由计数存储器THx和TLx这2个8位寄存器完成的。
对于计数器,每来一个负跳变信号(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。
对于定时器,每隔1个机器周期 加 1,假如(只是假如)一个机器周期为 1ms , 当加到1000次时,我们就认为经过了1s,这就是定时器定时依据。
 
 
T0和T1都拥有一对8bit计数存储寄存器。他们的复位值都是0。
T0 对应:TH0 ,TL0
T1 对应 : TH1 , TL1
 
sfr TL0 = 0x8A; // TL中的L是LOW的意思,代表低位,同理H代表HIGH高位。2个8位组合起来就形成了一个16位的计数器。当然也可以配置为仅仅当做8bit计数存储器用。
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
 
当计数器加满后,再加1,就溢出了,溢出后自动归0。且溢出时,溢出标识位TFx 就会自动变为1(T0的溢出标志位TF0,T1的溢出标志位TF1)。如果启用了对应的中断,单片机会调用中断处理函数。
 
 
 
若TH0 和 TL0 以 16位 模式工作,那它的计数范围为   [0 , 65535 ]  ,  也就是累加 65536次发生溢出。 每累加一次是  12 / (11.0592x10^6) 秒。
那么从 0 累加到溢出 历时  ≈ 0.071s = 71ms 。
可以延时 10的整数倍ms,这样就避免了误差,以便用倍数控制更长的延时时间。所以,我么要给 TH0 和  TL0赋一个初始值,使他们的溢出周期(TH0,TL0从初始值到溢出所用的时间)减少到 10ms。
就像一个瓶子,开始装了2/3,再来就只能装1/3就溢出了。通过比例式计算:
12 / (11.0592x10^6) s       -----     1   次
10x 10-3   s                        ------          x  次         (求出 x = 9216次 ,计数9216次后溢出)
65536 - 9216 = 56320  =  二进制( 11011100   00000000)
也就是  TH0 = 11011100 , TL0 = 00000000
 
 
 
 
工作模式寄存器TMOD
 
通过TMOD来配置T0和T1的工作模式。
注意,TMOD寄存器不可位寻址(例如sbit led = P0^0 就是P0寄存器位寻址的例子),因此对它的配置需要对这个8bit寄存器整体赋值。
注:51中有些特殊功能寄存器不支持位寻址。只有寄存器的地址值能够被8整除的(即以数字0或者8结尾的地址,如0xA8, 0xD0),才能支持位寻址。不支持位寻址的,只能整体赋值。
 
 
小技巧:在对寄存器整体赋值时,要注意只修改我们想修改的位而不影响其它无关位的值,避免影响了之前对这个寄存器的配置。
 
TMOD |= 0x01;   //仅仅修改TMOD的最低位,其他位保持不变。
 
 

 
 
C/T:计数器,定时器功能选择位。 1为计数器模式, 0 为定时器模式。
 
M0和M1:
 
M1
M0
模式
0
1
THx和TLx  组成一个16位计数存储器
1
0
8位重装模式。THx的值不变,负责在每次溢出后初始化TLx,仅仅由TLx计数
1
1
禁用定时器 1,定时器 0 变成 2 个 8 位定时器。很少使用。
0
0
兼容 8048 单片机的 13 位定时器,THn的 8 位和 TLn 的 5 位组
成一个 13 位定时器。很少使用。
 
GATE:门控位。
 

 
解释说明:
②处 C/T = 0 表示为定时器模式,触发信号为①处的单片机内部时钟信号。(若②处CT = 1,则触发信号为Tn脚)
③处表明,信号能触发使加法计数器加1,还得受④处控制。不然时钟信号是不能让加法计数器累加的。 ④处这个是与门,所以TRx(TR0和TR1)必须为1,表明我们要开启定时器。同时当,GATE为0,通过非门后为1,再通过或门,也是1,那么就让③处控制起来了。若GATE为1,那么,定时器的启动停止受 TRx和 INTx 共同控制。 INTx脚为1且TRx为1才能启动定时器/计数器。
于是在一般情况下使用定时器,我们需要如下配置:
 
TRx    为  1
GATE  为 0
INTx   任意
 
 
控制寄存器TCON
 
控制寄存器就是用来控制定时器/计数器 启动和停止的,以及溢出标志位的查询和修改。TFx是计数存储器溢出标志位,只要一溢出,就马上置为1。
 

TF1:定时器/计数器1的溢出标志位。1表示计数存储器溢出,0表示计数存储器正常计数。
        清0方式:①通过代码修改TF1为0
                       ②当通过中断机制来使用定时器/计数器1时,进入中断处理函数后自动归0
TR1:定时器/计数器1的启动和停止位。1表示启动,0表示停止。
 
 
 
TF0:定时器/计数器0的溢出标志位。1表示计数存储器溢出,0表示计数存储器正常计数。
        清0方式:①通过代码修改TF0为0
                       ②当通过中断机制来使用定时器/计数器0时,进入中断处理函数后自动归0
TR0:定时器/计数器0的启动和停止位。1表示启动,0表示停止。
 
 
低4位与外部中断INT0和INT1有关,与定时器/计数器无关。这里不做介绍。
 
 
 
 
 
查询法使用T0作为定时器
 
程序1:P0_0连接驱动的LED小灯,用T0作为16位定时器,完成间隔为1s 的 blink程序。
 
#include<REGX51.H>
#include"binary.h"
#include"int51.h"
/******************************/
void timer0_init(void);
void timer0_delay(uint16_t dly);
// P0_0驱动LED小灯
#define LEDpin P0_0
void main(void)
{
    LEDpin = 0;
    timer0_init();
    TR0 = 1;
    
    for(;;)
    {
       LEDpin = 1;
       timer0_delay(1000);         //延时1000ms
       LEDpin = 0;
       timer0_delay(1000);        //延时1000ms
    }
}
/*************************
T0作为定时器的初始化
**************************/
void timer0_init(void)
{
    TMOD |= B0000_0001;        //定时器0,16位存储计数器模式
    
    TH0 = B1101_1100;       //TH0 TL0 形成数是 56320  。这样,一次溢出代表经过10ms     
    TL0 = B0000_0000;
}
/**********************
参数:
    dly,延时的毫秒数,只能是10的整数倍
***********************/
void timer0_delay(uint16_t dly)
{
    
    while(dly)
    {    
        if(TF0){
             TF0 = 0;
             TH0 = B1101_1100;  
             TL0 = B0000_0000;
             dly -= 10;             //溢出一次代表10ms
        }
    }
}
 
 
程序2:通过T0定时器的8位重装模式,使得P0_0输出PWM信号,LED为呼吸灯效果。
 
#include<REGX51.H>
#include"binary.h"
#include"int51.h"
/******************************/
void timer0_init(void);
void timer0_delay(uint16_t dly);
void pwm_duty(uint16_t d);
// P0_0驱动LED小灯
#define LEDpin P0_0
void main(void)
{    
    uint16_t i;
    LEDpin = 0;
    timer0_init();
    TR0 = 1;
    
    
    for(;;)
    {
       for(i=0;i<=500;++i)
           pwm_duty(i);
       for(i=500;i>0;--i)
           pwm_duty(i);
    }
}
/*************************
T0作为定时器的初始化
**************************/
void timer0_init(void)
{
    TMOD |= B0000_0010;      //定时器0,8位重装模式
    
    TH0 = 250;           //一次溢出代表经过6.51us     
    TL0 = 250;
}
/**********************
一次溢出代表经过6.51us
参数 c乘以6.51us 就是这个函数延时的时间   
***********************/
void timer0_delay(uint16_t c)
{
    while(c)
    {    
        if(TF0){
             TF0 = 0;   //因为是自动重装,因此不用给计数存储器赋值。
             --c;             
        }
    }
}
/*************
参数d 的范围是[0,500]。d / 500 即为 pwm输出的占空比,控制LED灯的暗亮程度
**************/
void pwm_duty(uint16_t d)
{
    LEDpin = 1;
    timer0_delay(d);
    LEDpin = 0;
    timer0_delay(500-d);
}
 
 
注:如果需要精确的延时,使用8位自动重装模式最好,因为硬件装值(赋值给TH0)比软件装值快。但8位自动重装模式不宜做单次长时间延迟。毕竟溢出周期短。长时间延迟需要多个溢出周期,也挺消耗资源的。
 
尽量让溢出周期 越长越好。溢出周期为10ms 的优于 1ms 的。因为,在同样的延时时间下,如100ms,溢出周期为10ms 的 只需要溢出10次,为TH0 和 TL0重新赋值10次,而溢出周期为1ms的要溢出100次,为TH0 和 TL0重新赋值100次。减少溢出次数和赋值次数,可以减轻单片机的负担,提高定时的准确性。
 
 
 
 

【C51】单片机定时器介绍的更多相关文章

  1. C51单片机_day_01(定时器和中断系统)

                c51单片机 51单片机是控制电路系统的开关,当然芯片就是51芯片,现在随着科技的发展,也是出了很多,功能更多,更全的芯片. 51是用c语言做为程序编程的语言 ——我对基本基础 ...

  2. C51单片机头文件和启动文件

    STARTUP.A51//启动文件. 清理RAM.设置堆栈等.即执行完start.a51后跳转到.c文件的main函数 <reg51.h>  //特殊寄存器的字节地址和位地址,sfr定义字 ...

  3. C51单片机中data、idata、xdata、pdata的区别

    C51单片机中data.idata.xdata.pdata的区别 data: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小. idata: 固定指前 ...

  4. 一种基于C51单片机的非抢占式的操作系统架构

    摘 要:从Keil C51的内存空间管理方式入手,着重讨论实时操作系统在任务调度时的重入问题,分析一些解决重入的基本方式与方法:分析实时操作系统任务调度的占先性,提出非占先的任务调度是能更适合于Kei ...

  5. 51单片机定时器实现LED闪烁

    要启用一个定时器,先要开启定时器,然后产生中断 系统中断: 初始化程序应完成如下工作: 对TMOD赋值,以确定T0和T1的工作方式. 计算初值,并将其写入TH0.TL0或TH1.TL1. 中断方式时, ...

  6. 2-物联网开发标配方案(51单片机程序介绍+WIFI程序介绍)

    上一节  https://www.cnblogs.com/yangfengwu/p/9944438.html 购买云服务器安装MQTT就不用说了,以前写过文章介绍 https://www.cnblog ...

  7. C51 单片机的中断号以及中断向量

    1.外部中断0. 1:分别由引脚/INT0./INT1的电平信号引起. 2.定时/计数器0.1:分别由T0. T1的溢出引起. 3.串行口发送.接收:发送完一个字节或接收到一个字节引起. 上述共5个中 ...

  8. C8051F单片机定时器的定时

    假设C8051F020单片机的晶振是sysclk=22114800HZ,即每秒计22114800个数经过Div=12分频后得到定时器的计数频率Tclk=sysclk/12,每秒计22114800÷12 ...

  9. jmeter--九种定时器介绍(包括思考时间、集合点)

    知识来源:http://www.cnblogs.com/imyalost/p/6004678.html jmeter提供了很多元件,帮助我们更好的完成各种场景的性能测试,其中,定时器(timer)是很 ...

随机推荐

  1. json学习系列(2)-生成JSONObject的方法

    生成JSONObject一般有两种方式,通过javabean或者map类型来生成.如下面的例子: 先定义一个User实体类: package com.pcitc.json; /** * 用户实体类 * ...

  2. 阿里云ECS(云服务器)之产品简介

    参考阿里产品文档:https://docs.aliyun.com/?spm=5176.100054.3.1.ywnrMX#/pub/ecs/product-introduction/concept

  3. 海贼王之——梦想音乐

      相信和很多海粉一样,对伙伴的关照和战斗,是相当地震撼.   好东西时不时地听一下,然后感受那种刷新全身表层细胞,触电...:   音乐链接: http://v.youku.com/v_show/i ...

  4. HUST1024 dance party(最大流)

    题目大概说有n男n女,男的每回合要和不同女的跳舞,男女都有自己喜欢一起跳舞的对象,他们最多能容忍和k个不喜欢的人跳舞,问舞会最多能进行几个回合. 二分枚举回合用最大流判断:男和女各拆成两点i.i'和j ...

  5. Flo's Restaurant[HDU1103]

    Flo's Restaurant Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. POJ 1064 (二分)

    题目链接: http://poj.org/problem?id=1064 题目大意:一堆棍子可以截取,问要求最后给出K根等长棍子,求每根棍子的最大长度.保留2位小数.如果小于0.01,则输出0.00 ...

  7. 修改setInterval作用域

    Hello,今天和大家分享如何修改setInterval作用域. 0.引子 最近在做一个项目的时候需要开发一个图片轮播显示的组件,在实现过程中遇到了关于setInterval作用域的问题. Slide ...

  8. Codeforces Round #213 (Div. 2) A. Good Number

    #include <iostream> #include <vector> using namespace std; int main(){ ; cin >> n ...

  9. 【BZOJ】2802: [Poi2012]Warehouse Store(贪心)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2802 自己yy了一下... 每一次如果够那么就买. 如果不够,考虑之前买过的,如果之前买过的比当前花 ...

  10. 学习了ZKW费用流

    所谓ZKW费用流,其实就是Dinic. 若干年前有一个人发明了最小增广路算法,每次用BFS找一条增广路,时间O(nm^2) 然后被DinicD飞了:我们为什么不可以在长度不变时多路增广呢?时间O(n^ ...