1.初识51单片机定时器

2.如何配置一个简单的定时器

3.进一步了解并使用定时器

初识51单片机定时器

为什么要使用定时器?

  1. 生成精确定时延迟: 定时器可以用来生成精确的时间延迟,例如在通信协议中的时间间隔、传感器数据采集间隔等。这对于需要精确时间控制的应用非常重要。
  2. 脉冲宽度调制(PWM): 定时器可以用来生成PWM信号,用于控制电机速度、LED亮度等,从而模拟模拟信号的输出。
  3. 定时中断: 定时器可以配置成在预定的时间间隔后触发中断,以执行特定的任务。例如,定时器中断可以用于周期性地更新显示、检查按键状态、进行数据处理等。
  4. 频率计数: 定时器可以用来计算外部事件的频率,例如测量脉冲的频率或输入信号的周期。
  5. 时间戳记录: 在一些应用中,需要记录事件发生的时间戳,定时器可以提供时间基准,帮助记录事件的时间。
  6. 超时检测: 在通信或协议处理中,定时器可以用来检测是否在规定的时间内收到了预期的响应,以进行超时处理。
  7. 脉冲计数: 定时器可以用来计数外部脉冲的数量,例如测量速度、计数物体通过等。
  8. 周期性任务: 定时器可以用来触发周期性的任务,例如周期性地发送心跳信号、更新传感器数据等。
  9. 时钟分频: 定时器可以用来将高频时钟分频为低频时钟,从而降低功耗或适应特定模块的时钟需求

一般的定时器是在到达自己的预定时间之后触发中断函数,使用定时器和中断函数可以减轻CPU的运算压力,那么自然而然地就会出现一个问题:为什么中断不耗费cpu资源,或者说没那么耗费????

其实问题的答案很简单:因为发生中断的时候,cpu把当前任务放到等待队列里,然后去调用相应的中断处理程序,处理完中断后再从等待队列把进程丢到工作队列抢占cpu资源。类似的设计思路其实很多,比如java的AQS.

所以说定时器不仅用处很多而且在恰当的位置使用可以很好的优化我们的代码。

定时器原理?

51单片机定时器(一)STC89C52_寄存器

51单片机内部有一个12MHZ的晶振,

我们算一下:hz是频率单位,它是每秒钟的周期性变动重复次数的计量。

时钟周期=1/(12M) (s)= 1/12/1000/1000 (s) = 1/12 us

51单片机一个指令周期是12个时钟周期,即指令周期=12*1/12 us = 1us

接下来来配置一个简单的定时器,工作模式为1,选择定时器0

51单片机定时器(一)STC89C52_寄存器_02

51单片机有两个定时器T0和T1,上图为其相关的寄存器表

TCON控制寄存器(可位寻址)

TF0=0(溢出中断标志),加到65536后TFO会被置为0

TR0=1 允许定时器0计时

TMOD寄存器(不可位寻址)

51单片机定时器(一)STC89C52_工作模式_03

定时器1的不用配置,定时器0配置如下

GATE=0:这个看电路图就知道为啥给0(不需要管INT0是啥)

C/T=0:0代表用作定时器,1代表用作计数器

M1=0,M0=1。M1和M0这样设置代表使用模式1,即TH0和TL0两个寄存器都使用

TMOD=0x01

51单片机定时器(一)STC89C52_寄存器_04

第一步:配置工作方式寄存器TCON

工作模式寄存器TMOD有四种工作模式,其中常用的是工作模式1和2,具体内容自己搜索

TMOD = 0x01;//设置为模式1,更多设置可以参考芯片手册

第二步:给TH0和TL0赋值

TH0和TL0分别是高位寄存器和低位寄存器,都是八位寄存器。

51单片机定时器(一)STC89C52_51单片机_05

第三步:配置控制寄存器TCON

首先是开启定时器TR0,然后将TF0软件复位(可选)

第四步:中断配置

ET0=1;
EA=1;

第五步:优先级配置(可选)




最后,源代码献上

#include <REGX52.H>
sbit LED = P1^0;

int main(void)
{
	TMOD = 0x01;		//第一步:配置TMOD		//  0000 0001 ; 选择方式1
        TH0 = (65536 - 1000) / 256
        TL0 = (65536 - 1000) % 256		// 第二步:赋初值 		//  0xfc18 = 64536.  定时1000us = 1ms (500HZ)
	TR0 = 1;			//第三步:配置TCON		// 定时方式,选择定时器 T0
	ET0 = 1;									// 定时器/计数器0中断允许位,打开T0中断
	EA = 1;			//第四步:开总中断	

	while(1);
}


void timer0() interrupt 1
{

        TH0 = (65536 - 1000) / 256
        TL0 = (65536 - 1000) % 256		// 方式1 在中断中需要重新赋初值
	LED = ~LED;
		
}