51单片机的定时器/计数器及编程

本文简单阐述了怎么使用51的定时器/计数器。
如果不在意细节,可以直接看“五、应用实例”。

一、原理(简略)

​ 定时器/计数器实质是加1计数器,该计数器由两个寄存器存储着计数的值(每一个有8位),将其称之为高8位、低8位寄存器;意即高8位、低8位的数值总和即为计数总和。

​ 当高8位、低8位寄存器全满时(即16位全为1,等同于216),若再计数一次,定时器/计数器会产生一次“溢出”,将高8位、低8位寄存器清0,并向单片机发生中断请求。所以只要设定了寄存器的初值,就可以控制啥时候溢出了。

​ 然而,什么时候计数一次呢?脉冲下降沿。而脉冲有两个来源:一是系统的时钟振荡器,二是T0或T1引脚输入的外部脉冲源。一般情况下,使用系统的时钟源即可满足需求。

二、寄存器

1.控制寄存器TCON

位:76543210
字节地址:88HTF1TR1TF0TR0IE1IT1IE0IT0

各标志位功能如下:(仅讲4位与定时器有关的)

  • TF1——定时器1的溢出标志位。当加1计数器达到最大值时,则在下一次脉冲时产生溢出,此时由硬件将TF1置1,发出中断请求;响应中断后,该位由硬件清0。【注:软件也可以对它进行操作】
  • TR1——定时器1的运行控制位。设定为1时,定时器开始工作;为0时,定时器停止工作。
  • TF0、TR0——分别是定时器0的溢出标志位、运行控制位,功能与上述相同。

2.工作方式寄存器TMOD

位:76543210
字节地址:89HGATEC/TM1M0GATEC/TM1M0

各标志位功能如下:(低4位控制T0,高4位控制T1;此处仅以高4位为例)

  • GATE——门控位。设定为0时,定时器/计数器T1的运行启动仅受TCON的TR1控制;为1时,不但需要TR1=1,还需要外部引脚INT0=1。
  • C/T——工作模式选择位。设定为0时,T1是定时器;为1时,T1是计数器。
  • M1、M0——工作方式控制位。设定为00,对应方式0;为01,则方式1;为10,则方式2;为11,则方式3。

3.加1计数器的寄存器THx和TLx

  • TH0、TL0是T0的计数器,TH1、TL1是T1的计数器。TH是高8位,TL是低8位。
  • 当我们需要设定初值时,就可以对THx和TLx进行赋值,而后定时器/计数器会从这个值开始累加,直至216

三、如何设定初值

由于常使用工作方式1,所以下面以T0为例,展示在工作方式1的情况下如何设定初值。

  • 计数器模式:

    设初值为X、计算次数为M,则
    X = 65536 − M X=65536-M X=65536M

  • 定时器模式:

    设初值为X、定时为t微秒,时钟频率为f MHz、时钟周期为T微秒(12分频后,T=12/f),则
    X = 65536 − t / T = 65536 − t ∗ f / 12 X=65536-t/T=65536-t*f/12 X=65536t/T=65536tf/12

放入数值:
//提示:2的8次方等于256
TH0=X/256;
TL0=X%256;

四、定时器/计数器的编程(使用中断)

初始化
//使用T1
TMOD=0x10//GATE=0,C/T=0,工作方式为1
赋初值
//想要计数50000次,则设定初值为15536
TH1=15536/256;
TL1=15536%256;
开中断
EA=1;	//总中断
EX0=1//开定时器中断
TR1=1;	//使能定时器
写中断服务程序
void time() interrupt 1		//1是定时器T0中断序号
{
    write something
}

五、应用实例

利用中断、定时器,实现精准延时1s和延时t s,让LED每2s取反一次:

/*功能:通过中断延时,令LED1的闪烁间隔为2s。(使用T0)*/

#include <reg52.h>
#define uint unsigned int

sbit led1=P1^0;
uint num=0;

/**函数功能:精准延时1s**/
void delay_1s(){
	while(num<=20);
	num=0;
}

/**函数功能:精准延时。单位:s**/
void delay(uint t){
	while(num<=20*t);
	num=0;
}

/**函数功能:初始化T0**/
void init_T0(){
	TMOD=0x01;	//受TR0控制、定时器、方式1
	
	//想要计数50000次,则设定初值为19456(f=11.059)
	TH0=19456/256;
	TL0=19456%256;

}

void main()
{	
	init_T0();
	led1=0;

	EA=1;	//开总中断
	ET0=1;	//开定时器中断
	TR0=1; 	//使能定时器
	
	while(1){
		delay(1);
		delay_1s();
		led1=~led1;
	}
}

void time() interrupt 1		//T0中断序号为1
{
	num++;
}
  • 12
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值