单片机学习笔记 —— 定时器与中断

  今天来学习一个有用的新东西——定时器与中断,虽然刚学起来这个东西会让人感觉摸不着头脑,但仔细考虑一番还是不难的。

一、定时器概述

简介:MCS51系列的单片机通常有2个16位可编程定时/计数器,即定时器T0和T1,T0和T1均可分为高8位TH和低8位TL。与定时/计数器相关的有两个特殊功能寄存器:模式控制寄存器TMOD和控制寄存器TCON,它们控制了定时器的工作,如下图:

时间:16位的定时器/计数器实质上就是一个加1计数器。当定时器/计数器为定时工作方式时,计数器的加1信号由振荡器的12分频信号产生(1个机器周期);每过一个机器周期,计数器加1,直至计满溢出为止。因此,定时器的定时时间与系统的振荡频率有关。我们的晶振频率为12MHz,所以一次计数加一就是1us。




二、模式控制寄存器TMOD

TMOD构成
TMOD寄存器分为两组,高四位控制定时器T1,低四位控制定时器T0,构成如下:

GATEC/T*M1M0GATEC/TM1M0

如果我们使用一个定时器,那么只要设置对应的4位就可以了:

位符号描述
GATE门控位,为0时以TR1TR0来启动定时器运行,为1时依靠中断/TR启动定时器运行
C/T*为0:定时器模式 | 1时:计数器模式
M1+M0工作方式的选择,有4中工作方式

定时器的工作方式
加入我们使用的是T0定时器:

TMOD工作方式描述
0000 0000工作方式013位定时器
0000 0001工作方式116位定时器
0000 0010工作方式28位常数自动重新装载器
0000 0011工作方式3T0分为两个8位计数器



三、控制寄存器TCON

TCON构成

TF1TR1TF0TR0IE1IT1IE0IT0

功能描述
低四位与外部中断有关,高四位功能如下:
TF:计数溢出标志位,定时器/计数器T0或T1溢出时,由硬件自动将TF0或TF1置为“1”,并向CPU申请中断,CPU响应中断后,自动将TF清零。
TR:计数运行控制位,TRx=1时,启动计数器/定时器;TRx=0时停止定时器/计数器工作



三、定时器的工作

定时器/计数器初始化流程:

设置TMOD寄存器
装载计数器初始值
设置ETx允许中断
置位EA开启总中断
设置TCON的TRx 开启/停止计数器

EA:控制总中断
TRx:TCON的控制位,控制计时器Tx中断

下面是使用T0定时器定时1ms的初始化函数:

void Init()
{
	TMOD = 0X01;			// T0选择工作方式1
	TH = (65536-1000)/256;	//设定TH初始值
	TL = (65536-1000)%256;	//设定TL初始值
	ET0 = 1;				//开启定时器T0中断
	EA = 1;					//开启总中断
	TR0 = 1;				//开启定时器T0
}

  这里设置了定时器模式以及定时器TH和TL的初始值,这里设置了定时1000个及其周期,即1ms。之后设置了中断,最后开启定时器。


设置计时时间

如果我们要定时时间为t ms,包含1000*t个机器周期,则我们需要为T0预先填装初始值 2^16^-1=65535
设置 TH = (6535 - t*1000) / 256
设置 TL = (6535 - t*1000) % 256

例如,我们需要计时1ms,则T0初始值为(65535-1*1000) = 64535,对应的TH和TL分别为252和23。




四、中断的实现

当定时器T0/T1计数计满溢出时,会导致TCON的TF置位并向CPU申请中断,CPU响应中断,执行中断函数。

中断函数:一种当有中断发生时自动执行的函数,它不需要由主函数调用执行。执行完中断函数后,定时器/计数器重新计数。

函数定义

void funct() interupt N
{
	do_sonething();
}

描述:函数名后面加上了 inerrupt N 即interrupt加上1个数字,这个数字表示中断的级别。T0定时器的中断级别高于T定时器的中断级别,级别高的中断函数优先执行

举个栗子

void T0_process() interrupt 1
{
	TH = (65535 - 1000) / 256;
	TL = (65535 - 1000) % 256;
	count++;
	if (count == 100)
	{
		count = 0;
		led = ~led;
	}
}

描述:这个中断函数在中断时,重置了T0定时器的数值,同时,当发生了100次中断(1ms)的时候,led灯的电位变化一次,即led灯每200ms闪烁一次。




五、综合运用

先看一个使用工作方式2的计数器,TL0是8位的定时器,TH0是缓冲器,保存装载的数值。在发生中断时,自动将TH0的数值重装到TL0,TL0重新开始计数,这样可以减小软件带来的误差:

#include "STC15F2K60S2.H"
#define uint unsigned int
#define uchar unsigned char

sbit led_sel=P2^3;
sbit LED = P0^0;
uint count = 0;

void init()
{
	P0M1 = 0x00;	//设置推挽输出
	P0M0 = 0xff;
	P2M1 = 0x00;
	P2M0 = 0xf0;
	P0 = 0x00;
	led_sel = 1;
	
	TMOD = 0x02;	//设置定时器
	TH0 = (255 - 100);
	TL0 = (255 - 100);
	EA = 1;
	ET0 = 1;
	TR0 = 1;
}

void T0_process() interrupt 1
{
	count++;
}

void main()
{
	init();
	while (1)
	{
		if (count == 5000)
		{
			count = 0;
			LED = ~LED;
		}
	}
}

描述:在上面的程序中,我们使用了中断来计时,每一次中断时间为0.1ms,5000次就是0.5s,得到的结果就是led灯以1Hz的频率闪烁。同时可以发现,我们不需要每次中断时手动为T0重装数值。



第四篇单片机学习笔记完结,cheers ! ??

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值