微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 定时器的学习(参考自郭天祥的教程)

定时器的学习(参考自郭天祥的教程)

时间:10-02 整理:3721RD 点击:

更多51单片机定时器知识请进入专题:http://bbs.elecfans.com/topic-dingshiqi.html

8051内部有2个十六位的定时器/计数器,主要作用是对外部脉冲计数,产生精确定时时间

结构如下:


特殊功能寄存器之工作方式寄存器TMOD


M1和M0:操作模式控制位  当M1=0,M0=1时,也就是工作方式1的16位定时器/计数器

GATE:   门控制位       当GATE=1,时,INT0(INT1)=1,且TR0(TR1)=1则启动定时器/计数器

                         当GATE=0,时,只要TR0(TR1)=1定时器/计数就开始工作

C/T:     选择定时或者选择计数方式

                                            当C/T=0时,则选择定时方式(每个周期使计数器加1)

                         当C/T=1时,则选择计数方式(当接收到的外部脉冲产生负跳变时使计数器加1)

特殊寄存器之状态控制寄存器TCON


TF1: 定时器T1溢出中断标志    当定时器T1溢出时,由硬件置1

                                                  当响应中断时,由硬件置0,

TR1:定时器T1运行控制位,由软件控制置位和复位,控制定时器是否运行,当是0时,关闭定时器1。TF1和TR1都是控制定时器T1的,同理TF0和TR0都是控制定时器T0的

IE1,IT1,IE0,IT0是控制外部中断的

IE1:外部中断1请求标志

IE0:外部中断0请求标志

IT1:外部中断1触发方式选择位

IT0:外部中断0触发方式选择位

定时器0的工作方式逻辑图:


分析上面的逻辑图知(INT0非 OR GATE非)AND  TR0为真时定时器0启动工作

                                C/T=1为计数工作方式,计数脉冲由T0引脚输入。

                                C/T=0为定时工作方式。

工作的过程中,发生溢出是硬件自动设置TF0=1,然后单片机去处理中断


定时器0工作方式1下分析

因为定时器在默认情况下装入的是00000000 00000000,当定时器开始计数时,寄存器的值一直加1,当加到11111111 11111111时,外部再过来一个脉冲后就发生溢出了,单片机就去处理中断程序了。假设单片机的晶振的频率是12MHZ,那么一个机器周期的时间就是1us,这种情况下一共需要的时间是65536us,也就是65.5ms,因此如果我们要定时65.5ms的话,就可以这样做,但是定的时间如果不是65.5ms的话,则需要装入定时器中一个初值。假设我们要计数的个数是N个,设装入的初值是X,则X+N=2^16, 解得X=2^16-N,比如要装50000个数的话,初值X=65536-50000=15536,然后把15536对256取模15536/256=60装入TH0中,15536%256=176装入TL0中。因为实验板上的晶振是11.0592MHZ,可知机器周期=1.09us,比如说我们要定时50ms(50000us)那么计数的个数是N=50000/1.09=45872,再计算初始值X=65536-45872=19664,,再分别计算TH0和TL0中具体装多少就可以了。

利用定时器工作方式1,在实验板上实现第一个发光二极管以1s亮灭闪烁

程序如下:


  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit led1=P1^0;
  5. uchar num;
  6. void main()
  7. {
  8.        TMOD=0x01;   // 工作方式是1
  9.        TH0=(65536-45872)/256;     //计算初值
  10.        TL0=(65536-45872)%256;    //计算初值
  11.        EA=1;                     //开总中断
  12.        ET0=1;                    //定时器T0 中断允许
  13.        TR0=1;                    //启动定时器定时的功能
  14.        while(1);[/p][p=30, 2, left]
  15. }
  16. void T0_time()interrupt 1         //定时器0的中断服务程序
  17. {
  18.        TH0=(65536-45872)/256;     //重装初值
  19.        TL0=(65536-45872)%256;
  20.        num++;
  21.        if(num==20)                //应为定时1s,因此循环20次
  22.               {
  23.                      num=0;            //重新赋值num进入下一次循环
  24.                      led1=~led1;       //定时1s后,改变发光二极管的状态[/p][p=30, 2, left]            
  25.              }     
  26. }

复制代码


上面程序等价于

  1. #include <reg52.h>
  2. #define uchar unsigned char
  3. #define uint unsigned int
  4. sbit led1=P1^0;
  5. uchar num;
  6. void main()
  7. {
  8.        TMOD=0x01;
  9.        TH0=(65536-45872)/256;
  10.        TL0=(65536-45872)%256;
  11.        EA=1;
  12.        ET0=1;
  13.        TR0=1;
  14.        while(1)
  15.               {
  16.                      if(num==20)
  17.                             {
  18.                                    num=0;
  19.                                    led1=~led1;
  20.                             }     
  21.               }
  22. void T0_time() interrupt 1
  23. {
  24.        TH0=(65536-45872)/256;
  25.        TL0=(65536-45872)%256;
  26.        num++;
  27. }

复制代码


程序分析:首先进入主程序设置一些寄存器的初始参数,开中断。当执行到while(1);时,停在这里,另一方面定时器还在计数,当发生溢出时,于是就转去执行中断程序,执行完后又回到while(1);处,如此一直循环下去。注意:循环的前提是中断没有关闭,除非你关中断!

不错 。感谢分享

谢谢分享!

正在学习定时器这里,现在还有很多不明白,大家多多交流

请教一下为什么初值要写两次,一次不行吗?

不错

学习!

很精彩,谢谢分享

我在KEIL2里行?

学懂这了啦,受益匪浅

haixing ,bucuo ``yoyong ``

我的板板不能运行第二段程序。请大家指点迷津。

第一段和第二段不是等一样吗?。

第一段和第二段不是等一样吗?。

为什么有错啊?给我讲解哈

小编辛苦了,学习中

比我自己做的笔记好很多。谢谢小编了。

谢谢

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top