4.2 51单片机-中断

Posted DS小龙哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4.2 51单片机-中断相关的知识,希望对你有一定的参考价值。

4.2 中断

4.2.1 中断介绍

中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的

当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完完后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断,实现这种功的部件称为中断系统,请示CPU中断的请求源称为中断源。

微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别,CPU总是先响应优先级别最高的中断请求。

当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序),发生了另外一个优先级比它还高的中断源请求;如果CPU能够暂停对原来中断源的服务程序,转而去处理优先级更高的中断请求源,处理完以后再回到原来低级中断服务程序,这样的过程称为中断嵌套。这样的中断系统称为多级中断系统,没有中断嵌套功能的中断系统称为单级中断系统。

4.2.2 STC90C51RD系统中断源介绍

STC90C51RC/RD+系列单片机提供了8个中断请源,它们分别是:外部中断0(INT0)、定时器0中断、外部中断1(INT1)、定时器1中断、定时器2中断、串口(UART)中断、外部中断2(INT2)、外部中断3(INT3)

所有的中断都具有4个中断优先级,用户可以用关总中断允许位(EA/IE.7)或相应中断的允许位,屏蔽所有的中断请求,也可以打开相应的中断允许位使CPU响应相应的中断申请;每一个中断源可以用软件独立地控制开中断或关中断状态;每一个中断的优先级别均可用软件设置。高优先级的中断请求可以打断低优先级的中断,反之,低优先级的中断请求不可以打断高优先级及同优先级的中断。当两个相同优先级的中断同时产生时,将由查询次序来决定系统先响应哪个中断。

4.2.3 中断的优先级与中断结构图

图4-2-1 中断优先级表

通过设置新增加的特殊功能寄存器IPH中的相应位,可将中断优先级设为四级,如果设置IP或XICON,那么中断优先级就只有两级,与传统8051单片机两级中断优先级完全兼容。

图4-2-2 中断结构图 

 

图4-2-3 中断相关寄存器

4.2.4 中断服务函数

中断服务函数的名字只要符合C语言标识符的命名规则,可以随意取,需要注意的地方是: 中断服务函数没有返回值,没有形参,也不需要单独去声明,并且函数名称体的右边需要使用interrupt关键字声明,interrupt是中断特有的关键字,在interrupt关键字后面可以增加数字,这个数字是根据中断优先级编号来的(可以看4.2.3小节的中断优先级表)。

使用C语言编程,中断查询次序号就是中断号,C51所有的中断服务函数编写如下:

void EXTI0_IRQHandler(void) interrupt 0 //外部中断0
{
    /*code block*/
}
void TIM0_IRQHandler(void) interrupt 1  //定时器0
{
    /*code block*/
}
void EXTI1_IRQHandler(void) interrupt 2 //外部中断1
{
    /*code block*/
}
void TIM1_IRQHandler(void) interrupt 3  //定时器1
{
    /*code block*/
}
void UART_IRQHandler(void) interrupt 4  //串口
{
    /*code block*/
}
void TIM2_IRQHandler(void) interrupt 5  //定时器2
{
    /*code block*/
}
void EXTI2_IRQHandler(void) interrupt 6 //外部中断2
{
    /*code block*/
}
void EXTI3_IRQHandler(void) interrupt 7 //外部中断3
{
    /*code block*/
}

4.2.5 中断控制寄存器介绍

51单片机CPU对中断源的开放或者屏蔽,每一个中断源是否被允许中断,是由内部的中断允许寄存器IE(地址为A8H)和XICON(地址为C0H)控制的,寄存器IE的格式如下:

图4-2-4

EA : CPU的总中断允许控制位, EA=1,CPU开放中断, EA=0, CPU屏蔽所有的中断申请。EA的作用是使中断允许形成两级控制。即各中断源首先受EA控制;其次还受各中断源自己的中断允许控制位控制。

ET2: 定时/计数器T2的溢出中断允许位,ET2=1,允许T2中断; ET2=0,禁止T2中断。

ES : 串行口1中断允许位。ES=1,允许串行口1中断; ES=0,禁止串行口1中断。

ET1: 定时/计数器T1的溢出中断允许位。ET1=1,允许T1中断; ET1=0,禁止T1中断。

EX1 : 外部中断1中断允许位。EX1=1,允许外部中断1中断; EX1=0,禁止外部中断1中断。

ET0 : T0的溢出中断允许位。ET0=1,允许T0中断; ET0=0禁止T0中断。

EX0 : 外部中断0中断允许位。 EX0=1,允许中断; EX0=0禁止中断。

4.2.6 配置定时器0使用中断(8位模式)

下面代码里配置51单片机的定时器0工作在8位定时器自动重装载模式,并开启了溢出中断,在自动重装载模式下,每次定时器溢出之后,会自动重装载,就省去了手动赋重装值的过程,比较方便,但是定时器的每次最大定时时间变短了,计数器到达255就会溢出。

程序里封装了计算重装值的函数,方便调用,程序开启了溢出中断,定时器时间到达后会进入到中断服务函数,中断服务函数里使用了一个计数变量,用于记录定时器的超时次数,时间到达500毫秒时,就改变一次LED灯的状态。

(硬件平台说明:CPU是STC90C516RD 、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)

示例代码:

#include <reg51.h>
int main()
{
    Timer0_8bit_Init(100);  //配置定时器超时的时间为100us
    LED=0x00; //关闭所有灯
    while(1)
    {
        
    }
}
/*
配置定时器0工作在8位自动重装载模式
注意,时间不能超过定时器最大时间
255*(12/11.059200)=276us
*/
void Timer0_8bit_Init(u16 us)
{   
    //当前实验板上的晶振实际频率为: 11.956MHZ
    u16 val=us/(12/11.956); //得到计数的时间,只要整数部分
    TMOD&=0xF0;     //清除配置
    TMOD|=0x02;     //配置定时器0工作在8位自动重载模式
    TL0=TH0=255-val;//得到重装载值;
    EA=1;           //开启总中断
    ET0=1;          //开启定时器0溢出中断
    TR0=1;          //启动定时器0
}

/*
定时器0的中断服务函数
*/
u32 cnt=0;
void TIM0_IRQHandler(void) interrupt 1
{
    //使用了中断,就不需要手动清除标志位,硬件会自动清除
    cnt++;//记录超时次数
    if(cnt==10*500) //500ms
    {
        cnt=0;
        LED=~LED;
}
}

4.2.7 配置定时器1使用中断(16位模式)

下面代码里配置51单片机的定时器1工作在16位定时器模式。程序封装了计算重装值的函数,方便调用,程序里开启了溢出中断,在中断服务函数里使用了一个计数变量,记录定时器超时的次数,时间到达1秒钟,就是改变一次LED灯的状态。

(硬件平台说明:CPU是STC90C516RD 、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)

示例代码:

#include <reg51.h>
u16 T1_Update_data;//定时器1的初始值
void Timer1_16bit_Init(u16 us)
{   
    //当前实验板上的晶振实际频率为: 11.956MHZ
    u16 val=us/(12/11.956); //得到计数的时间,只要整数部分
    T1_Update_data=65535-val; //得到重装载值
    TMOD&=0x0F;            //清除配置
    TMOD|=0x10;            //配置定时器1工作在16位定时器模式
    TH1=T1_Update_data>>8; //定时器1高位重装值
    TL1=T1_Update_data;    //定时器1低位重装值
    EA=1;                   //开启总中断
    ET1=1;                  //开启定时器1溢出中断
    TR1=1;                 //启动定时器1
}

//定时器1的重装值更新函数
void Timer1_Update(void)
{
    TH1=T1_Update_data>>8; //定时器1高位重装值
    TL1=T1_Update_data;    //定时器1低位重装值
}

/*
定时器1的中断服务函数
*/
void TIM1_IRQHandler(void) interrupt 3  //定时器1
{
    //使用了中断,就不需要手动清除标志位,硬件会自动清除
    Timer1_Update(); //更新重装载值
    //使用了中断,就需要手动清除标志位,硬件会自动清除
    cnt++;//记录超时次数
    if(cnt==1000) //1000ms
    {
        cnt=0;
        LED=~LED;
    }
}
int main()
{
    Timer1_16bit_Init(1000);  //配置定时器超时的时间为1000us
    LED=0x00; //关闭所有灯
    while(1)
    {
        
    }
}

4.2.8 外部中断(EXTI)配置寄存器介绍

STC90C51有4个外部中断源,分别是:外部中断0(P3.2),外部中断1(P3.3),外部中断2(P4.3),外部中断3(P4.2)。

图4-2-5 外部中断1和0的IO口

图4-2-6 外部中断2和3的IO口

外部中断0和外部中断1的相关配置位在TCON寄存器里,TCON寄存器位如下表所示:

图4-2-7 外部中断0和1的配置寄存器

IE1外部中断1请求源(INT1/P3.3)标志。 当发生外部中断请求时 ,IE1会被CPU置1,在中断服务函数里需要将IE1清0。

IT1外部中断1源中断源类型选位。IT1=0,INT1/P3.3引脚上的低电平信号可触发外部中断1;IT1=1,外部中断1为下降沿触发方式。

IE0外部中断0请求源(INT0/P3.2)标志。 当发生外部中断请求时 ,IE0会被CPU置1,在中断服务函数里需要将IE0清0。

IT0外部中断0中断源类型选择位。IT0=0,INT0/P3.2引脚上的低电平可触发外部中断0;IT0=1,外部中断0为下降沿触发方式。

外部中断2和外部中断3的相关配置为在XICON寄存器里,XICON寄存器位如下表所示:

图4-2-8 外部中断2和3的配置寄存器

IE3 : 外部中断3中断请求标志位,中断条件成立后,IE3=1,可由硬件自动清零。

IT3 : 当此位由软件置位时(IT3=1),外部中断3为下降沿触发中断;当此位由软件清零时(IT3=0),为低电平触发中断。

IE2 : 外部中断2中断请求标志位,中断条件成立后,IE2=1,可由硬件自动清零。

IT2 : 当此位由软件置位时(IT2=1),外部中断2为下降沿触发中断;当此位由软件清零时(IT2=0),为低电平触发中断。

EX3 : 如被设置成1,允许外部中断3中断;如被清成0,禁止外部中断3中断。

EX2 : 如被设置成1,允许外部中断2中断;如被清成0,禁止外部中断2中断。

4.2.9 配置外部中断0下降沿触发示例

下面代码配置外部中断0采用下降沿触发,在外部中断0的服务函数里改变LED灯的状态。

外部中断0的复用IO是P3.2,在实验板上实验时,需要使用杜邦线把按键的一个引脚接在P3.2上,可以使用按键测试外部中断0的触发效果,由于实验板上的红外线遥控也是接的P3.2,为了不产生干扰,需要先将红外线遥控的跳线帽拔掉,再使用按键测试。

 图4-2-5

(硬件平台说明:CPU是STC90C516RD 、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)

示例代码:

#include <reg51.h>
int main()
{
    LED=0x00;
    EXTI0_Init();
    while(1)
    {
        
    }
}
/*
配置外部中断0下降沿触发中断
IO口: P3.2
*/
void EXTI0_Init(void)
{
   EA=1;  //开启总中断
   IT0=1; //外部中断0下降沿触发
   EX0=1; //允许外部中断0产生中断
}
/*
外部中断0中断服务函数
*/
void EXTI0_IRQHandler(void) interrupt 0
{
    LED=~LED; //改变LED灯的状态
    IE0=0; //清除外部中断0的标志位
}

4.2.10 中断优先级配置

传统8051单片机具有两个中断优先级,即高优先级和低优先级,可以实现两级中断嵌套。

STC90C51RC/RD+系列单片机通过设置新增加的特殊功能寄存器(IPH)中的相应位,可将中断优先级设置为4个中断优先级;如果设置IP,那么中断优先级只有两级,与传统8051单片机两级中断优先级完全兼容。

一个正在执行的低优先级中断能被高优先级中断所中断,但不能被另一个低优先级中断所中断。

上所述可归纳为下面两条基本规则:

1. 低优先级中断可被高优先级中断所中断,反之不能。

2. 任何一种中断(不管是高级还是低级),一旦得到响应,不会再被它的同级中断所中断

中断优先级的配置寄存器如下表所示:

图4-2-6

PX3H,PX3: 外部中断3优先级控制位:

当PX3H=0且PX3=0时,外部中断3为最低优先级中断(优先级0)

当PX3H=0且PX3=1时,外部中断3为较低优先级中断(优先级1)

当PX3H=1且PX3=0时,外部中断3为较高优先级中断(优先级2)

当PX3H=1且PX3=1时,外部中断3为最高优先级中断(优先级3)

PX2H, PX2: 外部中断2优先级控制位:

当PX2H=0且PX2=0时,外部中断2为最低优先级中断(优先级0)

当PX2H=0且PX2=1时,外部中断2为较低优先级中断(优先级1)

当PX2H=1且PX2=0时,外部中断2为较高优先级中断(优先级2)

当PX2H=1且PX2=1时,外部中断2为最高优先级中断(优先级3)

PT2H, PT2: 定时器2中断优先级控制位:

当PT2H=0且PT2=0时,定时器2中断为最低优先级中断(优先级0)

当PT2H=0且PT2=1时,定时器2中断为较低优先级中断(优先级1)

当PT2H=1且PT2=0时,定时器2中断为较高优先级中断(优先级2)

当PT2H=1且PT2=1时,定时器2中断为最高优先级中断(优先级3)

PSH,PS: 串口1中断优先级控制位:

当PSH=0且PS=0时,串口1中断为最低优先级中断(优先级0)

当PSH=0且PS=1时,串口1中断为较低优先级中断(优先级1)

当PSH=1且PS=0时,串口1中断为较高优先级中断(优先级2)

当PSH=1且PS=1时,串口1中断为最高优先级中断(优先级3)

PT1H, PT1: 定时器1中断优先级控制位:

当PT1H=0且PT1=0时,定时器1中断为最低优先级中断(优先级0)

当PT1H=0且PT1=1时,定时器1中断为较低优先级中断(优先级1)

当PT1H=1且PT1=0时,定时器1中断为较高优先级中断(优先级2)

当PT1H=1且PT1=1时,定时器1中断为最高优先级中断(优先级3)

PX1H, PX1: 外部中断1优先级控制位:

当PX1H=0且PX1=0时,外部中断1为最低优先级中断(优先级0)

当PX1H=0且PX1=1时,外部中断1为较低优先级中断(优先级1)

当PX1H=1且PX1=0时,外部中断1为较高优先级中断(优先级2)

当PX1H=1且PX1=1时,外部中断1为最高优先级中断(优先级3)

PT0H, PT0: 定时器0中断优先级控制位:

当PT0H=0且PT0=0时,定时器0中断为最低优先级中断(优先级0)

当PT0H=0且PT0=1时,定时器0中断为较低优先级中断(优先级1)

当PT0H=1且PT0=0时,定时器0中断为较高优先级中断(优先级2)

当PT0H=1且PT0=1时,定时器0中断为最高优先级中断(优先级3)

PX0H, PX0: 外部中断0优先级控制位:

当PX0H=0且PX0=0时,外部中断0为最低优先级中断(优先级0)

当PX0H=0且PX0=1时,外部中断0为较低优先级中断(优先级1)

当PX0H=1且PX0=0时,外部中断0为较高优先级中断(优先级2)

当PX0H=1且PX0=1时,外部中断0为最高优先级中断(优先级3)

中断优先级控制寄存器IP和IPH的各位都由可用户程序置“1”和清“0” 。但IP寄存器可位操作,所以可用位操作指令或字节操作指令更新IP的内容。而IPH寄存器的内容只能用字节操作指令来更新。

STC90C51RC/RD+系列单片机复位后IPIPH均为00H,各个中断源均为低优先级中断

4.2.11 配置外部中断0的优先级示例

下面代码初始化了外部中断0和外部中断1,在外部中断0 的初始化代码里,配置外部中断0的优先级为最高,在外部中断1的中断服务函数里写了一个死循环。

当外部中断1产生中断后,会卡死在中断服务函数里,这时可以触发外部中断0 ,测试外部中断0的中断服务函数是否可以执行(结果是可以执行的,因为外部中断0的优先级高于外部中断1的优先级,可以打断外部中断1的服务函数)。

实验上的测试过程说明:

外部中断0的复用IO是P3.2, 外部中断q的复用IO是P3.3,在实验板上实验时,需要使用杜邦线把按键1的引脚接在P3.2上,把按键2的引脚接在P3.3上,这样可以使用按键测试外部中断的触发效果,由于实验板上的红外线遥控接的是P3.2,为了不产生干扰,需要先将红外线遥控的跳线帽拔掉,再测试。

(硬件平台说明:CPU是STC90C516RD 、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)

示例代码:

#include <reg51.h>
int main()
{
    LED=0x00;
    EXTI0_Init();
    EXTI1_Init();
    while(1)
    {
        
    }
}
/*
配置外部中断0下降沿触发中断
IO口: P3.2
*/
sfr IPH=0xB7; //定义特殊功能寄存器
void EXTI0_Init(void)
{
   IPH|=1<<0; //配置PX0H=1 
   PX0=1;     //当PX0H=1且PX0=1时,外部中断0为最高优先级中断(优先级3)
   EA=1;  //开启总中断
   IT0=1; //外部中断0下降沿触发
   EX0=1; //允许外部中断0产生中断
}
/*
外部中断0中断服务函数
*/
void EXTI0_IRQHandler(void) interrupt 0
{
    LED=~LED; //改变LED灯的状态
    IE0=0; //清除外部中断0的标志位
}

/*
配置外部中断1下降沿触发中断
IO口: P3.2
*/
void EXTI1_Init(void)
{
   EA=1;  //开启总中断
   IT1=1; //外部中断1下降沿触发
   EX1=1; //允许外部中断1产生中断
}
/*
外部中断1中断服务函数
IO口: P3.3
*/
void EXTI1_IRQHandler(void) interrupt 2
{
    while(1){}  //死循环
    LED=~LED; //改变LED灯的状态
IE1=0; //清除外部中断1的标志位
}

以上是关于4.2 51单片机-中断的主要内容,如果未能解决你的问题,请参考以下文章

关于51单片机的外部中断使用方法

51单片机怎么设置外部中断?

51单片机中的定时器中断是怎么用的 ?

单片机中断程序P1=P1 0x80;

51单片机串口通讯

51单片机 INT0中断3位计数+Proteus仿真