中断问题(详解)
- 格式:doc
- 大小:140.00 KB
- 文档页数:4
单片机中断处理过程:中断响应中断处理中断返回
详解
中断处理过程可分为中断响应、中断处理和中断返回三个阶段。
中断响应
中断响应是CPU对中断源中断请求的响应,包括保护断点和将程序转向中断服务程序的入口地址(通常称矢量地址)。
中断响应过程
中断响应过程包括保护断点和将程序转向中断服务程序的入口地址。
首先,中断系统通过硬件自动生成长调用指令(LACLL),该指令将自动把断点地址压入堆栈保护(不保护累加器A、状态寄存器PSW和其它寄存器的内容),然后,将对应的中断入口地址装入程序计数器PC(由硬件自动执行),使程序转向该中断入口地址,执行中断服务程序。
MCS-51系列单片机各中断源的入口地址由硬件事先设定,分配如下:
中断源入口地址
外部中断00003H
定时器T0中断000BH。
7.1EXTI外部按键中断实验前面我们学习了,LED灯和按键。
实际上对于STM32来说,我们是学习了它的外设GPIO。
这一节我们前面学习的内容,学习STM32的EXTI (External interrupt),即外部中断。
前面的按键章节中,我们检测按键是否被按下的方式是轮询检测的方式,这里我们改为使用中断检测的方式,提高CPU的效率。
7.1.1什么是中断单片机中断系统的概念:什么是中断,我们从一个生活中的例程引入。
比如说你在做A 事,但是突然间来了你想起来了更重要的B事,所以你马上去做B事了,做完之后再回来继续做A事,这个就是中断。
7.1.2什么是单片机的中断?当CPU正在执行一个任务,但突然又发生了一个更高级的任务,CPU必须立即去执行的任务,所以CPU必须中断当前的任务,并保存该任务已经执行的状态和相关信息,然后转而去执行那个更加高级的任务,因此就引入了“中断”这个概念。
中断是指计算机在执行程序的过程中,当出现异常情况或特殊请求时,计算机停止现行程序的运行,转向对这些异常情况或特殊请求的处理,处理结束后再返回现行程序的间断处,继续执行原程序。
中断是单片机实时地处理内部或外部事件的一种内部机制。
当某种内部或外部事件发生时,单片机的中断系统将迫使CPU暂停正在执行的程序,转而去进行中断事件的处理,中断处理完毕后,又返回被中断的程序处,继续执行下去。
在程序里面也是一样的。
举个例子可能会容易懂点,定时中断:比如你定时1ms,主程序在运行,每当1ms时间到后,就跑到定时中断子程序里面执行,执行完后再回到主程序(中断程序是1ms中断一次)。
那对于整个系统来说中断能实现什么好处呢?下面我们给以说明:1)提高了CPU的效率CPU是计算机的指挥中心,它与外围设备(如按键、显示器等)通讯的方法有查询和中断2种:查询的方法是无论外围IO是否需要服务,CPU每隔一段时间都要依次查询一遍,这种方法CPU需要花费一些时间在做查询服务工作。
由于不少同学们,学习51单片机到了中断课程的时候,就开始进入一知半解的状态了,为此,开题一篇,以供大家搞明白,中断这回事。
我们还是用清晰点的逻辑来分析,围绕这四个部分来介绍,当然重点在于3和4部分。
通篇我会以让初学者都能看懂的语言来说明。
如果有专业一点的术语名词,我也尽量用简单易懂的描述。
注:本文旨在让大家理解什么是中断和怎么去设置。
具体的东西有些考虑到深浅问题,则跳过不讲。
如需了解,可自行查询资料1.什么是中断?2.为什么要有中断?3.中断怎么触发?4.怎么设置中断?什么是中断?举个老生常谈的例子——接电话。
在一个风和日丽的下午,你在电脑前看着视频,突然间,你桌上的手机来电话了,这时候你就该暂停视频,拿起手机接电话。
OK,回到单片机里来,我们之前写程序,都是在main函数里,甚至main 函数里的while(1)里执行我们的程序。
这就相当于这个例子中的【看视频】,而【电话响了】这个过程,就相当于产生了中断,而【接电话】就是你在中断里做的事情。
为什么要有中断?为什么要有中断,再举一个例子好了。
简单来讲,就是一些程序我们平时不执行,但到了某个特殊时刻,我们才去执行。
所以我们就让这个特殊时刻产生一个中断,这时候,就跳去了我们特殊时刻才执行的函数里了。
什么情况会触发中断?那么,我们什么情况下,单片机才会识别到中断,或者说,什么情况下,单片机才会跳入我们中断的函数里呢?简单来讲,我们的中断大致分为三种,外部中断、定时器中断、串口中断。
这三种的触发方式不一样。
外部中断:顾名思义,就是单片机外部出现了一定的情况,才进入了中断。
89c51有两个外部中断,一个是P3.2引脚,一个是P3.3引脚。
分别是外部中断0和外部中断1。
我们以外部中断0为例,当P3.2这个脚读到一个低电平(0)或者下降沿(由高电平变低电平)的时候,这时单片机自己就识别到了,所以就会自己跳入中断。
定时器中断:定时器中断不再这详细说明,大致是讲,我们可以设置一个时间(或者叫闹钟),然后这个单片机会开始计时,当到了这个时间点,单片机就会跳入中断。
单片机外部中断详解及程序单片机在自主运行的时候一般是在执行一个死循环程序,在没有外界干扰(输入信号)的时候它基本处于一个封闭状态。
比如一个电子时钟,它会按时、分、秒的规律来自主运行并通过输出设备(如液晶显示屏)把时间显示出来。
在不需要对它进行调校的时候它不需要外部干预,自主封闭地运行。
如果这个时钟足够准确而又不掉电的话,它可能一直处于这种封闭运行状态。
但事情往往不会如此简单,在时钟刚刚上电、或时钟需要重新校准、甚至时钟被带到了不同的时区的时候,就需要重新调校时钟,这时就要求时钟就必须具有调校功能。
因此单片机系统往往又不会是一个单纯的封闭系统,它有些时候恰恰需要外部的干预,这也就是外部中断产生的根本原由。
实际上在第二个示例演示中,就已经举过有按键输入的例子了,只不过当时使用的方法并不是外部中断,而是用程序查询的方式。
下面就用外部中断的方法来改写一下第二个示例中,通过按键来更改闪烁速度的例子(第二个例子)。
电路结构和接线不变,仅把程序改为下面的形式。
#include ;unsigned int t=500; //定义一个全局变量t,并设定初始值为500次//===========延时子函数,在8MHz晶振时约1ms=============void delay_ms(unsigned int k){unsigned int i,j;for(i=0;i<k;i++){for(j=0;j<1140;j++);}}//============主函数==================================void main( void ){DDRB = 0xFF; //设置端口B为输出方向PORTB = 0xFF; //设置端口B的输出为全高电平DDRD = 0x00; //设置端口D为输入方向PORTD = 0xFF; //设定端口D为内部上拉方式,无信号输入时处于高电平状态MCUCR = 0x0A; //设定INT0、INT1为下降沿触发GICR = 0xC0; //使能INT0、INT1中断SREG = 0x80; //使能总中断while(1){PORTB = 0x55; //让接在端口B上的LED显示01010101 delay_ms(t); //延时t个msPORTB = 0xAA; //让接在端口B上的LED显示01010101 delay_ms(t); //延时t个ms}}//============中断函数(外部0)==========================#pragma vector = INT0_vect__interrupt void INT0_Server(void){t = 100; //设定t的值为100次}//============中断函数(外部1)==========================#pragma vector = INT1_vect__interrupt void INT1_Server(void){t = 500; //设定t的值为500次}把上述程序进行编译并下载到单片机中,可以看到结果与第二个示例中的完全一致。
linux系统中断详解最近为了解决风控问题,⼀直在研究linux的系统内核,经过⼀段时间的学习,先整理出⼀份关于linux中断的⼩记。
1.什么是中断?计算机cpu在执⾏task时,不可能每次都将任务执⾏完毕,会因为各种不同的场景⽽暂停执⾏,所谓中断就是这个暂停执⾏的过程。
2.中断算是⼀种错误吗?严格来说,中断当然算是运⾏错误的⼀种,但是,由于其不可避免,程序开发者⾃然可以将其视为⼀种机制,加以运⽤,反⽽更容易帮助我们完成现实功能的实现。
3.中断的分类从产⽣原因上看,中断可以分为软件中断和硬件中断,⽽从类别划分上看,也可以氛围有出错码中断和⽆出错码中断。
⼆者并不排斥,⽐如说,中断分类存在int0~int255中,其中int0 ~ int31 表⽰软件中断,int32 ~ int255: 可由⽤户⾃⼰设置。
其中int32 ~ int47 对应8259A的IRQ0 ~ IRQ15中断。
需要注意的是,int128 为系统调⽤中断(system_call)。
如果⼤家有看过内核源码或者其他汇编代码,会发现汇编语⾔在调⽤c函数时,就是使⽤system_call,由此可见,调⽤其他函数,也是⼀种中断。
这⾥不⽌局限于linux系统,其中中断逻辑囊括所有计算机逻辑执⾏逻辑,其最基础的实现逻辑就是计算机0/1与或逻辑,属于机器语⾔中最低级也是最⾼效的展现形式。
4.中断时堆栈变化情况堆栈相关知识此处不做介绍,不了解的同学可以⾃⾏查找⼀下相关资料。
上图可以⾮常清楚的展⽰中断发⽣时堆栈的变化情况。
即中断发⽣前,需要将图中的信息按照先后顺序,压⼊中断处理程序的堆栈中。
下⾯进⾏具体的分析:SS(stack segment): 堆栈段ESP(extended stack pointer): 堆栈指针EFLAGS : 状态标志寄存器CS(code segment): 代码段EIP(extended instruction pointer) : 中断后要执⾏的下⼀条指令的地址1)有/⽆出错码:我们只需知道,对于某些中断,⽐如:int0(⽆错误码)是不需要保存出错码的,⽽像int8等中断是需要保存出错码的。
关于单片机中断详解什么是中断?就是打断当前要做的事,转而去执行别的事情。
比如小七我现在正在电脑前写帖子,突然老妈叫我帮她下楼拿点东西,于是我就收到了老妈给我的一个中断(可以叫做外部中断),当我去拿东西时,突然尿急(内部中断,尿袋快要撑爆了),这又是一个中断,!我们把引起中断的事件叫做中断源(如老妈给我的任务,以及我的尿意。
外部引起的叫外部中断,内部引起的叫内部中断),产生中断后就要去处理它,这称为中断的响应。
由于尿急这个内部中断的优先级比老妈给我的外部中断还要高,尿急了,我总得先去撒尿吧?所以我就先去执行撒尿这个语句(小七:怎么我觉得这个比喻很别扭呢?!)。
当我撒完尿后(还是觉得很别扭。
)我会返回来帮老妈拿东西(高优先级的中断处理完后返回执行优先级较低的中断),拿完东西了我再回到电脑前继续写帖子(全部中断处理完后继续接手中断前的工作)。
这个就叫做中断的返回。
这么通俗的比喻,大家对中断的概念应该都明白了吧,那么在单片机里面,中断有什么用呢?当单片机正在执行程序的时候,突然某个按键按下了(产生外部中断),单片机就必须得去处理那个按键(中断的响应),看看是发生了什么事,按键处理完后继续回来执行程序(中断的返回)。
同样,单片机正在执行程序的时候,内部的定时器溢出(定时器后面会单独讲到),或者检测到单片机的电压低于正常值等等(单片机内部产生的中断叫内部中断),单片机就得去处理这些事情,然后再返回来。
在单片机里面,中断是有特殊的功能寄存器控制的,单片机里面一共有两个中断,一个是中断0,一个是中断1 ,和两个定时器T0,T1,定时器就是你打开它后,它会自动数数,当数到你给它限定的值时,它就会溢出,产生中断让CPU处理(就像一个桶,你打开水龙头后,水越来越多,当达到你需要的水位时,就会产生中断叫你去处理它)。
这些我们先不深入了解他是什么东西,我们只需知道中断是用下面这几个关键词控制的就行了:IT0声明外部中断0的类型,IT0=1是边沿触发,0是电平触发边沿触发就是当检测到外部电平发生变化,即由低变高,或者由高变低时,就会产生一个中断电平触发就是检测到高电平或者低电平时,产生中断IE0外部边沿触发产生中断后,它的值会变1,当CPU响应后,会自动变为0IT1和IT0一样的含义IE1和IT0一样的含义EX0外部中断0控制器,EX0=1是允许外部中断,0是禁止外部中断,也就是不理会外部中断ET0这个是定时器中断控制器,ET1=1是允许定时器产生中断,0是禁止EX1,ET1的含义跟上面的都一样。
一. UCOSII的中断过程简介系统接收到中断请求后,如果CPU处于开中断状态,系统就会中止正在运行的当前任务,而按中断向量的指向去运行中断服务子程序,当中断服务子程序运行完成后,系统会根据具体情况返回到被中止的任务继续运行,或转向另一个中断优先级别更高的就绪任务。
由于UCOS II是可剥夺型的内核,所以中断服务程序结束后,系统会根据实际情况进行一次任务调度,如果有优先级更高的任务,就去执行优先级更高的任务,而不一定要返回被中断了的任务。
二.UCOSII的中断过程的示意图三.具体中断过程1.中断到来,如果被CPU识别,CPU将查中断向量表,根据中断向量表,获得中断服务子程序的入口地址。
2.将CPU寄存器的内容压入当前任务的任务堆栈中(依处理器的而定,也可能压入被压入被中断了的任务堆栈中。
3.通知操作系统将进入中断服务子程序。
即:调用OSIntEnter()或OSIntNesting直接加1。
4.If(OSIntNesting==1){OSTCBCur->OSTCBStrPtr=SP;} //如果是第一层中断,则将堆栈指针保存到被中断任务的任务控制块中5.清中断源,否则在开中断后,这类中断将反复的打入,导致系统崩贵6.执行用户ISR7.中断服务完成后,调用OSIntExit().如果没有高优先级的任务被中断服务子程序激活而进入就绪态,那么就执行被中断了的任务,且只占用很短的时间.8.恢复所有CPU寄存器的值.9.执行中断返回指令.四.相关代码与编译器相关的数据类型:typedef unsigned char BOOLEAN;typedef unsigned char INT8U;typedef unsigned int OS_STK; //堆栈入口宽度为16 位(一) void OSIntEnter (void)的理解uCOS_II.H中定义:#ifdef OS_GLOBALS#define OS_EXT#else#define OS_EXT extern#endif //定义全局宏OS_EXT#ifndef TRUE#define TRUE 1#endifOS_EXT BOOLEAN OSRunning; //定义外部BOOLEAN类型全局变量,用来指示//核是否在运行OS_EXT INT8U OSIntNesting;//定义外部8位无符号整型数全局变量,用来表//示中断嵌套层数OS_CORE.C中的OSIntEnter()函数原型:void OSIntEnter (void){if (OSRunning == TRUE) //如果内核正在运行则进入if{if (OSIntNesting < 255) //如果嵌套层数小于255,则可以继//续{OSIntNesting++; //嵌套层数加1}}}(二)在中断服务子程序中加if ( OSIntNesting == 1){…}的原因uCOS_II.H中定义:typedef struct os_tcb {OS_STK *OSTCBStkPtr;//声明指向任务堆栈栈顶的16位指针………………} OS_TCB;//定义名为OS_TCB的结构体数据类型,即任务控制块的数据结构OS_EXT OS_TCB *OSTCBCur;//声明一个指向任务控制块的全局指针变量//用于指向当前任务的任务控制块中断服务程序中添加的代码:if ( OSIntNesting == 1){OSTCBCur->OSTCBStkPtr = SP; // 如果是第一层中断,则将被中断任务//的堆栈指针保存在被中断任务的任务//任务控制块中}关于uCOS-II的中断服务程序(ISR)中必须加“OSIntNesting == 1”的原因==避免调整堆栈指针.出现这个问题的根源是当低优先级的任务被中断,当中断完成后由于有高优先级的任务就绪,则必须调度高优先级的任务,原来的低优先级任务继续被中断着,但是此时的低优先级任务的堆栈已经被破坏,已不能被调度程序直接调度了,要想被调度而必须调整堆栈指针。
概念:引起CPU中断的根源,称为中断源。
中断源向CPU提出的中断请求。
CPU暂时中断原来的事务A,转去处理事件B。
对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。
实现上述中断功能的部件称为中断系统(中断机构)。
80C51的中断系统有5个中断源,2个优先级,可实现二级中断嵌套(就是可以在嵌套过程中再次响应嵌套)。
中断源
1、INT0(P3.2),外部中断1。
可由IT0(TCON.0)选择其为低电平有效还是下降沿有效。
当CPU检测到P3.2引脚上出现有效的中断信号时,中断标志IE0(TCON.1)置1,向CPU 申请中断。
2、INT1(P3.3),外部中断2。
可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。
当CPU检测到P3.3引脚上出现有效的中断信号时,中断标志IE1(TCON.3)置1,向CPU 申请中断。
3、TF0(TCON.5),片内定时/计数器T0溢出中断请求标志。
当定时/计数器T0发生溢出时,置位TF0,并向CPU申请中断。
4、TF1(TCON.7),片内定时/计数器T1溢出中断请求标志。
当定时/计数器T1发生溢出时,置位TF1,并向CPU申请中断。
5、RI(SCON.0)或TI(SCON.1),串行口中断请求标志。
当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。
中断请求标志
1、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溢出中断请求标志位。
单片机TCON辅助设置工具
2、SCON的中断标志
RI(SCON.0),串行口接收中断标志位。
当允许串行口接收数据时,每接收完一个串行帧,由硬件置位RI。
同样,RI必须由软件清除。
TI(SCON.1),串行口发送中断标志位。
当CPU将一个发送数据写入串行口发送缓冲器时,就启动了发送过程。
每发送完一个串行帧,由硬件置位TI。
CPU响应中断时,不能自动清除TI,TI必须由软件清除。
80C51中断的控制
中断允许控制
CPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制的。
∙EX0(IE.0):外部中断0允许位;
∙ET0(IE.1):定时/计数器T0中断允许位;
∙EX1(IE.2):外部中断0允许位;
∙ET1(IE.3):定时/计数器T1中断允许位;
∙ES(IE.4):串行口中断允许位;
∙EA (IE.7):CPU中断允许(总允许)位。
单片机IE自动设计工具
中断优先级控制
80C51单片机有两个中断优先级,即可实现二级中断服务嵌套。
每个中断源的中断优先级都是由中断优先级寄存器IP中的相应位的状态来规定的。
∙PX0(IP.0),外部中断0优先级设定位;
∙PT0(IP.1),定时/计数器T0优先级设定位;
∙PX1(IP.2),外部中断0优先级设定位;
∙PT1(IP.3),定时/计数器T1优先级设定位;
∙PS? (IP.4),串行口优先级设定位;
∙PT2(IP.5),定时/计数器T2优先级设定位。
单片机IP自动设计工具
中断优先级规则:
∙CPU同时接收到几个中断时,首先响应优先级别最高的中断请求。
∙正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。
∙正在进行的低优先级中断服务,能被高优先级中断请求所中断。
中断系统总结:
TCON和SCON是中断请求,以及控制外部中断的有效方式。
IE控制是否允许CPU 响应中断,是否允许响应某一个中断。
IP控制中断的优先级。
interrupt 表示中断优先级,using表示所用工作寄存器组。
interrupt x using y
跟在interrupt 后面的xx 值得是中断号,就是说这个函数对应第几个中断端口,一般在51中
0 外部中断0
1 定时器0
2 外部中断1
3 定时器1
4 串行中断
其它的根据相应得单片机有自己的含义,实际上c在编译的时候就是把你这个函数的入口地址放到这个对应中断的跳转地址
using y 这个y是说这个中断函数使用的那个寄存器组就是51里面一般有4个 r0 -- r7寄存器,如果你的终端函数和别的程序用的不是同一个寄存器组则进入中断的时候就不会将寄存器组压入堆栈返回时也不会弹出来节省代码和时间
外部中断INT0
void intsvr0(void) interrupt 0 using 1
定时/计数器T0
void timer0(void) interrupt 1 using 1
外部中断INT1
void intsvr1(void) interrupt 2 using 1
定时/计数器T1
void timer1(void) interrupt 3 using 1
串口中断
void serial0(void) interrupt4 using 1。