【51单片机实验笔记】中断篇(一) 外部中断


前言

中断是单片机非常重要的概念,类似于软件中回调的作用。前面几章我们都是主动驱动元器件工作,但如果单片机需要被动地响应外部的信息时,中断的重要性就凸显出来了。从本章节开始,我们要开始直接操作中断相关的寄存器,由于偏底层,学起来可能没有之前几章那么轻松。


中断系统概述

中断涉及的概念比较多,先阐释如下:

  • 轮询依次询问每一个IO设备,如果检测到需要提供服务,立刻执行服务,再询问下一个设备。
    • 适用场景频繁需要服务的外设
    • 特点
      • 优点:实现简单
      • 缺点:消耗大量CPU资源。慢速的IO交互无需大量频繁的检测
  • 中断:当外部设备需要服务时,CPU接收到中断请求立刻停止当前程序,转而执行中断服务程序,执行结束后,回到原先处继续执行。
    • 适用场景慢速交互的情况
    • 特点
      • 优点实时性高、即刻响应、节约CPU资源
      • 缺点:实现稍复杂
  • 中断源:发生中断的源头传统51单片机中一般至少有5个基础的中断源(按自然优先级排列)。
    • 外部中断0INT0
    • 定时器0中断T0
    • 外部中断1INT1
    • 定时器1中断T1
    • 串口中断UART
  • 中断优先级
    • 自然优先级:当几个中断同时向CPU发出请求,CPU会根据中断自然优先级依次处理。
    • 抢占优先级:当进入某个中断时,发生了优先级更高中断,CPU会打断低优先级中断,转而执行高优先级中断,形成中断嵌套同级不会打断传统51单片机只有2个优先级,设置寄存器IP即可更改默认排序,一般保持默认即可。
  • 中断嵌套:在执行中断服务函数的过程中,有优先级更高中断发生,会暂停当前中断执行,转而执行更高级中断程序。即形成嵌套
  • 中断请求中断源CPU申请中断
  • 中断响应CPU接收到中断请求转去执行中断服务程序的行为。
  • 中断服务程序:由开发者预先定义(关键字interrupt + 中断号),处理相应的中断事件。原则上,不要在中断中写任何阻塞程序,以保证其实时性
  • 中断号:是CPU进入对应中断服务程序重要标志,不同的中断源对应不同的中断号
  • 中断返回:执行完对应中断服务程序后,返回中断点处继续往下执行。
  • 中断点:主函数被中断的地方。
中断源 优先级 中断请求标志位 中断允许标志位 中断号
I N T 0 ‾ \overline{INT0} INT0 0 IE0 EX0/EA 0
T 0 T0 T0 1 TF0 ET0/EA 1
I N T 1 ‾ \overline{INT1} INT1 2 IE1 EX1/EA 2
T 1 T1 T1 3 TF1 ET1/EA 3
U A R T UART UART 4 RI/TI ES/EA 4
T 2 T2 T2 5 TF2 ET2/EXF2/EA 5
I N T 2 ‾ \overline{INT2} INT2 6 IE2 EX2/EA 6
I N T 3 ‾ \overline{INT3} INT3 7 IE3 EX3/EA 7

注:T2定时器,外部中断INT2INT3STC89C52RC系列新增外设

以上那么多概念,其实都是很重要的,所以建议大家好好读一读,能对中断系统有一个总体的感知。虽然理论上,上述寄存器都会用到,但也没有必要强行记忆,多写两次,你就会看这些寄存器非常眼熟了,实在记不清也可以来我的博客再回忆一遍哈~

下面对中断系统做一个小结
中断系统主要是解决高速CPU慢速人机交互所造成的CPU资源浪费问题。适用于被动响应场景。试想,对于按键检测,如果将它放在循环里不断检测,人按下按键的过程至少是毫秒级别的,而等待按下的时间更是漫长,而此刻CPU已经循环检测了上万次,这显然是一种无意义的检测。

而这时中断的优势就体现出来了,将按键响应的代码放在中断服务函数里,只有当按键被按下时,才会执行。这样大大节约了CPU的资源。

那么我们怎么去利用中断呢,需要介绍以下几种寄存器


寄存器说明

中断优先级寄存器(IP)

寄存器 7 6 5 4 3 2 1 0
IP - - PT2 PS PT1 PX1 PT0 PX0
  • 中断优先级寄存器(IP)控制中断的抢占优先级。字节地址B8H
    • PX0:外部中断INT0中断优先级控制位,置1为高优先级,置0为低优先级。
    • PT0:外部定时器T0中断优先级控制位
    • PX1:外部中断INT1中断优先级控制位
    • PT1:外部定时器T1中断优先级控制位
    • PS串口中断优先级控制位
    • PT2:外部定时器T2中断优先级控制位(新增)

注:STC89C52单片机可以通过配置 IP寄存器IPH寄存器实现4个抢占优先级。详见芯片手册,本文不做介绍。


中断允许控制寄存器(IE)

寄存器 7 6 5 4 3 2 1 0
IE EA - ET2 ES ET1 EX1 ET0 EX0
  • 中断允许控制寄存器(IE)控制中断的使能开关。字节地址A8H
    • EX0:外部中断INT0允许位,置1(高)开,置0(低)关。
    • ET0:外部定时器T0允许位
    • EX1:外部中断INT1允许位
    • ET1:外部定时器T1允许位
    • ES串口中断允许位
    • ET2:外部定时器T2允许位(新增)
    • EA关总中断允许位,是控制所有中断使能的总开关。

中断请求标志寄存器(TCON)

寄存器 7 6 5 4 3 2 1 0
TCON TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
  • 中断请求标志寄存器(TCON)设置中断的发生方式。字节地址88H
    • IT0:外部中断INT0触发方式控制位,置0为低电平触发,置1为下降沿触发(常用
    • IE0:外部中断INT0请求标志位,发生中断请求时,由硬件自动置1,响应后自动置0
    • IT1: 外部中断INT1触发方式控制位
    • IE1:外部中断INT1请求标志位
    • TR0:定时器T0运行控制位置1为开始运行,置0停止运行。
    • TF0:定时器T0溢出中断请求标志位,发生溢出中断请求时,硬件自动置1,响应后自动置0
    • TR1:定时器T1运行控制位
    • TF1:定时器T1溢出中断请求标志位

外部中断配置

STM32系列单片机每个引脚都可以配置中断,而传统的51单片机只有2个引脚外部中断STC89C52单片机共有4个外部中断引脚,分别为P3.2–INT0、P3.3–INT1、P4.3–INT2、P4.2–INT3,其中,外部中断2和3的配置还需要用到XICON寄存器)。

了解了上述3个寄存器之后,配置引脚外部中断其实很简单。具体配置流程如下(以INT0为例):

  1. 设置外部中断触发方式为下降沿触发 IT0 = 1;
  2. 使能外部中断 EX0 = 1;
  3. 打开关总中断 EA = 1;

软件实现

按键事件的外部中断实现

实验现象为,按下第四个独立按键P3.3),第一个LEDP2.0亮灭翻转

delay.h

#ifndef _DELAY_H_
#define _DELAY_H_

#include <REGX52.H>

#define false 0
#define true 1

typedef unsigned char u8;
typedef unsigned int u16;

void delay_10us(u16);
void delay_ms(u16);

#endif

delay.c

#include "delay.h"
/** 
 **  @brief    通用函数
 **  @author   QIU
 **  @data     2023.08.23
 **/

/*-------------------------------------------------------------------*/

/**
 **  @brief   延时函数(10us)
 **  @param   t:0~65535,循环一次约10us
 **  @retval  无
 **/
void delay_10us(u16 t){
    
    
	while(t--);
}

/**
 **  @brief   延时函数(ms)
 **  @param   t:0~65535,单位ms
 **  @retval  无
 **/
void delay_ms(u16 t){
    
    
	while(t--){
    
    
		delay_10us(100);
	}
}

interrupt.h

#ifndef __INTERRUPT_H__
#define __INTERRUPT_H__

#include "delay.h"

void INT0_init();
void INT1_init();
	
#endif

interrupt.c

#include "interrupt.h"
/** 
 **  @brief    外部中断封装
 **  @author   QIU
 **  @data     2023.08.23
 **/

/*-------------------------------------------------------------------*/

/**
 **  @brief   配置外部中断0
 **  @param   无
 **  @retval  无
 **/
void INT0_init(){
    
    
	IT0 = 1; // 设置外部中断0触发方式,下降沿触发
	EX0 = 1; // 使能外部中断0
	EA = 1;  // 使能总中断
}

/**
 **  @brief   配置外部中断1
 **  @param   无
 **  @retval  无
 **/
void INT1_init(){
    
    
	IT1 = 1; // 设置外部中断1触发方式,下降沿触发
	EX1 = 1; // 使能外部中断1
	EA = 1;  // 使能总中断
}

// 外部中断0的中断服务程序模板
//void INT1_serve() interrupt 0{
    
    
//	;
//}

// 外部中断1的中断服务程序模板
//void INT1_serve() interrupt 2{
    
    
//	;
//}

main.c

#include "delay.h"
#include "interrupt.h"
/** 
 **  @brief    以外部中断方式响应按键事件
 **  @author   QIU
 **  @data     2023.08.31
 **/

/*-------------------------------------------------------------------*/

// 定义引脚
sbit btn4 = P3^3;
sbit LED1 = P2^0;


void main(){
    
    
	INT1_init();
	while(1);
}


void INT1_serve() interrupt 2{
    
    
	
	if(btn4 == 0){
    
    
		delay_ms(10);
		// 按下消抖
		if(btn4 == 0){
    
    
			LED1 = !LED1;	
		}
	}
}

本例简单演示了如何使能外部中断,其意义在于,将慢速的按键响应放在中断中而非主程序中检测处理,这显然比轮询方法更加高效,节约了CPU的资源。

但与此同时,我们知道,中断服务程序中不宜处理耗时的程序,这也是本例存在的缺陷,仅仅使用外部中断不能完美解决按键检测的问题,因为按键存在抖动这一客观事实。在下一个章节,我们将使用定时器完成按键消抖。它比延时函数更加优雅,且进一步提升由于延时所消耗的性能


遇到的问题

  • 如果使能中断就必须书写中断服务程序,并正确书写中断号。否则程序进入中断卡死
  • 开发板上P3.2引脚外部中断INT0,除了接独立按键,还接了红外接收装置,可能会产生串扰。建议查看开发板原理图

总结

外部中断使得CPU可以免于无谓等待的消耗,从而集中处理更加重要事情上。单片机的性能得以充分利用。

猜你喜欢

转载自blog.csdn.net/m0_46500149/article/details/128518889