Bootstrap

51单片机基础6——定时器中断控制LED灯闪烁

51单片机定时器中断控制LED闪烁

1. 软硬件条件

  • 单片机型号:STC89C52RC
  • 继电器模块:FL-3FF-S-Z
  • LED小灯泡:高电平亮
  • 开发环境:KEIL4
  • 烧录软件:stc-isp
  • 433m遥控器与解码器

2. 定时器中断原理

2.1 中断部分概念

中断:CPU 暂停当前执行程序转而执行临时发生的事件的过程。
中断源:引发中断的事件。
中断申请:中断源向CPU 发起处理请求。
中断响应过程:CPU暂停当前处理事件转而处理中断事件的过程。
中断系统:支持中断功能的部件。
中断服务程序:中断过程中CPU所执行的程序。
中断断点:被中断程序所中断的正要执行的指令的地址。
在这里插入图片描述

2.2 定时器中断

即,在到达设定时间之后CPU 需要暂停当前程序转而执行中断服务程序。

2.3 时钟周期

也称之为震荡周期,是时钟频率的倒数,在单片机中晶振震荡频率为 11.0592M Hz。
T 时钟周期 = 1 f 晶振频率 T_{时钟周期} = \frac{1}{f_{晶振频率}} T时钟周期=f晶振频率1

2.4 机器周期

在计算机中为了方便管理,将执行指令的过程分为多个阶段,每一个阶段完成一个基本动作,完成一个基本动作所需要的时间就是机器周期。一个机器周期由若干个时钟周期组成。在单片机中一般是12个或者6个。
T 机器周期 = 12 ∗ T 时钟周期 = 1.085 u s T_{机器周期} = 12*T_{时钟周期} = 1.085us T机器周期=12T时钟周期=1.085us

3. 定时器编程

51单片机定时器需要用到多个寄存器,分别是TMOD、TCON、THx、TLx。
以定时器0为例:
在这里插入图片描述
其中TCON 可以按位寻址,可以直接定义每一位的状态。TMOD 不可按位寻址,需要整个8位同时定义。

3.1 TMOD模式寄存器

在这里插入图片描述

M0M1模式
0013位定时器/计数器,兼容8048定时模式,TL1只用低5位参与分频,TH1整个8位全用。
0116位定时器/计数器,TL0、TH0全用
108位自动重装载定时器,当溢出时将TH0存放的值自动重装入TL0
11定时器0此时作为双8位定时器/计数器。TL0作为一个8位定时器/计数器,通过标准定时器0的控制位控制。TH0仅作为一个8位定时器,由定时器1的控制位控制。

一般情况下使用定时器0,的16位定时器模式。

TMOD &= 0xF0; // 保留高位 清空低位
TMOD |= 0x01; // 保留高位 设置低位

不推荐采用直接赋值,容易破坏定时器1的配置。

3.2 TCON 控制寄存器

在这里插入图片描述
同样以T0为例:

  • TF0:定时器计数器中断溢出标志位,溢出时,硬件至1,向CPU提出中断请求,CPU响应中断时,由硬件置0
  • TR0:定时器0运行标志由软件置位与清零。当TR0=0时,禁止计数, 当TR0=1,GATE(TMOD.3) = 0,允许T0计时;当GATE(TMOD.3) = 1,记录~INT0高电平接收个数。
3.3 中断方式寄存器

在这里插入图片描述

  • EA:CPU的总中断允许控制位,EA=1,CPU开放中断,EA=0,CPU屏蔽所有的中断申请。EA的作用是使中断允许形成两级控制。即各中断源首先受EA控制:其次还受各中断源自己的中断允许控制位控制。
  • ET0:T0的溢出中断允许位。ET0=1,允许T0中断;ET0=0禁止T0中断。
  • ET1:定时/计数器T1的溢出中断允许位。ET1=1,允许T1中断;ET1=0,禁止T1中断。

4. 代码实现

查询方式,没有直接声明中断服务程序

#include "reg52.h"


sbit greenLed = P2^2;
sbit D0 = P1^1;
sbit sw = P1^5;
void Timer0Init(){

	TMOD &= 0xF0;
	TCON |= 0x01;
	//10ms后溢出
	TL0 = 0x00;
	TH0 = 0xDC;
	ET0 = 1;
	EA = 1;
	TF0 = 0;
	TR0 = 0;
}

void init(){
	sw = 0;
	D0 = 0;
	greenLed = 0;
	Timer0Init();
}
void main(){
	int cnt = 0;
	init();
	while(1){
		if(D0==1){
			greenLed = 0;
			sw = !sw;
			TR0 = !TR0;
			while(D0 == 1);
		}
		if(TF0 == 1){
				TF0 = 0; // 没有中断服务程序 没有跳转,一直在主程序
				TL0 = 0x00;
				TH0 = 0xDC;
				cnt++;
				if(cnt == 20){
						greenLed = !greenLed;
						cnt = 0;
				}
		}
	}

}

中断服务方式需要知道中断服务号 定时器0中断服务号为1。

#include "reg52.h"


sbit greenLed = P2^2;
sbit D0 = P1^1;
sbit sw = P1^5;



int cnt = 0;
void Timer0Init(){

	TMOD &= 0xF0;
	TCON |= 0x01;
	//10ms后溢出
	TL0 = 0x00;
	TH0 = 0xDC;
	ET0 = 1;
	EA = 1;
	TF0 = 0;
	TR0 = 0;
}

void Timer0Handler() interrupt 1{ // 中断服务程序
	cnt++;
	TL0 = 0x00;
	TH0 = 0xDC;
	cnt++;
	if(cnt == 20){
		greenLed = !greenLed;
		cnt = 0;
	}
}
void init(){
	sw = 0;
	D0 = 0;
	greenLed = 0;
	Timer0Init();
}

void main(){
	init();
	while(1){
		if(D0==1){
			greenLed = 0;
			sw = !sw;
			TR0 = !TR0;
			while(D0 == 1);
		}
	}

}
;