51单片机的默认中断优先级都是低级及中断嵌套
51单片机的中断优先级及中断嵌套

51 单片机的中断优先级及中断嵌套
说最基本的,老的51 单片机(80C51 系列)有5 个中断源,2 个优先级,
可以实现二级中断服务嵌套。
现在很多扩展的51 单片机已经有4 个优先级(或更多)和更多的中断源了。
在说到中断之前,我先来定义一下优先级,明白了什幺是优先级,后面的阐述就容易明白了。
实际上很多人都是混淆了优先级的含义,所以才觉得糊里糊涂。
中断的优先级有两个:查询优先级和执行优先级。
什幺是查询优级呢?我们从datasheet 或书上看到的默认(IP 寄存器不做设
置,上电复位后为00H)的优先级:
外部中断0 > 定时/计数器0 > 外部中断1 > 定时/计数器1 > 串行中断
或int0,timer0,int1,timer1,serial port 或INT0、T0、INT1、T1、UART
或PX0>PT0>PX1>PT1>PS>......
其实都是查询优级。
首先查询优先级是不可以更改和设置的。
这是一个中断优先权排队的问题。
是指多个中断源同时产生中断信号时,中断仲裁器选择对哪个中断源优先处理的顺序。
而这与是否发生中断服务程序的嵌套毫不。
51单片机中断:寄存器与优先级

51单⽚机中断:寄存器与优先级中断与定时器通常定时器⼀般⽤法都是采取中断⽅式来做,但中断和定时器并⾮同⼀种东西,定时器按照⼀定设置后会触发中断,但还有外部中断,UART这些设置后都可以触发中断.定时器是单⽚机模块的⼀个资源,确确实实存在的⼀个模块。
中断是单⽚机的⼀种运⾏机制。
中断相关寄存器IE: 中断使能寄存器的位分配(地址0xA8, 可位寻址)位76543210符号EA--ET2ES ET1EX1ET0EX0复位值0--000000中断使能寄存器的位描述位符号描述7EA总中断使能位,相当于总开关6--5ET2定时器 2 中断使能4ES串⼝中断使能3ET1定时器 1 中断使能2EX1外部中断 1 使能1ET0定时器 0 中断使能0EX0外部中断 0 使能中断函数的使⽤单⽚机如何找到中断函数的?单⽚机借助中断向量地址来调⽤中断函数,中断向量地址⼜是如何计算的?中断函数interrupt后⾯中断函数标号的数字x就是根据中断向量地址得出的,其计算⽅法为:向量地址=x∗8+3具体向量地址见下⼀节中断序列查询表中断序列查询中断序列查询表中断函数编号中断名称中断标志位中断使能位中断向量地址默认优先级0外部中断 0IE0EX00x00031(最⾼)1T0中断TF0ET00x000B22外部中断1IE1EX10x001333T1中断TF1ET10x001B44UART中断TI/RI ES0x002355T2中断TF2/EXF2ET20x002B6中断优先级寄存器中断优先级有两种,⼀种是抢占优先级,⼀种是固有优先级抢占优先级IP寄存器-中断优先级寄存器的位分配(地址 0xB8、可位寻址)位76543210符号----PT2PS PT1PX1PT0PX0复位值----000000中断优先级寄存器的位描述位符号描述7--6--5PT2定时器 2 中断优先级控制位4PS串⼝中断优先级控制位3PT1定时器 1 中断优先级控制位2PX1外部中断 1 中断优先级控制位1PT0定时器 0 中断优先级控制位0PX0外部中断 0 中断优先级控制位IP这个寄存器的每⼀位,表⽰对应中断的抢占优先级,每⼀位的复位值都是0,当把某⼀位设置为1的时候,这⼀位的优先级就⽐其它位的优先级⾼了。
单片机中的中断优先级与中断嵌套技术研究

单片机中的中断优先级与中断嵌套技术研究中断是单片机中的重要概念之一,它能够在特定条件下打断正常的程序执行流程,跳转到一个处理特定事件的子程序中执行,然后再回到原来的程序继续执行。
中断优先级和中断嵌套技术是单片机中处理中断的两个重要方面,对于中断服务程序的优化和系统性能的提升具有重要意义。
一、中断优先级的基本概念与作用中断优先级是指在多个中断请求同时到达时,根据设定的优先级确定哪个中断请求优先被处理。
单片机中的中断优先级是通过硬件电路实现的,不同的单片机具有不同数量的中断优先级位,即能够支持的中断请求个数。
中断优先级主要用于解决中断冲突问题。
当多个中断请求同时发生时,通过设置不同的中断优先级,可以确保高优先级的中断请求先被响应并进行处理。
这样可以提高系统的响应速度,保证重要事件的及时处理。
在设定中断优先级时,需要根据系统的实际需求来确定各个中断的优先级,一般会根据中断请求的紧急程度、重要性以及处理时间的长短等因素进行判断。
通常,系统关键性的中断请求具有较高的优先级,而次要的中断请求则具有较低的优先级。
二、中断嵌套技术的基本概念与实现中断嵌套是指在一个中断服务程序中,允许发生更高优先级的中断请求,并且暂时挂起当前正在执行的中断程序,转而处理更高优先级的中断请求。
中断嵌套技术在确保高优先级事件得到及时处理的同时,也提高了单片机系统的灵活性和效率。
1. 中断嵌套的实现方式单片机中的中断嵌套可以通过软件或硬件方式实现。
(1)软件方式:在编写中断服务程序时,可以通过设置相关的标志位来控制中断嵌套。
当中断请求到来时,会首先检查标志位,如果允许嵌套,则挂起当前中断程序,跳转到更高优先级的中断服务程序中执行;如果不允许嵌套,则忽略该中断请求。
(2)硬件方式:某些单片机芯片内部集成了硬件中断嵌套功能。
通过设置相应的硬件寄存器,可以实现中断嵌套的功能。
硬件方式能够更好地支持多个中断请求的处理和优先级设置,具有更高的灵活性和效率。
单片机题库 (1)

单片机题库一:判断题您的姓名: [填空题] *_________________________________1、#define LED P2是宏定义,即用P2来代替LED。
[判断题] *对错(正确答案)2、X>>1表示将X中的各个位都向左移动1位,右边空出来的位用0补足。
[判断题] *对错(正确答案)3、在C语言中,函数体部分需要用{ }括起来。
() [单选题] *A、对(正确答案)B、错4、a==1表示将变量a赋值为1 [判断题] *对错(正确答案)5、51单片机的每个中断源都具有高低两个中断优先级。
[判断题] *对错(正确答案)4、int型数据和无符号int型数据的取值范围是一样的。
[判断题] *对错(正确答案)5、数组中的数据可以是不同类型的。
[判断题] *对错(正确答案)6、在C语言中,常量可以是数值型常量也可以是符号型常量 [判断题] *对(正确答案)错7、数组可以分为一维数组,二维数组和多维数组。
[判断题] *对(正确答案)错8、在LED闪烁方式控制的电路所用的发光二极管具有单向导通性。
[判断题] *对(正确答案)错9、#define LED P2是宏定义,即用P2来代替LED。
[判断题] *对错(正确答案)10、算数运算符%表示取余运算,10%3的结果是1。
[判断题] *对(正确答案)错11、C语言中一个分号可以作为一个执行语句。
[判断题] *错12、拉幕灯实验中使用到的LED灯是发光二极管,它具有单向导通性。
[判断题] *对(正确答案)错13、同级优先级不能相互断。
[判断题] *对(正确答案)错14、除法运算7/3的结果是1。
[判断题] *对错(正确答案)15、void delay_1ms(uint x)该函数有一个参数x [判断题] *对(正确答案)错16、陶瓷电容和电解电容在结构上是相同的,在硬件电路中可互换。
[判断题] *对错(正确答案)13、8段LED数码管显示器只有共阳极结构。
第5章 习题参考答案

第五章习题参考答案一、填空题1、MCS-51有5个中断源,2个中断优先级,优先级由软件填写特殊功能寄存器 IP 加以选择。
2、外中断请求标志位是 IE0 和 IE1 。
3、 RETI 指令以及任何访问 IE 和 IP 寄存器的指令执行过后,CPU不能马上响应中断。
4、8051单片机响应中断后,产生长调用指令LCALL,执行该指令的过程包括:首先把 PC的内容压入堆栈,以进行断点保护,然后把长调用指令的16位地址送 PC ,使程序执行转向程序存储器中的中断地址区。
二、选择题:1、在中断服务程序中,至少应有一条( D )。
A、传送指令B、转移指令C、加法指令D、中断返回指令2、要使MCS-51能够响应定时器T1中断,串行接口中断,它的中断允许寄存器IE的内容应是( A )。
A、 98HB、 84HC、 42HD、 22H3、MCS-51响应中断时,下列哪种操作不会发生( A )A、保护现场B、保护PCC、找到中断入口D、保护PC转入中断入口4、MCS-51中断源有( A )A、 5个B、 2个C、 3个D、6个5、计算机在使用中断方式与外界交换信息时,保护现场的工作应该是( C )A、由CPU自动完成B、在中断响应中完成C、应由中断服务程序完成D、在主程序中完成6、MCS-51的中断允许触发器内容为83H,CPU将响应的中断请求是( D )。
A、 INT0,INT1B、 T0,T1C、 T1,串行接口D、 INT0,T07、若MCS-51中断源都编程为同级,当它们同时申请中断时,CPU首先响应( B )。
A、 INT1B、 INT0C、 T1D、T08、当CPU响应串行接口中断时,程序应转到( C )。
A、 0003HB、 0013HC、 0023HD、 0033H9、执行MOV IE,#03H后,MCS-51将响应的中断是( D )。
A、 1个B、 2个C、 3个D、0个10、外部中断1固定对应的中断入口地址为( C )。
MCS-51作业讲解

③ 位地址7CH与字节地址7CH如何区别?位地址 7CH具体在片内RAM中什么位置?
答:位地址7CH与字节地址7CH靠所使用的指令 或指令中所使用的寄存器来区别,当使用 位指令或指令中使用“C”寄存器时表明此 时的地址是位地址,其余情况均为字节地 址。 位地址7CH具体在片内RAM2FH单元中D4位。
CJNE A,30H,NEXT ;两数比较,不等转NEXT SJMP NOCHA ;相等转NOCHA(不交换位置)
NEXT:JNC NOCHA;C=0则(A)>(30H)不交换, 转NOCHA(@R1>R0@)
MOV @R0,A;交换R0与R1指向单元的数 XCH A,30H ;将@R1中的数(A)与30H
⒍ MCS-51单片机如何实现工作寄存器组 R0-R7的选择?
答:用户可通过改变PSW中的RS1和RS0的 两位的值选择相应的工作寄存器组。
⒎什么是时钟周期、机器周期、指令周期?当 单片机时钟频率为12 MHz时,一个机器周期 是多少?ALE引脚的输出频率是多少?
答:时钟周期:指为单片机提供时钟信号的振 荡源的周期.
(原R0 )交换 MOV @R1,A;使A(原R0中数)→@R1 NOCHA:INC R0;调节地址指针
INC R1 DJNZ R3,LOOP1;内循环结束判别 DJNZ R2,LOOP0;外循环结束判别
RET
MOV R0,#51H MOV R5,#07H MOV R4,#00H MOV A, @R0 INC R0 LP: ADD A, @R0 JNC LP1 INC R4 CLR C LP1:INC R0 DJNZ R5,LP
⒉在以3000H为首地址的外部单元中,存放了14 个ASCII码表示的0~9之间的数,试编写程序 将它们转换为BCD码,并以压缩型BCD码的 形式存放在以2000H为首地址的外部单元中. MOV DPTR,#2000H MOV P2,#20H MOV R0,#00H MOV R3,#07H LOOP: MOVX A,@R0
51单片机中断总结

51单片机中断总结:1. 查询优先级为固定的(外部中断0>定时器0>外部中断1>定时器1>串行中断)。
2. 执行优先级可以通过IP寄存器进行设置(高/低)。
3. CPU同时收到多个中断请求时,首先响应优先级较高者,然后相应优先级较低者;如果优先级相同,则按照查询优先级顺序依次响应。
4. 正在执行的中断服务,不能被同级或更低级的中断请求打断,但会被更高级的中断请求打断。
推论(1)高优先级的中断不能被任何其它中断所打断(2)低优先级的中断只能在没有任何中断服务运行时得到响应。
5. 对于定时器和外部中断,在进入中断服务后,其中断标志位会自动清零;对于串行中断,由于有两个中断源,需要手动查询并清零RI或/和TI。
if (RI) {// processingRI = 0;}if (TI) {// processingTI = 0;}6. 如果是使用汇编写中断服务,需要保护累加器、状态寄存器、寄存器组等8051 Tutorial: Interrupts/tutint.phpAs the name implies, an interrupt is some event which interrupts normal program execution.As stated earlier, program flow is always sequential, being altered only by those instructions which expressly cause program flow to deviate in some way. However, interrupts give us a mechanism to "put on hold" the normal program flow, execute a subroutine, and then resume normal program flow as if we had never left it. This subroutine, called an interrupt handler, is only executed when a certain event (interrupt) occurs. The event may be one of the timers "overflowing," receiving a character via the serial port, transmitting a character via the serialport, or one of two "external events." The 8051 may be configured so that when any of these events occur the main program is temporarily suspended and control passed to a special section of code which presumably would execute some function related to the event that occured. Once complete, control would be returned to the original program. The main program never even knows it was interrupted.The ability to interrupt normal program execution when certain events occur makes it much easier and much more efficient to handle certain conditions. If it were not for interrupts we would have to manually check in our main program whether the timers had overflown, whether we had received another character via the serial port, or if some external event had occured. Besides making the main program ugly and hard to read, such a situation would make our program inefficient since wed be burning precious "instruction cycles" checking for events that usually dont happen.For example, lets say we have a large 16k program executing many subroutines performing many tasks. Lets also suppose that we want our program to automatically toggle the P3.0 port every time timer 0 overflows. The code to do this isnt too difficult:JNB TF0,SKIP_TOGGLECPL P3.0CLR TF0SKIP_TOGGLE: ...Since the TF0 flag is set whenever timer 0 overflows, the above code will toggle P3.0 every time timer 0 overflows. This accomplishes what we want, but is inefficient. The JNB instruction consumes 2 instruction cycles to determine that the flag is not set and jump over the unnecessary code. In the event that timer 0 overflows, the CPL and CLR instruction require 2 instruction cycles to execute. To make the math easy, lets say the rest of the code in the program requires 98 instruction cycles. Thus, in total, our code consumes 100 instruction cycles (98 instruction cycles plus the 2 that are executed every iteration to determine whether or not timer 0 has overflowed). If were in 16-bit timer mode, timer 0 will overflow every 65,536 machine cycles. In that time we would have performed 655 JNB tests for a total of 1310 instruction cycles, plus another 2 instruction cycles to perform the code. So to achieve our goal weve spent 1312 instruction cycles. So 2.002% of our time is being spent just checking when to toggle P3.0. And our code is ugly because we have to make that check every iteration of our main program loop.Luckily, this isnt necessary. Interrupts let us forget about checking for the condition. The microcontroller itself will check for the condition automatically and when the condition is met will jump to a subroutine (called an interrupt handler), execute the code, then return. In this case, our subroutine would be nothing more than:CPL P3.0RETIFirst, youll notice the CLR TF0 command has disappeared. Thats because when the 8051 executes our "timer 0 interrupt routine," it automatically clears the TF0 flag. Youll also notice that instead of a normal RET instruction we have a RETI instruction. The RETI instruction does the same thing as a RET instruction, but tells the 8051 that an interrupt routine has finished. You must always end your interrupt handlers with RETI.Thus, every 65536 instruction cycles we execute the CPL instruction and the RETI instruction. Those two instructions together require 3 instruction cycles, and weve accomplished the same goal as the first example that required 1312 instruction cycles. As far as the toggling of P3.0 goes, our code is 437 times more efficient! Not to mention its much easier to read and understand because we dont have to remember to always check for the timer 0 flag in our main program. We just setup the interrupt and forget about it, secure in the knowledge that the 8051 will execute our code whenever its necessary.The same idea applies to receiving data via the serial port. One way to do it is to continuously check the status of the RI flag in an endless loop. Or we could check the RI flag as part of a larger program loop. However, in the latter case we run the risk of missing characters--what happens if a character is received right after we do the check, the rest of our program executes, and before we even check RI a second character has come in. We will lose the first character. With interrupts, the 8051 will put the main program "on hold" and call our special routine to handle the reception of a character. Thus, we neither have to put an ugly check in our main code nor will we lose characters.What Events Can Trigger Interrupts, and where do they go?We can configure the 8051 so that any of the following events will cause an interrupt:Timer 0 Overflow.Timer 1 Overflow.Reception/Transmission of Serial Character.External Event 0.External Event 1.In other words, we can configure the 8051 so that when Timer 0 Overflows or when a character is sent/received, the appropriate interrupt handler routines are called.Obviously we need to be able to distinguish between various interrupts and executing different code depending on what interrupt was triggered. This is accomplished by jumping to a fixed address when a given interrupt occurs.Interrupt Flag Interrupt Handler AddressExternal 0 IE0 0003hTimer 0 TF0 000BhExternal 1 IE1 0013hTimer 1 TF1 001BhSerial RI/TI 0023hBy consulting the above chart we see that whenever Timer 0 overflows (i.e., the TF0 bit is set), the main program will be temporarily suspended and control will jump to 000BH. It is assumed that we have code at address 000BH that handles the situation of Timer 0 overflowing.Setting Up InterruptsBy default at powerup, all interrupts are disabled. This means that even if, for example, the TF0 bit is set, the 8051 will not execute the interrupt. Your program must specifically tell the 8051 that it wishes to enable interrupts and specifically which interrupts it wishes to enable.Your program may enable and disable interrupts by modifying the IE SFR (A8h):Bit Name Bit Address Explanation of Function7 EA AFh Global Interrupt Enable/Disable6 - AEh Undefined5 - ADh Undefined4 ES ACh Enable Serial Interrupt3 ET1 ABh Enable Timer 1 Interrupt2 EX1 AAh Enable External 1 Interrupt1 ET0 A9h Enable Timer 0 Interrupt0 EX0 A8h Enable External 0 InterruptAs you can see, each of the 8051s interrupts has its own bit in the IE SFR. You enable a given interrupt by setting the corresponding bit. For example, if you wish to enable Timer 1 Interrupt, you would execute either:MOV IE,#08horSETB ET1Both of the above instructions set bit 3 of IE, thus enabling Timer 1 Interrupt. Once Timer 1 Interrupt is enabled, whenever the TF1 bit is set, the 8051 will automatically put "on hold" the main program and execute the Timer 1 Interrupt Handler at address 001Bh.However, before Timer 1 Interrupt (or any other interrupt) is truly enabled, you must also set bit 7 of IE. Bit 7, the Global Interupt Enable/Disable, enables or disables all interrupts simultaneously. That is to say, if bit 7 is cleared then no interrupts will occur, even if all the other bits of IE are set. Setting bit 7 will enable all the interrupts that have been selected by setting other bits in IE. This is useful in program execution if you have time-critical code that needs to execute. In this case, you may need the code to execute from start to finish without any interrupt getting in the way. To accomplish this you can simply clear bit 7 of IE (CLR EA) and then set it after your time-criticial code is done.So, to sum up what has been stated in this section, to enable the Timer 1 Interrupt the most common approach is to execute the following two instructions:SETB ET1SETB EAThereafter, the Timer 1 Interrupt Handler at 01Bh will automatically be called whenever the TF1 bit is set (upon Timer 1 overflow).Polling SequenceThe 8051 automatically evaluates whether an interrupt should occur after every instruction. When checking for interrupt conditions, it checks them in the following order:External 0 InterruptTimer 0 InterruptExternal 1 InterruptTimer 1 InterruptSerial InterruptThis means that if a Serial Interrupt occurs at the exact same instant that an External 0 Interrupt occurs, the External 0 Interrupt will be executed first and the Serial Interrupt will be executed once the External 0 Interrupt has completed.Interrupt PrioritiesThe 8051 offers two levels of interrupt priority: high and low. By using interrupt priorities you may assign higher priority to certain interrupt conditions.For example, you may have enabled Timer 1 Interrupt which is automatically called every time Timer 1 overflows. Additionally, you may have enabled the Serial Interrupt which is called every time a character is received via the serial port. However, you may consider that receiving a character is much more important than the timer interrupt. In this case, if Timer 1 Interrupt is already executing you may wish that the serial interrupt itself interrupts the Timer 1 Interrupt. When the serial interrupt is complete, control passes back to Timer 1 Interrupt and finally back to the main program. You may accomplish this by assigning a high priority to the Serial Interrupt and a low priority to the Timer 1 Interrupt.Interrupt priorities are controlled by the IP SFR (B8h). The IP SFR has the following format:Bit Name Bit Address Explanation of Function7 - - Undefined6 - - Undefined5 - - Undefined4 PS BCh Serial Interrupt Priority3 PT1 BBh Timer 1 Interrupt Priority2 PX1 BAh External 1 Interrupt Priority1 PT0 B9h Timer 0 Interrupt Priority0 PX0 B8h External 0 Interrupt PriorityWhen considering interrupt priorities, the following rules apply:Nothing can interrupt a high-priority interrupt--not even another high priority interrupt.A high-priority interrupt may interrupt a low-priority interrupt.A low-priority interrupt may only occur if no other interrupt is already executing.If two interrupts occur at the same time, the interrupt with higher priority will execute first. If both interrupts are of the same priority the interrupt which is serviced first by polling sequence will be executed first.What Happens When an Interrupt Occurs?When an interrupt is triggered, the following actions are taken automatically by the microcontroller:The current Program Counter is saved on the stack, low-byte first.Interrupts of the same and lower priority are blocked.In the case of Timer and External interrupts, the corresponding interrupt flag is cleared.Program execution transfers to the corresponding interrupt handler vector address.The Interrupt Handler Routine executes.Take special note of the third step: If the interrupt being handled is a Timer or External interrupt, the microcontroller automatically clears the interrupt flag before passing control to your interrupt handler routine. This means it is not necessary that you clear the bit in your code.What Happens When an Interrupt Ends?An interrupt ends when your program executes the RETI (Return from Interrupt) instruction. When the RETI instruction is executed the following actions are taken by the microcontroller:Two bytes are popped off the stack into the Program Counter to restore normal program execution.Interrupt status is restored to its pre-interrupt status.Serial InterruptsSerial Interrupts are slightly different than the rest of the interrupts. This is due to the fact that there are two interrupt flags: RI and TI. If either flag is set, a serial interrupt is triggered. As you will recall from the section on the serial port, the RI bit is set when a byte is received by the serial port and the TI bit is set when a byte has been sent.This means that when your serial interrupt is executed, it may have been triggered because the RI flag was set or because the TI flag was set--or because both flags were set. Thus, your routine must check the status of these flags to determine what action is appropriate. Also, since the 8051 does not automatically clear the RI and TI flags you must clear these bits in your interrupt handler.A brief code example is in order:INT_SERIAL: JNB RI,CHECK_TI ;If the RI flag is not set, we jump to check TIMOV A,SBUF ;If we got to this line, its because the RI bit *was* setCLR RI ;Clear the RI bit after weve processed itCHECK_TI: JNB TI,EXIT_INT ;If the TI flag is not set, we jump to the exit pointCLR TI ;Clear the TI bit before we send another characterMOV SBUF,#A ;Send another character to the serial portEXIT_INT: RETIAs you can see, our code checks the status of both interrupts flags. If both flags were set, both sections of code will be executed. Also note that each section of code clears its corresponding interrupt flag. If you forget to clear the interrupt bits, the serial interrupt will be executed over and over until you clear the bit. Thus it is very important that you always clear the interrupt flags in a serial interrupt.Important Interrupt Consideration: Register ProtectionOne very important rule applies to all interrupt handlers: Interrupts must leave the processor in the same state as it was in when the interrupt initiated.Remember, the idea behind interrupts is that the main program isnt aware that they are executing in the "background." However, consider the following code:CLR C ;Clear carryMOV A,#25h ;Load the accumulator with 25hADDC A,#10h ;Add 10h, with carryAfter the above three instructions are executed, the accumulator will contain a value of 35h.But what would happen if right after the MOV instruction an interrupt occured. During this interrupt, the carry bit was set and the value of the accumulator was changed to 40h. When the interrupt finished and control was passed back to the main program, the ADDC would add 10h to 40h, and additionally add an additional 1h because the carry bit is set. In this case, the accumulator will contain the value 51h at the end of execution.In this case, the main program has seemingly calculated the wrong answer. How can 25h + 10h yield 51h as a result? It doesnt make sense. A programmer that was unfamiliar with interrupts would be convinced that the microcontroller was damaged in some way, provoking problems with mathematical calculations.What has happened, in reality, is the interrupt did not protect the registers it used. Restated: An interrupt must leave the processor in the same state as it was in when the interrupt initiated.What does this mean? It means if your interrupt uses the accumulator, it must insure that the value of the accumulator is the same at the end of the interrupt as it was at the beginning. This is generally accomplished with a PUSH and POP sequence. For example:PUSH ACCPUSH PSWMOV A,#0FFhADD A,#02hPOP PSWPOP ACCThe guts of the interrupt is the MOV instruction and the ADD instruction. However, these two instructions modify the Accumulator (the MOV instruction) and also modify the value of the carry bit (the ADD instruction will cause the carry bit to be set). Since an interrupt routine must guarantee that the registers remain unchanged by the routine, the routine pushes the original values onto the stack using the PUSH instruction. It is then free to use the registers it protected to its hearts content. Once the interrupt has finished its task, it pops the original values back into the registers. When the interrupt exits, the main program will never know the difference because the registers are exactly the same as they were before the interrupt executed.In general, your interrupt routine must protect the following registers:PSWDPTR (DPH/DPL)PSWACCBRegisters R0-R7Remember that PSW consists of many individual bits that are set by various 8051 instructions. Unless you are absolutely sure of what you are doing and have a complete understanding of what instructions set what bits, it is generally a good idea to always protect PSW by pushing and popping it off the stack at the beginning and end of your interrupts.Note also that most assemblers (in fact, ALL assemblers that I know of) will not allow you to execute the instruction:PUSH R0This is due to the fact that depending on which register bank is selected, R0 may refer to either internal ram address 00h, 08h, 10h, or 18h. R0, in and of itself, is not a valid memory address that the PUSH and POP instructions can use.Thus, if you are using any "R" register in your interrupt routine, you will have to push that registers absolute address onto the stack instead of just saying PUSH R0. For example, instead of PUSH R0 you would execute:PUSH 00hOf course, this only works if youve selected the default register set. If you are using an alternate register set, you must PUSH the address which corresponds to the register you are using.Common Problems with InterruptsInterrupts are a very powerful tool available to the 8051 developer, but when used incorrectly they can be a source of a huge number of debugging hours. Errors in interrupt routines are often very difficult to diagnose and correct.If you are using interrupts and your program is crashing or does not seem to be performing as you would expect, always review the following interrupt-related issues:Register Protection: Make sure you are protecting all your registers, as explained above. If you forget to protect a register that your main program is using, very strange results may occur. In our example above we saw how failure to protect registers caused the main program to apparently calculate that 25h + 10h = 51h. If you witness problems with registers changing values unexpectedly or operations producing "incorrect" values, it is very likely that you've forgotten to protect registers. ALWAYS PROTECT YOUR REGISTERS.Forgetting to restore protected values: Another common error is to push registers onto the stack to protect them, and then forget to pop them off the stack before exiting the interrupt. For example, you may push ACC, B, and PSW onto the stack in order to protect them and subsequently pop only ACC and PSW off the stack before exiting. In this case, since you forgot to restore the value of "B", an extra value remains on the stack. When you execute the RETI instruction the 8051 will use that value as the return address instead of the correct value. In this case, your program will almost certainly crash. ALWAYS MAKE SURE YOU POP THE SAME NUMBER OF VALUES OFF THE STACK AS YOU PUSHED ONTO IT.Using RET instead of RETI: Remember that interrupts are always terminated with the RETI instruction. It is easy to inadvertantly use the RET instruction instead. However, the RETinstruction will not end your interrupt. Usually, using a RET instead of a RETI will cause the illusion of your main program running normally, but your interrupt will only be executed once. If it appears that your interrupt mysteriously stops executing, verify that you are exiting with RETI.11。
80c51单片机对中断源的中断优先级的处理原则

80c51单片机对中断源的中断优先级的处理原则
80C51单片机使用了5级中断优先级,具体的中断优先级处理
原则如下:
1. 不可屏蔽中断 (External Interrupt) 优先级最高,不能被其他
中断打断,且不可被软件修改。
2. 时钟中断 (Timer Interrupt) 优先级次高,用于定时器中断。
当出现同时中断请求时,时钟中断优先级高于串口中断。
3. 串行中断(Serial Interrupt) 优先级较低,用于串口通信中断。
当出现同时中断请求时,如果没有发生时钟中断,则串行中断可以打断其他低优先级中断。
4. 外部中断0 (External Interrupt 0) 优先级较低,用于外部中断
0的中断请求。
当出现同时中断请求时,如果没有发生时钟中
断或串行中断,则外部中断0可以打断其他低优先级中断。
5. 外部中断1 (External Interrupt 1) 优先级最低,用于外部中断
1的中断请求。
当出现同时中断请求时,如果没有发生时钟中断、串行中断或外部中断0,则外部中断1可以打断其他低优
先级中断。
总结起来,中断优先级的处理原则是按照中断的重要性和紧急程度进行排序,优先级高的中断可以打断优先级低的中断。
在80C51单片机中,不可屏蔽中断的优先级最高,其次是时钟中断,然后是串行中断,外部中断0和外部中断1的优先级最低。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
51单片机的默认中断优先级都是低级及
中断嵌套
51单片机(80C51系列)有5个中断源,2个优先级,可以实现二级中断服务嵌套。
现在很多扩展的51单片机已经有4个优先级(或更多)和更多的中断源了。
在说到中断之前,我先来定义一下优先级,明白了什么是优先级,后面的阐述就容易明白了。
实际上很多人都是混淆了优先级的含义,所以才觉得糊里糊涂。
中断的优先级有两个:查询优先级和执行优先级。
什么是查询优级呢?我们从datasheet或书上看到的默认(IP寄存器不做设置,上电复位后为00H)的优先级:外部中断0 >; 定时/计数器0 >; 外部中断1 >; 定时/计数器1 >; 串行中断
或 int0,timer0,int1,timer1,serial port 或 INT0、T0、INT1、T1、UART
或 PX0>;PT0>;PX1>;PT1>;PS>;......
其实都是查询优级。
首先查询优先级是不可以更改和设置的。
这是一个中断优先权排队的问题。
是指多个中断源同时产生中断信号时,中断仲裁器选择对哪个中断源优先处理的顺序。
而这与是否发生中断服务程序的嵌套毫不相干。
当CPU查询各个中断标志位的时候,会依照
上述5个查询优先级顺序依次查询,当数个中断同时请求的时候,会优先查询到高优查询先级的中断标志位,但并不代表高查询优先级的中断可以打断已经并且正在执行的低查询优先级的中断服务。
例如:当计数器0中断和外部中断1(按查询优先级,计数器0中断>;外部中断1)同时到达时,会进入计时器0的中断服务函数;但是在外部中断1的中断服务函数正在服务的情况下,这时候任何中断都是打断不了它的,包括逻辑优先级比它高的外部中断0计数器0中断。
而中断的执行优先级就是你对IP寄存器的设置了。
在2个优先级的情况下,某位为1,则相应的中断源为高优先级;为0,则为低优先级。
关于中断的优先级有三条原则:
1、CPU同时接收到几个中断时,首先响应优先级最高的中断请求;
2、正在进行的中断过程不能被新的同级或低行优优先级的中断请求所中断;
3、正在进行的低行优优先级中断服务,能被高行优优先级中断请求中断;
若:同一执行优先级中的中断申请不止一个时,则有一个中断优先权排队问题。
优先权排队,由中断系统硬件确定的自然优先级形成,优先权自高到低的顺序即:
外部中断0>;定时/计数0>;外部中断1>;定时/计数1>;
串行接口(同级中断默认顺序)
例如:设置IP = 0x10,即设置串口中断为最高优先级,则串口中断可以打断任何其他的中断服务函数实现嵌套,且只有串口中断能打断其他中断的服务函数。
若串口中
断没有触发,则其他几个中断之间还是保持逻辑优先级,相互之间无法嵌套。
关于中断嵌套。
可以这样说,当一个中断正在执行的时候,如果事先设置了中断优先级寄存器IP,那么当一个
更高优先级的中断到来的时候会发生中断嵌套,如果没
有设置则不会发生任何嵌套;如果有同一个优先级的中
断触发,它并不是在“不断的申请”,而是
将它相应的中断标志位置即IE寄存器的某位置位,当CPU执行完当前中断之后,按照查询优先级重新去查询
各个中断标志位,进入相应中断。
要记住,没有设置IP时,单片机会按照查询优先级(或都说逻辑优先级)来排队进入服务。
如果要想让某个中断优先响应,则要设置IP,更改执行优先级(或者说物理优先级)。
要注意的是,当设置了IP后,当低执行优先级中断在运行时,如果有高执行优先级的中断产生,则
会嵌套调用进入高执行优先级的中断。
如果你是用C语
言写的程序,并在中断服务时 using 了寄存组,要注意,
两个不同优先级的中断不要 using 同一组寄存器。
否则进入一个中断会破坏之前中断用的寄存器数据。
看两个问题,如下:
1 在各个中断都是低优先级的时候,如果定时器0的溢
出进入中断。
在这个中断处理的过程中,外部中断0也
被触发了,那么是不是要发生中断嵌套?
2 如果定时器0发生中断的时候,进入中断处理程序,
这个时候外部中断1条件触发条件满足了。
因为定时器0自然优先级比外部中断1高,那么定时器0的中断处理程序继续执行。
假设定时器中断处理程序执行的过程中,
外部中断1的触发。
条件消失了,那么等定时器0的中断处理完后,程序还是会进入外部中断1处理程序吗?
答案1:在IP事先设置了外部中断0的优先级的情况下,CUP会中止定时器0的中断服务,进入外部中断0服务程序,执行完以后再回到定时器0中断服务程序。
否则不会。
答案2:肯定会进入中断的;外部中断1的触发条件满足后会置位外部1的中断标志,即使后来外部中断1的触发条件消失了,也不会清除已置位的中断标志,所以等定
时器0的中断处理完后,程序判断外部中断的中断标志
为1后依然会进入外部中断1处理程序的,只有在外部中断1处理程序中执行reti指令才会硬件清除外部中断1
的中断标志(这也正是为什么中断返回使用reti指令而不可以用ret替换的原因)...。