0
点赞
收藏
分享

微信扫一扫

8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用


在前面九篇博文中,我们认识到了一些基于IO口输入与输出的基础电子器件使用:
《​​8051单片机实战分析(以STC89C52RC为例) | 01 - 点亮一个LED​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 02 - LED延时约5s闪烁​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 03 - LED流水灯​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 04 - 蜂鸣器驱动​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 05 - 静态数码管驱动​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 06 - 动态数码管驱动​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 07 - 独立按键驱动​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 08 - 矩阵按键驱动​​》
《​​8051单片机实战分析(以STC89C52RC为例) | 09 - LED点阵显示数字​​》
但现在我们要开始回到8051单片机内部,通过实战来认识它们的工作原理,你会发现通过它们可以去开发一些更有意思的东西!

这篇博文带领大家认识一下STC89C52RC单片机外部中断的使用,如果你不了解什么是中断,建议你先看这篇:
《​​STC89C52RC单片机额外篇 | 01 - 认识中断、中断源以及中断优先级​​》

1 中断系统结构

以下这张图是从中断引脚到中断入口所经过的通道:


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_51单片机

从图中不难看出​​INT0​​​与​​INT1​​​是中断引脚,其中经过了​​TCON、IE、IP​​这些寄存器,因此我们在写程序时得把这些寄存器功能配置好,CPU才会按照我们的想法只执行!下面分别对这些寄存器进行介绍(稍微了解一下即可,忘记的时候再查)。

1.1 TCON寄存器

TCON(Timer Control Register),中文叫定时器/计数器控制寄存器,TCON寄存器是用于中断触发方式设置以及中断标志。


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_嵌入式_02

各寄存器位的作用如下:

TCON寄存器位

作用

​TF0(TF1)​

计数溢出标志位。当计数器计数溢出时,该位置​​1​

​TR0(TR1)​

定时器运行控制位。当​​TR0(TR1)=0​​​停止定时器/计数器工作;当​​TR0(TR1)=1​​启动定时器/计数器工作

​IE0(IE1)​

外中断请求标志位。当CPU采样到​​P3.2(P3.3)​​​出现有效中断请求时,此位由硬件置1。在中断响应完成后转向中断服务时,再由硬件自动清​​0​

​IT0(IT1)​

外中断请求信号方式控制位。当​​IT0(IT1) =1​​​ 脉冲方式(后沿负跳有效);当​​IT0(IT1)=0​​​电平方式(低电平有效)此位由软件置​​1​​​或清​​0​

​TF0(TF1)​

计数溢出标志位。当计数器产生计数溢出时,此位由硬件置​​1​​​。当转向中断服务时,再有硬件自动清​​0​​。计数溢出的标志位的使用有两种情况:采用中断方式时,作中断请求标志位来使用;采用查询方式时,作查询状态位来使用

1.2 IE寄存器

IE(Interrupt Enable),中文叫中断允许寄存器,它的作用是控制所有中断源的开放或禁止,以及每个中断源是否被允许。

8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_单片机_03

各寄存器位的作用如下:

IE寄存器位

作用

​EA​

​EA = 0​​​时,所有中断禁止(即不产生中断);​​EA = 1​​时,各中断的产生由个别的允许位决定

​ES​

串行口​​RX/TX​​中断允许

​ET1​

定时器​​T1​​中断允许

​EX1​

外中断​​INT1​​中断允许

​ET0​

定时器​​T0​​中断允许

​EX0​

外部中断​​INT0​​中断允许

1.3 IP寄存器

IP(Interrupt Priority),中文叫中断优先级寄存器,它是用来设定各个中断源属于两级中断中的哪一级。

8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_嵌入式_04

各寄存器位的作用如下:

IP寄存器位

作用

​PS​

串行口​​RX/TX​​中断优先

​PT1​

定时器​​T1​​中断优先

​PX1​

外中断​​INT1​​中断优先

​PT0​

定时器​​T0​​中断优先

​PX0​

外部中断​​INT0​​中断优先

2 原理图

下面我们进行例子来学习外部中断​​INT0​​​与​​INT1​​的使用,例子很简单:使用外部按键模拟外部中断源,当发生外部中断的时候,我们给一个LED灯的电位值取反。下面我们通过原理图来看看要用到的引脚:

① 单片机:


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_中断_05

② 独立按键:


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_51单片机_06

③ 上拉电阻:


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_51单片机_07

④ LED灯:


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_中断_08

3 程序

① 中断服务函数:

我们知道我们编写的C程序,函数的执行是从main主函数开始执行,现在有了中断,自然就产生一个中断服务函数:


8051单片机实战分析(以STC89C52RC为例) | 10 - 外部中断的使用_中断_09

从图中我们可以知道单片机在发生中断的时候,程序的执行过程会从主程序A跳到中断服务程序B,在执行完中断服务程序B后,会返回到之前主程序A被中断打断处继续执行程序。

那么我们如何指定中断服务程序?具体参考以下模板(对于函数名你可以随便写,当然最好贴近有意义的命名)。

外部中断0的中断服务函数:

void Int0() interrupt 0
{
... // 中断服务程序中要执行内容
}

定时器0的中断服务函数:

void Timer0() interrupt 1
{
... // 中断服务程序中要执行内容
}

外部中断1的中断服务函数:

void Int1() interrupt 2
{
... // 中断服务程序中要执行内容
}

定时器1的中断服务函数:

void Timer1() interrupt 3
{
... // 中断服务程序中要执行内容
}

串行口的中断服务函数:

void Serial() interrupt 4
{
... // 中断服务程序中要执行内容
}

② 使用外部中断0控制LED:

#include "reg52.h"       //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;

sbit k3=P3^2; //定义按键K3
sbit led=P2^0; //定义P20口是led

/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}

/*******************************************************************************
* 函 数 名 : Int0Init()
* 函数功能 : 初始化外部中断0
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0Init()
{
//设置INT0,只有一个中断不需要考虑优先级
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}

/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Int0Init(); // 初始化外部中断0
while(1);
}

/*******************************************************************************
* 函 数 名 : Int0() interrupt 0
* 函数功能 : 外部中断0的中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/

void Int0() interrupt 0 //外部中断0的中断函数
{
delay(1000); //延时消抖
if(k3==0)
{
led=~led;
}
}

③ 使用外部中断1控制LED:

#include "reg52.h"       //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;

sbit k4=P3^3; //定义按键K4
sbit led=P2^0; //定义P20口是led

/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}

/*******************************************************************************
* 函 数 名 : Int1Init()
* 函数功能 : 初始化外部中断1
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int1Init()
{
//设置INT1,只有一个中断不需要考虑优先级
IT1=1;//跳变沿出发方式(下降沿)
EX1=1;//打开INT1的中断允许。
EA=1;//打开总中断
}

/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Int1Init(); // 初始化外部中断1
while(1);
}

/*******************************************************************************
* 函 数 名 : Int1() interrupt 2
* 函数功能 : 外部中断1的中断服务函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/

void Int1() interrupt 2 //外部中断1的中断服务函数
{
delay(1000); //延时消抖
if(k4==0)
{
led=~led;
}
}

④ 简要分析:

  1. 主程序首先执行中断初始化函数。
  2. 在中断初始化函数中,因为8051单片机这些中断相关的寄存器支持位操作,所以直接以位操作的形式写入​​TCON、IE​​这些寄存器,分别设置中断触发方式与打开中断接口,以及总中断,最好的理解回顾之前的中断系统结构图。
  3. 在中断服务程序中,我们在延时消除按键抖动后再进行按键判断,确认按键按下后进行LED电位反转。


举报

相关推荐

0 条评论