搜档网
当前位置:搜档网 › 51单片机中断总结

51单片机中断总结

51单片机中断总结
51单片机中断总结

51单片机中断总结:

1. 查询优先级为固定的(外部中断0>定时器0>外部中断1>定时器1>串行中断)。

2. 执行优先级可以通过IP寄存器进行设置(高/低)。

3. CPU同时收到多个中断请求时,首先响应优先级较高者,然后相应优先级较低者;如果

优先级相同,则按照查询优先级顺序依次响应。

4. 正在执行的中断服务,不能被同级或更低级的中断请求打断,但会被更高级的中断请求

打断。推论(1)高优先级的中断不能被任何其它中断所打断(2)低优先级的中断只能在没有任何中断服务运行时得到响应。

5. 对于定时器和外部中断,在进入中断服务后,其中断标志位会自动清零;对于串行中断,由于有两个中断源,需要手动查询并清零RI或/和TI。

if (RI) {

// processing

RI = 0;

}

if (TI) {

// processing

TI = 0;

}

6. 如果是使用汇编写中断服务,需要保护累加器、状态寄存器、寄存器组等

8051 Tutorial: Interrupts

https://www.sodocs.net/doc/473611601.html,/tutint.php

As 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 serial

port, 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_TOGGLE

CPL P3.0

CLR TF0

SKIP_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.0

RETI

First, 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 Address

External 0 IE0 0003h

Timer 0 TF0 000Bh

External 1 IE1 0013h

Timer 1 TF1 001Bh

Serial RI/TI 0023h

By 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 Interrupts

By 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 Function

7 EA AFh Global Interrupt Enable/Disable

6 - AEh Undefined

5 - ADh Undefined

4 ES ACh Enable Serial Interrupt

3 ET1 ABh Enable Timer 1 Interrupt

2 EX1 AAh Enable External 1 Interrupt

1 ET0 A9h Enable Timer 0 Interrupt

0 EX0 A8h Enable External 0 Interrupt

As 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,#08h

or

SETB ET1

Both 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 ET1

SETB EA

Thereafter, the Timer 1 Interrupt Handler at 01Bh will automatically be called whenever the TF1 bit is set (upon Timer 1 overflow).

Polling Sequence

The 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 Interrupt

Timer 0 Interrupt

External 1 Interrupt

Timer 1 Interrupt

Serial Interrupt

This 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 Priorities

The 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 Function

7 - - Undefined

6 - - Undefined

5 - - Undefined

4 PS BCh Serial Interrupt Priority

3 PT1 BBh Timer 1 Interrupt Priority

2 PX1 BAh External 1 Interrupt Priority

1 PT0 B9h Timer 0 Interrupt Priority

0 PX0 B8h External 0 Interrupt Priority

When 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 Interrupts

Serial 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 TI

MOV A,SBUF ;If we got to this line, its because the RI bit *was* set

CLR RI ;Clear the RI bit after weve processed it

CHECK_TI: JNB TI,EXIT_INT ;If the TI flag is not set, we jump to the exit point

CLR TI ;Clear the TI bit before we send another character

MOV SBUF,#A ;Send another character to the serial port

EXIT_INT: RETI

As 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 Protection

One 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 carry

MOV A,#25h ;Load the accumulator with 25h

ADDC A,#10h ;Add 10h, with carry

After 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 ACC

PUSH PSW

MOV A,#0FFh

ADD A,#02h

POP PSW

POP ACC

The 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:

PSW

DPTR (DPH/DPL)

PSW

ACC

B

Registers R0-R7

Remember 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 R0

This 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 00h

Of 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 Interrupts

Interrupts 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 RET

instruction 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.

51单片机中断系统详解

的定时器中断后便认为是1s,这样便可精确控制定时时间啦。要计50000个数时,TH0和TL0中应该装入的总数是65536-50000=15536.,把15536对256求模:15536/256=60装入TH0中,把15536对256求余:15536/256=176装入TL0中。 以上就是定时器初值的计算法,总结后得出如下结论:当用定时器的方式1时,设机器周期为T CY,定时器产生一次中断的时间为t,那么需要计数的个数为N=t/T CY ,装入THX和TLX中的数分别为: THX=(65536-N)/256 , TLX=(65536-N)%256 中断服务程序的写法 void 函数名()interrupt 中断号using 工作组 { 中断服务程序内容 } 在写单片机的定时器程序时,在程序开始处需要对定时器及中断寄存器做初始化设置,通常定时器初始化过程如下: (1)对TMOD赋值,以确定T0和 T1的工作方式。 (2)计算初值,并将初值写入TH0、TL0或TH1、TL1。 (3)中断方式时,则对IE赋值,开放中断。 (4)使TR0和TR1置位,启动定时器/计数器定时或计数。 例:利用定时器0工作方式1,实现一个发光管以1s亮灭闪烁。 程序代码如下: #include #define uchar unsigned char #define uint unsigned int sbit led1=P1^0; uchar num; void main() { TMOD=0x01; //设置定时器0位工作模式1(M1,M0位0,1) TH0=(65536-45872)/256; //装初值11.0592M晶振定时50ms数为45872 TL0=(65536-45872)%256; EA=1; //开总中断 ET0=1; //开定时器0中断 TR0=1; //启动定时器0 while(1) { if(num==20) //如果到了20次,说明1秒时间 { led1=~led1; //让发光管状态取反 num=0; } } } void T0_time()interrupt 1

51单片机利用中断控制灯频率和顺序

#include //包含51单片机寄存器定义的头文件#include int e=0,f=0,d=1,a=0,b=0,c=0,delay=10,m=1,V=128; G=1; /******************************************* 函数功能:主函数 ******************************************/ void main(void) { EA=1; //开放总中断 EX0=1; //允许使用外中断 ET0=1; //定时器0开 EX1=1; TMOD=0X01; IT0=1; //选择负跳变来触发外中断 IT1=1; TH0=(65536-50000)/256; TL0=(65536-50000)%256; TR0=1; while(1) ; //无限循环,防止程序跑飞 }

/************************************************************** 函数功能:外中断T0的中断服务程序 **************************************************************/ Time() interrupt 1 //外中断0的中断编号为0 { if(m%delay==0) { m=1; switch(e) { case 0: P1=G; a++; G=P1<<1; // P1=G; if(a==8) { a=0; G=1; } break; case 1: //反序 P1=V; b++; V=P1>>1; // P1=V; if(b==8) { b=0; V=128; } break; case 2: //中间到两边 P1=pow(2,4+c)+pow(2,3-c); c++; if(c==4) { c=0; }

51单片机中断总结

51单片机中断总结: 1. 查询优先级为固定的(外部中断0>定时器0>外部中断1>定时器1>串行中断)。 2. 执行优先级可以通过IP寄存器进行设置(高/低)。 3. CPU同时收到多个中断请求时,首先响应优先级较高者,然后相应优先级较低者;如果 优先级相同,则按照查询优先级顺序依次响应。 4. 正在执行的中断服务,不能被同级或更低级的中断请求打断,但会被更高级的中断请求 打断。推论(1)高优先级的中断不能被任何其它中断所打断(2)低优先级的中断只能在没有任何中断服务运行时得到响应。 5. 对于定时器和外部中断,在进入中断服务后,其中断标志位会自动清零;对于串行中断,由于有两个中断源,需要手动查询并清零RI或/和TI。 if (RI) { // processing RI = 0; } if (TI) { // processing TI = 0; } 6. 如果是使用汇编写中断服务,需要保护累加器、状态寄存器、寄存器组等 8051 Tutorial: Interrupts https://www.sodocs.net/doc/473611601.html,/tutint.php As 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 serial

51单片机中断详解

一、中断的概念 CPU在处理某一事件A时,发生了另一事件B请求C PU迅速去处理(中断发生); CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 待C PU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断二、中断源 在51单片机中有5个中断源 中断号优先级中断源中断入口地址 0 1(最高)外部中断0 0003H 1 2 定时器0 000BH 2 3 外部中断1 0013H 3 4 定时器1 0018H 4 5 串口总段0023H 三、中断寄存器 单片机有10个寄存器主要与中断程序的书写控制有关 1.中断允许控制寄存器IE 2.定时器控制寄存器TC ON 3.串口控制寄存器SCON 4.中断优先控制寄存器IP 5.定时器工作方式控制寄存器TMOD 6.定时器初值赋予寄存器(TH0/TH1,TL0/TL1)

四、寄存器功能与赋值说明 注:在用到中断时,必须要开总中断EA,即EA=1。//开总中断 1.中断允许控制寄存器IE EX0(EX1):外部中断允许控制位 EX0=1 外部中断0开关闭合//开外部0中断 EX0=0 外部中断0开关断开 ET0(ET1):定时中断允许控制位 ET0=1 定时器中断0开关闭合//开内部中断0 ET0=0 定时器中断0开关断开 ES: 串口中断允许控制位 ES=1 串口中断开关闭合//开串口中断 ES=0 串口中断开关断开 2.定时器控制寄存器TCON //控制外部中断和定时器中断 外部中断: IE0(IE1):外部中断请求标志位 当INT0(INT1)引脚出现有效的请求信号,此位由单片机自动置1,cpu开始响应,处理终端,而当入

51单片机中断控制LED

单片机作业 题目要求: 设计这样一个系统:在一个51单片机最小系统板上,P1口低四位接四个四角按键,高四位接四个LED灯。按键中断作为总中断,当接中断的按键按下后,所有灯均可按照对应的按键进行点亮。当没有中断按下时,无论怎么按接在P1口低四位的按键,均不能是按键点亮。 实现步骤: 第一:电路搭建: 电路搭建说明: 1.采用AT89C52单片机,DIP40封装。 2.选用12M,并使晶振尽可能接近单片机,采用22pf的电容接在晶振两边并接地,使晶振更容易起振。 3.标号为D18的LED是中断触发指示灯,一旦中断触发,D18会一直亮着。没有中断触发时会一直灭着。 4.key1,key2,key3,key4分别控制D1,D2,D3,D4,D 5. 5.D5为复位指示灯,当复位按键按下时,D5亮。反之灭。 第二:程序实现: 本程序十分简单,秉着杜绝抄袭,自助设计的理念,本程序完全有本人设计完成。没有采用老师讲解的例程。程序的注释已经将程序称述的很明白,现做简要说明: 本人将按键查询部分都放在中断处理函数中处理。当中断触发按键按下时,D18亮,程序进入中断函数,开始不断查询按键值,并点亮相应led.。这样的程序 对CPU的占有率较高,但由于这样写代码更加简单明了,有由于题目对cpu占有率的并没有明确要求,本着开发周期尽可能短的原则,本程序选择了简单方案。

现将代码复制如下: 将KEIL与PROTEUS联调,调试结果如下: 1.启动程序: ,可以看到图中三角符号变绿。此时:

此时,图中所有led灭,无现象。 1.此时按下任意按键,比如key1,key2两个(为了方便截图,直接将开关用导线短路): 现象如下: 可以看到,并没有认可指示灯亮。 2.按复位按键观察是否正常(为了方便截图,直接将开关用导线短路):

51单片机中断详解

一.中断的概念 1.中断发生 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理 2.中断响应和中断服务 CPU暂时中断当前的工作,转去处理事件B 3.中断返回 待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A 这一过程称为中断 二.中断过程示意图 三.MCS51中断系统的结构

MCS51的中断系统有5个中断源(8052有6个),2个优先级,可实现二级中断嵌套 四.中断寄存器 单片机有10个寄存器主要与中断程序的书写控制有关 1.中断允许控制寄存器IE 2.定时器控制寄存器TCON 3.串口控制寄存器SCON 4.中断优先控制寄存器IP 5.定时器工作方式控制寄存器TMOD 6.定时器初值赋予寄存器(TH0/TH1,TL0/TL1) 五.部分寄存器详解

1.中断允许控制寄存器(IE) EX0:外部中断0允许位; ET0:定时/计数器T0中断允许位; EX1:外部中断1允许位; ET1:定时/计数器T1中断允许位; ES :串行口中断允许位; EA :CPU中断允许(总允许)位。 2.定时器/计数器控制寄存器控制寄存器(TCON) IT0:外部中断0触发方式控制位 当IT0=0时,为电平触发方式(低电平有效) 当IT0=1时,为边沿触发方式(下降沿有效) IE0:外部中断0中断请求标志位 IT1:外部中断1触发方式控制位 IE1:外部中断1中断请求标志位

TF0:定时/计数器T0溢出中断请求标志位 TF1:定时/计数器T1溢出中断请求标志位 3.串行口控制寄存器(SCON) RI:串行口接收中断标志位。当允许串行口接收数据时,每接收完一个串行帧,由硬件置位RI。注意,RI必须由软件清除。 TI:串行口发送中断标志位。当CPU将一个发送数据写入串行口发送缓冲器时,就启动了发送过程。每发送完一个串行帧,由硬件置位TI。CPU响应中断时,不能自动清除TI,TI必须由软件清除。 4.中断优先级控制寄存器(IP) PX0:外部中断0优先级设定位 PT0:定时/计数器T0优先级设定位 PX1:外部中断0优先级设定位 PT1:定时/计数器T1优先级设定位

51单片机中断系统程序实例

51单片机中断系统程序实例(STC89C52RC) 51单片机有了中断,在程序设计中就可以做到,在做某件事的过程中,停下来先去响应中断,做别的事情,做好别的事情再继续原来的事情。中断优先级是可以给要做的事情排序。 单片机的学习不难,只要掌握学习方法,学起来并不难。什么是好的学习方法呢,一定要掌握二个要点: 1. 要知道寄存器的英文全拼,比如IE = interrupt中断 不知道全拼,要去猜,去查。这样就可以理解为什么是这个名称,理解了以后就不用记忆了。 2. 每个知识点要有形像的出处 比如看到TF0,脑子里马上要形像地定位到TCON寄存器的某位 看到ET0, 马上要形像地定位到IE寄存器的第2位 hi.baidu./tuenhai/独家揭秘:形像是记忆的最大技巧。当人眼看到某个图时,是把视觉信号转化成电信号,再转化成人能理解的形像。当我们回忆形像时,就是在重新检索原先那个视觉信号,并放大。在学习过程中,不断练习检索、放大信号,我们的学习能力就会越来越强。

写程序代码时,也要把尽量把每行代码形像化。 51单片机中断源 8051有五个中断源,有两个优先级。与中断系统有关的特殊功能寄存器有IE(中断允许寄存器)、IP(中断优先级控制寄存器)、中断源控制寄存器(如TCON、SCON的有关位)。51单片机的中断系统结构如下图(注意,IF0应为TF0): 8052有6个中断源,它比8051多一个定时器/计数器T2中断源。 8051五个中断源分别是:

(1)51单片机外部中断源 8051有两个外部中断源,分别是INT0和INT1,分别从P3.2和P3.3两个引脚引入中断请求信号,两个中断源的中断触发允许由TCON的低4位控制,TCON的高4位控制运行和溢出标志。 INT0也就是Interrupt 0。在这里应该看一下你的51单片机开发板的电路原理图。离开形像的记忆是没有意义的。读到上面这句,你应该回忆起原理图上的连接。任何记忆都转化为形像,这是学习的根本原理,我们通过学习单片机要学会这种学习方法,会让你一辈子受益无穷。 TCON的结构如下图: (a)定时器T0的运行控制位TR0 TR0由软件置位或者清0。当门控位GATE=0时,TO计数器仅由TR0控制,TR0=1启动计数,TR0=0时停止。当门控位GATE=1时,T0计数器由INT0和TR0共同控制,当INT0=1且TR0=1时启动T0计数器。

51单片机中断程序大全

( //实例42:用定时器T0查询方式P2口8位控制LED闪烁 #include<> // 包含51单片机寄存器定义的头文件 void main(void) { // EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x01; //使用定时器T0的模式1 TH0=(65536-46083)/256; //定时器T0的高8位赋初值 : TL0=(65536-46083)%256; //定时器T0的高8位赋初值 TR0=1; //启动定时器T0 TF0=0; P2=0xff; while(1)//无限循环等待查询 { while(TF0==0) ; ] TF0=0; P2=~P2; TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 //实例43:用定时器T1查询方式控制单片机发出1KHz音频 #include<> // 包含51单片机寄存器定义的头文件 sbit sound=P3^7; //将sound位定义为引脚 void main(void) ( {// EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-921)/256; //定时器T1的高8位赋初值 TL1=(65536-921)%256; //定时器T1的高8位赋初值 TR1=1; //启动定时器T1 TF1=0; while(1)//无限循环等待查询 — { while(TF1==0); TF1=0;

51单片机汇编语言教程:18课单片机中断系统

51单片机汇编语言教程:第18课-单片机中断系统

MCS-51单片机中断系统的结构: 5个中断源的符号、名称及产生的条件如下。 INT0:外部中断0,由P3.2端口线引入,低电平或下跳沿引起。 INT1:外部中断1,由P3.3端口线引入,低电平或下跳沿引起。 T0:定时器/计数器0中断,由T0计满回零引起。 T1:定时器/计数器l中断,由T1计满回零引起。 TI/RI:串行I/O中断,串行端口完成一帧字符发送/接收后引起。整个中断系统的结构框图见下图一所示。

<51单片机中断系统结构> 如图所示,由与中断有关的特殊功能寄存器、中断入口、次序查询逻辑电路等组成,包括5个中断请求源,4个用于中断控制的寄存器IE、IP、ECON和SCON来控制中断类弄、中断的开、关和各种中断源的优先级确定。 中断请求源: (1)外部中断请求源:即外中断0和1,经由外部管脚引入的,在单片机上有两个管脚,名称为INT0、INT1,也就是P3.2、P3.3这两个管脚。在内部的TCON中有四位是与外中断有关的。IT0:INT0触发方式控制位,可由软件进和置位和复位,IT0=0,INT0为低电平触发方式,IT0=1,INT0为负跳变触发方式。这两种方式的差异将在以后再谈。IE0:INT0中断请求标志位。当有外部的中断请求时,这位就会置1(这由硬件来完成),在CPU响应中断后,由硬件将IE0清0。IT1、IE1的用途和IT0、IE0相同。(2)内部中断请求源TF0:定时器T0的溢出中断标记,当T0计数产生溢出时,由硬件置位TF0。当CPU响应中断后,再由硬件将TF0清0。TF1:与TF0类似。TI、RI:串行口发送、接收中断,在串行口中再讲解。2、中断允许寄存器IE在MCS-51中断系统中,中断的允许或禁止是由片内可进行位寻址的8位中断允许寄存器IE来控制的。见下表EAX 其中EA是总开关,如果它等于0,则所有中断都不允许。ES-串行口中断允许ET1-定时器1中断允许EX1-外中断1中断允许。ET0-定时器0中断允许EX0-外中断0中断允许。如果我们要设置允许外中断1,定时器1中断允许,其它不允许,则IE能是EAX 即8CH,当然,我们也能用位操作指令SETB EA SETB ET1SETB EX1 来实现它。3、五个中断源的自然优先级与中断服务入口地址外中断0:0003H定时器0:000BH 外中断1:0013H定时器1:001BH串行口:0023H它们的自然优先级由高到低排列。写到这里,大家应当明白,为什么前面有一些程序一始我们这样写: ORG0000HLJMP START ORG0030H START:。 这样写的目的,就是为了让出中断源所占用的向量地址。当然,在程序中没用中断时,直接从0000H开始写程序,在原理上并没有错,但在实际工作中最好不这样做。优先级:单片机采用了自然优先级和人工设置高、低优先级的策略,即能由程序员设定那些中断是高优先级、

51单片机中断程序大全

//实例42:用定时器T0查询方式P2口8位控制LED闪烁#include<> // 包含51单片机寄存器定义的头文件 void main(void) { // EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x01; //使用定时器T0的模式1 TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 TR0=1; //启动定时器T0 @ TF0=0; P2=0xff; while(1)//无限循环等待查询 { while(TF0==0) ; TF0=0; P2=~P2; TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 | //实例43:用定时器T1查询方式控制单片机发出1KHz音频#include<> // 包含51单片机寄存器定义的头文件 sbit sound=P3^7; //将sound位定义为引脚 void main(void) {// EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-921)/256; //定时器T1的高8位赋初值 TL1=(65536-921)%256; //定时器T1的高8位赋初值 TR1=1; //启动定时器T1 — TF1=0; while(1)//无限循环等待查询 { while(TF1==0); TF1=0; sound=~sound; //将引脚输出电平取反 TH1=(65536-921)/256; //定时器T0的高8位赋初值

基于单片机AT89C51控制的中断控制流水灯课程设计报告

宁波技师学院 摘要 随着计算机技术的迅猛发展,计算机越来越广泛地应用于人们工作和生活的各个领域。作为计算机领域里的一个重要方面单片机及其应用技术近年来也得到了长足的发展。 单片机被广泛地应用在工业自动化控制、智能仪器仪表、数据采集、通讯以及家用电器等领域。单片机以其与通用微机完全不同的发展模式,不断满足工业测控、恶劣环境下可靠运行的要求。、单片机已成为现代工业领域中不可缺少的重要角色。 单片机技术的发展速度十分迅速,速度更快、功能更强的16位、32位单片机以及陆续问世,但8位机,特别是新一代高档8位机具有优异的性能,已能满足大部分单片机应用领域的需要,另外,它还具有可靠性高、外围芯片配套、系统结构简单、应用软件丰富、技术成熟、开发应用方便等优点,在单片机市场中依旧据有一定地位。

目录 一总体设计方案 (1) 1.1系统设计方案 (1) 1.2系统结构框图 (1) 二系统硬件设计 (2) 2.1晶振电路 (2) 2.2复位电路 (3) 2.3数码管电路 (4) 2.4LED指示电路与模式电路 (5) 三软件设计 (6) 3.1主程序流程图 (6) 3.2程序图 (7) 四制作与调试 (10) 五结论 (11) 六致谢 (12) 附录1系统实物图 (13) 2实验原理图 (13) 3系统仿真图 (14) 4 PCB原理图 (15)

一总体设计方案 1.1系统设计方案 流水灯系统主要由:复位电路、晶振电路、数码管显示电路、LED灯指示电路、速度与方式选择电路等部分电路组成。 各器件的选用: 1 单片机的选用: 单片机芯片选用A T89C51。 2数码管的选用: 数码管选用共阳极数码管。 3晶振的选用: 晶振选用的是12MHZ。 1.2系统结构框图 框图如图1.2-1。 图1..2-1系统结构框图

51单片机中断编程

第6章中断系统 在CPU与外设交换信息时,存在一个快速的CPU与慢速的外设间的矛盾。为解决这个问题,采用了中断技术。良好的中断系统能提高计算机实时处理的能力,实现CPU 与外设分时操作和自动处理故障,从而扩大了计算机的应用范围。 当CPU正在处理某项事务的时候,如果外界或内部发生了紧急事件,要求CPU暂停正在处理的工作转而去处理这个紧急事件,待处理完以后再回到原来被中断的地方,继续执行原来被中断了的程序,这样的过程称为中断。向CPU提出中断请求的源称为中断源。微型计算机一般允许有多个中断源。当几个中断源同时向CPU发出中断请求时,CPU应优先响应最需紧急处理的中断请求。为此,需要规定各个中断源的优先级,使CPU 在多个中断源同时发出中断请求时能找到优先级最高的中断源,响应它的中断请求。在优先级高的中断请求处理完了以后。再响应优先级低的中断请求。 当CPU正在处理一个优先级低的中断请求的时候,如果发生另一个优先级比它高的中断请求,CPU能暂停正在处理的中断源的处理程序,转去处理优先级高的中断.请求,待处理完以后,再回到原来正在处理的低级中断程序,这种高级中断源能中断低级中断源的中断处理称为中断嵌套。 MCS-51系列单片机允许有五个中断源,提供两个中断优先级(能实现二级中断嵌套)。每一个中断源的优先级的高低都可以通过编程来设定。中断源的中断请求是否能得到响应,受中断允许寄存器IE的控制;各个中断源的优先级可以由中断优先级寄存器IP 中的各位来确定;同一优先级中的各中断源同时请求中断时,由内部的查询逻辑来确定响应的次序。这些内容都将在本节中讨论。 6 . 1 中断请求源和中断请求标志 1、中断请求源 MCS-51中断系统可用图6-1来表示。五个中断源是: INT来自P3.2引脚上的外部中断请求(外中断0)。 ◆0 INT来自P3.3引脚上的外部中断请求(外中断1)。 ◆1 ◆T0 片内定时器/计数器0溢出(TF0)中断请求。 ◆T1片内定时器/计数器1溢出(TF1)中断请求。 ◆串行口片内串行口完成一帧发送或接收中断请求源TI或RI。 每一个中断源都对应有一个中断请求标志位,它们设置在特殊功能寄存器TCON和SCON中。当这些中断源请求中断时,分别由TCON和SCON中的相应位来锁存。

51单片机中断系统详解(定时器、计数器)

51单片机中断系统 51单片机中断级别 中断源默认中断级别序号(C语言用) INT0---外部中断0 最高0 T0---定时器/计数器0中断第2 1 INT1---外部中断1 第3 2 T1----定时器/计数器1中断第4 3 TX/RX---串行口中断第5 4 T2---定时器/计数器2中断最低 5 中断允许寄存器IE 位序号DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 符号位EA ------- ET2 ES ET1 EX1 ET0 EX0 EA---全局中允许位。 EA=1,打开全局中断控制,在此条件下,由各个中断控制位确定相应中断的打开或关闭。EA=0,关闭全部中断。 -------,无效位。 ET2---定时器/计数器2中断允许位。EA总中断开关,置1为开; ET2=1,打开T2中断。EX0为外部中断0(INT0)开关,…… ET2=0,关闭T2中断。ET0为定时器/计数器0(T0)开关,……ES---串行口中断允许位。EX1为外部中断1(INT1)开关,…… ES=1,打开串行口中断。ET1为定时器/计数器1(T1)开关,…… ES=0,关闭串行口中断。ES为串行口(TX/RX)中断开关,…… ET1---定时器/计数器1中断允许位。ET2为定时器/计数器2(T2)开关,…… ET1=1,打开T1中断。 ET1=0,关闭T1中断。 EX1---外部中断1中断允许位。 EX1=1,打开外部中断1中断。 EX1=0,关闭外部中断1中断。 ET0---定时器/计数器0中断允许位。 ET0=1,打开T0中断。 ET0=0,关闭T0中断。 EX0---外部中断0中断允许位。 EX0=1,打开外部中断0中断。 EX0=0,关闭外部中断0中断。 中断优先级寄存器IP 位序号DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0 位地址--- --- --- PS PT1 PX1 PT0 PX0 -------,无效位。 PS---串行口中断优先级控制位。

51单片机外部中断详解

一.外部中断相关寄存器 1.定时器/计数器控制寄存器控制寄存器(TCON)? ? IT0:外部中断0触发方式控制位? 当IT0=0时,为电平触发方式(低电平有效)? 当IT0=1时,为边沿触发方式(下降沿有效)? IT1:外部中断1触发方式控制位? 当IT1=0时,为电平触发方式(低电平有效)? 当IT1=1时,为边沿触发方式(下降沿有效) 2.中断允许控制寄存器(IE)? ? EX0:外部中断0允许位;? EX1:外部中断1允许位;? EA :CPU中断允许(总允许)位。 二.外部中断的处理过程 1、设置中断触发方式,即IT0=1或0,IT1=1或0?

2、开对应的外部中断,即EX0=1或EX1=1;? 3、开总中断,即EA=1;? 4、等待外部设备产生中断请求,即通过,口连接外部设备产生中断? 5、中断响应,执行中断服务函数 三.程序编写 要求:通过两位按键连接外部中断0和1,设定外部中断0为下降沿触发方式,外部中断1为低电平触发方式,按键产生中断使数字加减,用一位共阳极数码管来显示数值。? 目的:感受外部中断对程序的影响,体会低电平触发和下降沿触发的区别。 #include<>#define uint unsigned int #define uchar unsigned char uchar code dat[]={0xc0, 0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};uint num; void main() { EA=1; //开总中断 IT0=1; //下降沿触发 IT1=0; //低电平触发 EX0=1; //外部中断0允许 EX1=1; //外部中断1允许 while(1) { P0=dat[num%10]; } } void plus() interrupt 0???? //外部中断0 { EX0=0;

51单片机 流水灯 中断

//51单片机控制8个LED灯,左右循环移动,当外部中断0引脚的按键,第一次按下时,停在当前位置;第二次按下时,继续向下执行 //***************************************************************************** ***************************************** //注释:当主函数中在执行左右流水点亮LED灯的时候,按键按下(这是第一次按下,即奇数次),CPU暂时 //中断当前点亮灯的工作,转去处理中断程序(c=1),处理完后,再返回原来中断的地方继续原来的工作, //因为这时候C为1,while(c);为真,为死循环状态,即是LED亮的状态停在当前位置;当按键按下(这是第二次按下,即偶数次) //CPU中断当前状态,转去处理中断程序(c=0),处理完后,再返回原来中断的地方继续原来的工作, //这时候C为0,while(c);为假,则程序继续向下执行。 //***************************************************************************** ****************************************** #include<> #include<>//控制左右移的头文件 void delay(int);//声明延时函数 unsigned char i=0,a=0,b=0,c=0;//a为判断按键按下时奇数次还是偶数次 void main() { P2=0xfe; IT0=0;// 低电平有效 EX0=1;//开外部中断0 EA=1; //开总中断 while(1) { for(i=0;i<7;i++)//左循环 { b=1; while(c);//C为0时,顺序向下执行,为1时停在当前状态, P2=_crol_(P2,1); delay(500); } for(i=0;i<7;i++)//右循环 { b=1; while(c);//C为0时,顺序向下执行,为1时停在当前状态, P2=_cror_(P2,1); delay(500); }

相关主题