定时器/计数器⏰
CPU时序的相关知识时间⌛
- 振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)
- 状态周期:2个振荡周期为1个状态周期,用S表示。振荡周期又称S周期或时钟周期。
- 机器周期:1个机器周期含6个状态周期,12个振荡周期。
- 指令周期:完成1条指令所占用的全部时间,它以机器周期为单位。
例如:外接晶振为12 MHz时,51单片机相关周期的具体值为:
- Hz 是赫兹,频率单位, 1 MHz(兆赫) = 1000 KHz (千赫)= 1000000 HZ
- 振荡周期=1/12 us;
- 状态周期=1/6 us;
- 机器周期=1 us;
- 指令周期=1~4 us;
定时器介绍📃
-
传统51单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。
-
定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的,不需要CPU的参与。
-
51单片机中的定时器/计数器是根据机器内部的时钟 或者是外部的脉冲信号对寄存器中的数据加1。
-
有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加1的工作可以交给定时器/计数器处理。CPU转而处理一些复杂的事情。同时可以实现精确定时作用。
-
定时器作用:
(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作
(2)替代长时间的Delay,提高CPU的运行效率和处理速度
(3)...
STC89C52定时器资源⛽
- 定时器个数:3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源
- 注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的
定时器原理📳
-
定时/计数器实质上是一个加1计数器。它随着计数器的输入脉冲进行自加1,也就是每来一个脉冲,计数器就自动加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。
可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。
-
简单的说定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔"一秒",计数单元的数值就增加一,当计数单元数值增加到"设定的闹钟提醒时间"时,计数单元就会向中断系统发出中断申请,产生"响铃提醒",使程序跳转到中断服务函数中执行。
定时器的工作模式💼
STC89C52 的 T0 和 T1 均有四种工作模式:
- 模式0:13位定时器/计数器
- 模式1:16位定时器/计数器*(常用)*
- 模式2:8位自动重装模式
- 模式3:两个8位计数器
定时器的结构⚙
这里我分析一下定时器0
最常用的模式1,关于其他模式可以再数据手册查看
定时器部分:
- SYSclk是系统时钟就是晶振周期。
- 定时器可以由
0Pin
外部计数脉冲触发,也可以通过通过机器周期来触发。
门控端部分:
-
门控位GATE具有特殊的作用。
-
当GATE=0时,经反相后使或门输出为1,此时仅由TR0控制与门的开启,与门输出1时,控制开关接通,计数开始;
-
当GATE=1时,由外中断引脚信号控制或门的输出,此时控制与门的开启由外中断引脚信号和TR0共同控制。当TR0=1时,外中断引脚信号引脚的高电平启动计数,外中断引脚信号引脚的低电平停止计数。
这种方式常用来测量外中断引脚上正脉冲的宽度。
-
所以我们一般情况下将GATE配置为0,TR0配置为1
计数器部分:
- 方式1的计数位数是16位,由
TL0
作为低8位,TH0
作为高8位,组成了16位加1计数器 。 - 计数个数与计数初值的关系为:X=2^16-N
中断系统部分:
- 我们需要把ET和EA配置为1
相关寄存器📕
定时器控制寄存器TCON
定时器模式寄存器
M1、M0 :控制定时器模式。"00"为模式0,"01"为模式1,"10"为模式2,"11"为模式3
定时器初始化🚩
初始化程序应完成如下工作:
- 对TMOD赋值,以确定T0和T1的工作方式。
- 计算初值,并将其写入TH0、TL0或TH1、TL1。
- 中断方式时,则对EA赋值,开放定时器中断。
- 使TR0或TR1置位,启动定时/计数器定时或计数。
代码实例📝
c
#include <REGX52.H>
/**
* @brief 定时器0初始化,1毫秒@11.0592MHz
* @param 无
* @retval 无
*/
void Timer0Init(void)
{
//TMOD = 0x01; 这种方式后面配定时器1的时候,定时器0就会受到影响
TMOD &= 0xF0; //设置定时器模式 与运算使得前四位保留,后四位清除
TMOD |= 0x01; //设置定时器模式 或运算使得前四位保留,最低位置1
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //中断配置Timer0开关
EA=1; //中断配置总开关
PT0=0; //优先级
}
/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
T0Count++; //T0Count计次,对中断频率进行分频
if(T0Count>=1000)//分频1000次,1000ms
{
T0Count=0;
}
}
*/