外部中断介绍

  STC89C5X 系列单片机提供了4个外部中断:外部中断 O(INTO)、外部中断1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)。(注意:51 系列单片机一定有基本的 2 个外部中断,但不全有 4 个中断,需要查看芯片手册,通常我们都是使用基本的2个外部中断:INT0和INT1)

外部中断结构图

  图中INT0INT1即为外部中断0和外部中断1输入口。

  1. INT0 对应的是P3.2口的附加功能,可由IT0(TCON.0)选择其为低电平有效还是下降沿有效。当CPU检测到P3.2引脚上出现有效的中断信号时,中断标志IE0(TCON.1)置 1,向CPU申请中断。
  2. INT1 对应的是P3.3口的附加功能,可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当CPU检测到P3.3引脚上出现有效的中断信号时,中断标志IE1(TCON.3)置 1,向 CPU 申请中断。

中断允许控制

  CPU 对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE 控制的。

7 6 5 4 3 2 1 0
字节地址:A8H EA ES ET1 EX1 ET0 EX0 IE
  • EX0(IE.0) :外部中断0允许位
  • ET0(IE.1) : 定时/计数器T0中断允许位
  • EX1(IE.2) : 外部中断0允许位
  • ET1(IE.3) : 定时/计数器T1中断允许位
  • ES(IE.4) : 串行口中断允许位
  • EA(IE.7) : CPU中断允许(总允许)位

中断请求标志TCON

7 6 5 4 3 2 1 0
字节地址:88H TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 TCON
  • IT0(TCON.0) : 外部中断0触发方式控制位
    • IT0 = 0,为电平触发方式
    • IT0 = 1,为边沿触发方式(下降沿有效)
  • IE0(TCON.1) : 外部中断0中断请求标志位
  • IT1(TCON.2) : 外部中断1触发方式控制位
  • IE1(TCON.3) : 外部中断1中断请求标志位
  • TF0(TCON.5) : 定时/计数器T0溢出中断请求标志位
  • TF1(TCON.7) : 定时/计数器T1溢出中断请求标志位

外部中断配置

  在编写程序时通常我们会将外部中断的配置放到一个自定义函数内便于管理维护,如下所示:

1
2
3
4
5
6
void exit0_init()
{
IT0 = 1; // 跳变沿触发方式(下降沿触发)
EX0 = 1; // 打开INT0的中断允许
EA = 1; // 打开总中断
}

  当初发中断后即会进入中断服务函数,外部中断0中断服务函数如下:

1
2
3
4
void exit0 interrupt 0 // 外部中断0中断函数
{
// 执行所需的功能
}

  在中断函数中exit0时函数名,可自定义,但必须符合C语言标识符定义规则,interrupt时一个关键字,表示51单片机中断。后面“0”时中断号,外部中断0中断号为0,如果时外部中断1,则中断号为2

软件设计

  本实验要实现的功能时:使用独立按键K3控制LED灯亮灭

实物接线图
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "reg52.h"

// 对系统默认数据类型进行重命名
typedef unsigned int u16;
typedef unsigned char u8;

// 定义LED1管脚
sbit LED1 = P2^0;

// 定义独立按键K3控制脚
sbit KEY3 = P3^2;

/********************************************************************
*函数名: delay_10us
*函数功能:延时函数,ten_us=1时,大约延时10us
*输入: ten_us
*输出:无
*********************************************************************/
void delay_10us(u16 ten_us)
{
while(ten_us--);
}

/********************************************************************
*函数名: delay_ms
*函数功能: ms延时函数,ms=1时,大约延时1ms
*输入: ten_us
*输出:无
*********************************************************************/
void delay_ms(u16 ms)
{
u16 i,j;
for(i = ms;i > 0;i--)
for(j = 110;j > 0;j--);
}

/*******************************************************************************
*函数名: exti0_init
*函数功能:外部中断0配置函数
*输入:无
*输出:无
*******************************************************************************/
void exit0_init()
{
// 设置外部中断0为下降沿触发
IT0 = 1;
// 设置外部中断0的中断允许
EX0 = 1;
// 打开总中断
EA = 1;
}

void main()
{
exit0_init(); // 外部中断0配置

while(1)
{

}
}

void exit0() interrupt 0 // 外部中断0中断函数
{
delay_10us(1000); // 消抖
if(KEY3 == 0) // 再次判断K3键是否按下
LED1 = !LED1; // 翻转LED1状态
}

  我们在*exit0_init()*函数内就已经把按键管脚配置为外部中断0下降沿触发,当有按键按下,即会进入对应中断服务函数执行相应的功能程序,LED的控制就在中断函数内完成的。