定时器/计数器

一、简介

定时器实际上就是Soc当中的一个内部外设。定时器常与计数器扯到一起,计数器也是Soc当中的一个内部外设,计数器顾名思义是用来计数的,就和我们的秒表一样,秒表实际上就是一个计数器,每隔一个单位走一个格(就是计一个数),因为计数器的计数时间周期是固定的,因此到了一定时间只要用计数值*计数时间周期,就能得到一个时间段,这个时间段就是我们定的时间(这就是定时器了)。计数器和定时器其实是一回事。

二、定时器的原理

定时器计时其实是通过计数来实现的。定时器内部有一个计数器,每隔一个时钟周期,计数器就计数一次,定时器的时间就是计数器计数值x时钟周期。

  • 振荡周期:为单片机提供定时信号的振荡源周期。
  • 状态周期:2个振荡周期为一个状态周期。
  • 机器周期:一个机器周期包含六个状态周期,十二个振荡周期。
  • 指令周期:完成一条指令所占用的全部时间

三、51单片机的定时器

STC89C52有三个16位定时器,T0、T1、T2,单片机内的定时器和CPU是相互独立的,互不影响,所以它们的执行不需要CPU的参与,而软件延迟利用若干次空循环实现,占用CPU。

四、内部结构

定时器/计数器 11 - 斯塔克电子

定时/计数器的实质是加一计数器(16位),由高8位和低八位两个寄存器TH和TL组成,TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0,T1的启动和停止及设置溢出标志位。

五、定时器/计数器0和1的相关寄存器

定时器/计数器 12 - 斯塔克电子

1、定时器/计数器控制寄存器TCON

TCON为定时器/计数器TO、T1的控制寄存器,同时也锁存TO、T1溢出中断源和外部请求中断源等,TCON格式如下:

定时器/计数器 13 - 斯塔克电子

TF1:定时器/计数器T1溢出标志。T1被允许计数以后,从初值开始加1计数。当最高位产生溢出时由硬件置“1”TF1,向CPU请求中断,一直保持到CPU响应中断时,才由硬件清“0”TF1 (TF1也可由程序查询清“0”)。

TR1:定时器T1的运行控制位。该位由软件置位和清零。当GATE(TMOD.7) =O,TR1=1时就允许T1开始计数,TR1=0时禁止T1计数。当GATE (TMOD.7)=1, TR1=1且INT1输入高电平时,才允许T1计数。

TFO:定时器/计数器TO溢出中断标志。TO被允许计数以后,从初值开始加1计数,当最高位产生溢出时,由硬件置“1”TFO,向CPU请求中断,一直保持CPU响应该中断时,才由硬件清“0”TFO (TFO也可由程序查询清“O”)。

TRO:定时器TO的运行控制位。该位由软件置位和清零。当GATE(TMOD.3)=O,TRO=1时就允许TO开始计数,TRO=0时禁止TO计数。当GATE (TMOD.3)=1,TRO=1且INTO输入高电平时,才允许TO计数。

IE1:外部中断1请求源(INT1/P3.3)标志。IE1=1,外部中断向CPU请求中断,当CPU响应该中断时由硬件清“0”IE1。

IT1:外部中断1触发方式控制位。IT1=0时,外部中断1为低电平触发方式,当INT1(P3.3)输入低电平时,置位IE1。采用低电平触发方式时,外部中断源(输入到INT1)必须保持低电平有效,直到该中断被CPU响应,同时在该中断服务程序执行完之前,外部中断源必须被清除(P3.3要变高),否则将产生另一次中断。当IT1=1时,则外部中断1(INT1)端口由“1”→“0”下降沿跳变,激活中断请求标志位IE1﹐向主机请求中断处理。

IEO:外部中断O请求源(INTO/P3.2)标志。IEO=1外部中断0向CPU请求中断,当CPU响应外部中断时,由硬件清“0”IEO(边沿触发方式)。

ITO:外部中断0触发方式控制位。ITO=0时,外部中断0为低电平触发方式,当INTO (P3.2)输入低电平时,置位IEO。采用低电平触发方式时,外部中断源(输入到INTO)必须保持低电平有效,直到该中断被CPU响应,同时在该中断服务程序执行完之前,外部中断源必须被清除(P3.2要变高),否则将产生另一次中断。当ITO=1时,则外部中断0(INTO)端口由“1”→“0”下降沿跳变,激活中断请求标志位IEO ,向主机请求中断处理。

2.定时器/计数器工作模式寄存器TMOD

定时和计数功能由特殊功能寄存器TMOD的控制位CT进行选,TMOD寄存器的各位信息如下表所列。可以看出,2个定时/计数器有4种操作模式,通过TMOD的M1和MO选择。2个定时/计数器的模式0、1和2都相同,模式3不同,各模式下的功能如下所述。

定时器/计数器 14 - 斯塔克电子

六、两个重要概念

1、TH和TL用来干嘛?

TH和TL是计数器的初始计数值,计数器会从这个值开始向上计数。

2、什么时候触发中断?

配置成模式1时,当计数值计数到65536时,溢出中断触发,进入中断服务函数。

七、配置定时器/计数器

1、标准定时器(以T0为例)

/****

*******定时器0初使化函数

*****/

void Timer0_Init(void)

{

   TMOD &= 0xF0;              //清除 T0 的工作模式

   TMOD |= 0x01;              //配置 T0 的GATE=0; C/T=0; M1=0; M0=1;(模式1(16位))

   TH0 = (65536-921)/256;     //配置 T0 高8位计数初始值

   TL0 = (65536-921)%256;     //配置 T0 低8位计数初始值

   TR0 = 1;                   //启动 T0

   ET0 = 1;                   //启动 T0 中断

   EA = 1;                   //打开总中断

}

/****

*******T0计时中断函数

1s的定时次数= 1/(12/11059200)=921600,16位计数器最大可计数65536次,所以通常定时ms为单位,比如定时1ms,则循环1000次为1s,则计数次数为921600/1000=921,则初值为

TH0 = (65536-921)/256;

TL0 = (65536-921)%256;

*****/

void Timer0_Handler(void) interrupt 1   //0:外部中断1的中断号; 1:定时器0的中断号; 2 外部中断2的中断号; 3:为定时器1的中断号; 4 串口中断的中断号;

{

   static uint timer0_count;

   TH0 = (65536-921)/256;           //重新赋初值

   TL0 = (65536-921)%256;

   if(flag_timer_begin == 1)        //开始计时

   {

      timer0_count++;

      if(timer0_count >= 1000)      //定时1s

      {

         timer0_count = 0;

         flag_1s = 1;

      }

   }

   else                            //停止计时,清除标志位

   {

      timer0_count = 0;

      flag_1s = 0;

   }

}

2、触发定时器(以T0为例,引脚INT0必须为高电平才开启定时器)

/****

*******定时器0初使化函数

*****/

void Timer0_Init(void)

{

   TMOD &= 0xF0;                 //清除 T0 的工作模式

   TMOD |= 0x09;                 //配置 T0 的GATE=1; C/T=0; M1=0; M0=1;(模式1(16位))

   TH0 = (65536-921)/256;        //配置 T0 高8位计数初始值

   TL0 = (65536-921)%256;        //配置 T0 低8位计数初始值

   TR0 = 1;                     //启动 T0

   ET0 = 1;                     //启动 T0 中断

   EA = 1;                      //打开总中断

}

/****

*******T0计时中断函数

1s的定时次数= 1/(12/11059200)=921600,16位计数器最大可计数65536次,所以通常定时ms为单位,比如定时1ms,则循环1000次为1s,则计数次数为921600/1000=921,则初值为

TH0 = (65536-921)/256;

TL0 = (65536-921)%256;

*****/

void Timer0_Handler(void) interrupt 1   //0:外部中断1的中断号; 1:定时器0的中断号; 2 外部中断2的中断号; 3:为定时器1的中断号; 4 串口中断的中断号;

{

   static uint timer0_count;

   TH0 = (65536-921)/256;              //重新赋初值

   TL0 = (65536-921)%256;

   timer0_count++;

   if(timer0_count >= 1000)            //定时1s

   {

      timer0_count = 0;

      flag_1s = 1;

   }

}

3、计数器(以T0为例,P3.4引脚由高电平到低电平跳变,计数值+1)

/****

*******定时器0初使化函数

*****/

void Timer0_Init(void)

{

   TMOD &= 0xF0;           //清除 T0 的工作模式

   TMOD |= 0x05;           //配置 T0 的GATE=0; C/T=1; M1=0; M0=1;(模式1(16位))

   TH0 = (65536-10)/256;   //配置 T0 高8位计数值

   TL0 = (65536-10)%256;   //配置 T0 低8位计数值

   TR0 = 1;                //启动 T0

   ET0 = 1;                //启动 T0 中断

   EA = 1;                 //打开总中断

}

/****

*******T0计时中断函数

1s的定时次数= 1/(12/11059200)=921600,16位计数器最大可计数65536次,所以通常定时ms为单位,比如定时1ms,则循环1000次为1s,则计数次数为921600/1000=921,则初值为

TH0 = (65536-921)/256;

TL0 = (65536-921)%256;

*****/

void Timer0_Handler(void) interrupt 1   //0:外部中断1的中断号; 1:定时器0的中断号; 2 外部中断2的中断号; 3:为定时器1的中断号; 4 串口中断的中断号;

{

   flag_finish = 1;

}

八、流程设计

首先清除定时器工作模式,然后配置定时器工作模式为模式1,接着配置定时器高八位和低八位计数初始值,接着启动定时器、启动定时器中断、打开总中断。当计数值溢出时,触发中断,进入中断服务函数,在中断服务函数中重新赋值计数初始值,进行计时处理。

定时器/计数器 15 - 斯塔克电子

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
有新私信 私信列表
搜索