ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

4.2 51单片机-中断

2021-11-11 21:02:01  阅读:133  来源: 互联网

标签:定时器 优先级 4.2 中断 void 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+系列单片机复位后IP和IPH均为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,中断,void,51,单片机,低优先级,外部
来源: https://blog.csdn.net/xiaolong1126626497/article/details/121018075

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有