51单片机外部中断与定时器的实用

合集下载

51单板机定时和外部中断用到的寄存器说明

51单板机定时和外部中断用到的寄存器说明

51单板机定时和外部中断用到的寄存器说明1.TMOD:定时器设置寄存器,不可按位寻址,0x89TMOD=0x01;//初始化定时器0, 根据晶振频率计算定时时间//假设晶振频率12MHz, 则时钟频率1/12 微秒,一个机器周期(访问一次存储器的时间)是12个时钟周期=1微秒。

//下面设置延时50ms。

TH0=(65535-50000)/256 ;TL0=(65535-50000)%256 ;2.TCON:定时器控制寄存器,可按位寻址0X88//启动定时器0,开始计数TR0=1;3.IE:中断允许寄存器,可按位寻址0XA8//开启定时器0中断ET0=1;//开启总中断控制EA=1;4.IP:中断优先控制寄存器,0XB85. SCON:串口控制寄存器,0X98//模式1波特率计算公式://fosc=晶振频率//SMOD=PCON 寄存器D7,当SMOD=1时,频率倍增//T1定时/计数器,TH1=计数器高8位,TL1=计数器低8位//BaudRate=((2^SMOD)/32)*(T1的溢出率);//T1的溢出率=fosc/(12*(256-TH1));//所以可以根据需要设置的波特率反向推导TH1/TL1//TH1=TL1=256-(fosc*2^SMOD)/(baudrate*12*32);//以下设置一个9600bps 波特率,并开始外部中断PCON=0X00; //SMOD=0TH1=0XFD; // 波特率9600bpTL1=0XFD;SCON = 0x50; // 工作方式1ES = 0; // 关闭串口中断IT0 = 0; // 外部中断0使用电平触发模式TMOD = 0x01;EX0 = 1;EA = 1;6. PCON: 0X87,51单片机借用SMOD 位作为波特率系数7.中断和定时器C例程//使用外部中断,当中断发生时向串口发送特定数据#include <reg51.h>#define uchar unsigned char#define uint unsigned intvoid GetTrigger(); //获取外部中断状态void Ex0Init();void SendBuff(uchar *buf,uchar len);void SendByte(uchar da);void main(void){Ex0Init();while(1);}void GetTrigger(void) interrupt 0{//当外部中断发生(如地感触发,ALARM IN 短接),向串口发送一个状态数据SendByte(0xdd);}void Ex0Init(){//初始化外部中断PCON = 0x00; // SMOD = 1TH1=0XFD; // 波特率9600bp=256-(FOSC*2^SMOD)/(baudrate*12*32)TL1=0XFD;SCON = 0x50; // 工作方式1ES = 0; // 关闭串口中断IT0 = 0; // 外部中断0使用电平触发模式TMOD = 0x01;EX0 = 1;EA = 1;}/* send one byte, no verify*/void SendByte(uchar da){TI=0;SBUF=da;while(!TI);TI=0;}/* to send a data buffer*/void SendBuff(uchar *buf,uchar len){uchar i;for(i=0;i<len;i++){SendByte(*buf);buf++;}while(!TI);TI = 0;}//使用定时器T0#include <at89x51.h>#define HI ((65536 - 50000) / 256)#define LO ((65536 - 50000) % 256)#define _TH0_TL0_ (65536 - 50000)#define M 20 //(1000/25)unsigned hou = 12, min = 0, sec = 0;//0-9数字unsigned char SEG_TAB_B[ ] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //0.-9.数字unsigned char SEG_TAB_A[ ] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; void Delay(unsigned char a)//延时程序a*1MS{unsigned char j;while(a-- != 0){for (j = 0; j < 125; j++);}}//数码管显示void Disp(void){P2_0 = 1;P1 = SEG_TAB_B[ hou / 10 ];Delay(5);P2_0 = 0;P2_1 = 1;P1 = SEG_TAB_A[ hou % 10 ];Delay(5);P2_1 = 0;P2_2 = 1;P1 = SEG_TAB_B[ min / 10 ];Delay(5);P2_2 = 0;P2_3 = 1;P1 =SEG_TAB_A[ min % 10 ];Delay(5);P2_3 = 0;P2_4 = 1;P1 = SEG_TAB_B[ sec / 10 ];Delay(5);P2_4 = 0;P2_5 = 1;P1 = SEG_TAB_B[ sec % 10 ];Delay(5);P2_5 = 0;}//定时中断函数50msvoid IsrTimer0(void) interrupt 1 using 1{static unsigned char count = 0; //定义静态变量count count++;if(count == M){count = 0;sec++;if(sec == 60){min++;sec = 0;if(min == 60){hou++;min = 0;if(hou == 24){hou = 0;}}}}}void Timer0Init(void) //定时器0 {TMOD = 0x01;TH0 = HI;TL0 = LO;TR0 = 1;ET0 = 1;EA = 1;}//主函数void main(void){Timer0Init();while(1){Disp();}}。

51单片机串口中断与定时器中断共存同时使用

51单片机串口中断与定时器中断共存同时使用

51单片机串口中断与定时器中断共存同时使用#include#include#define uchar unsigned char#define uint unsigned intsbit led1=P2^0;uchar SerialV alue; //串口接收到的值;uchar i;void main(){smglk=0;smgbitlk=0;ledlk=1;//----- Serial Port Setting -----TMOD=0x21; //设定定时器为方式2 可自动再装入的定时器SM0=0; //设定串口工作方式1 10位异步收发器8位数据SM1=1; //设定串口工作方式1 10位异步收发器8位数据TH1=0xfd;//装入初值TL1=0xfd; //装入初值PCON=0x00; //设定串行口波特率REN=1; //允许串行接收位。

REN=1,启动接收数据;REN=0,禁止接收。

IP=0x10;TH0=(65535-50000)/256;TL0=(65535-50000)%256;TR0=1; //启用T0定时器/计数器ET0=1; //T0定时器中断开关;(开)TR1=1; //启用T1定时器/计数器ET1=1; //T1定时器中断开关;(开)ES=1; //串行中断开关;(开) EA=1; //总中断开关;(开) SerialV alue=0x02;while(1){}}//串口中断void serial() interrupt 4 {SerialV alue=SBUF;RI=0;}void timer0() interrupt 1 {TH0=(65535-50000)/256; TL0=(65535-50000)%256; i++;if(i>SerialV alue){i=0;led1=!led1;}}。

第05章 MCS-51单片机的中断与定时(1-4)

第05章 MCS-51单片机的中断与定时(1-4)

2
1
TH0
;P1.0输出“0” ;P1.0输出“1”
5.2 MCS-51单片机的中断系统
五、外中断应用举例
1. 中断初始化程序
设置外中断源的触发方式 设置中断允许寄存器IE 设置中断优先级寄存器IP
2. 中断服务程序
保护现场 中断处理 恢复现场
23/65
5.2 MCS-51单片机的中断系统
【例5-3】 设外部中断0为下降沿触发方 式,高优先级,试编写中断初始化程序
5.2 MCS-51单片机的中断系统
【例5-4】 将单脉冲接到外中断0(INT0)引脚,利 用P1.0作为输出,经反相器接发光二极管。编写程 序,每按动一次按钮,产生一个外中断信号,使发 光二极管的状态发生变化,由亮变暗,或反之
P1.0 单脉冲 发生器 INT0
1
+5V
8031
26/65
5.2 MCS-51单片机的中断系统
串口:0023H
20/65
5.2 MCS-51单片机的中断系统
四、中断请求的撤除
1.定时/计数器中断请求标志TF0/TF1会自动撤除 2.串行口中断请求标志TI/RI要用指令撤除
CLR TI ;清TI标志位 CLR RI ;清RI标志位
3.负脉冲触发的外中断请求标志IE0/IE1会自动撤除 4.低电平触发的外中断请求信号需要外加电路撤除
下次课前请预习5.3节
30/65
5.3 51单片机的定时器/计数器
MCS-51单片机内部有两个16位定时/计数器 T0和T1,简称定时器0和定时器1
在特殊功能寄存器TMOD和TCON的控制下, 它们既可以设定成定时器使用,也可以设定 成计数器使用
定时/计数器有4种工作方式,具有中断功能, 可以完成定时、计数、脉冲输出等任务

51单片机实验——单片机定时与外部中断

51单片机实验——单片机定时与外部中断

实验题目:单片机定时与外部中断的作用1 一、实验目的1)熟悉单片机定时功能的使用2)熟悉外部中断的使用3)熟悉一些常用的C语言编程语句4)熟练单片机的一些使用及操作方法二、实验原理工作原理框图7_SEG_LED:8_BI Ts_LED:三、参考程序#include <reg51.h>#define FOSC 11059200L#define BAUD 9600#define TRUE 1#define FALSE 0int CmpCnt;int T0IntCnt;bit FlagTimerOk;unsigned char LedVal;sbit HC373_CLK = P3^6;sbit Int0=P3^2;sbit P1_4=P1^4;sbit P1_5=P1^5;sbit P1_6=P1^6;sbit P1_7=P1^7;unsigned char code a[10]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x19};void Init_T0(void){TMOD = 0x01; //T0 方式1TH0 = (65536-(FOSC)/1200)/256;TL0 = (65536-(FOSC)/1200)&0xff;ET0 = 1;TR0 = 1;}void Init_Uart(void){SCON = 0x50; //UART设置PCON = 0x80;TMOD = 0x21;TH1=0xfa; //定时器1设置TL1=0xfa;TR1=1;ES=1;EA=1;}void Init_INT0(void) interrupt 0 {int s;s=0;while(Int0==0)s++; //防抖设置if(s>100){if(CmpCnt>1)CmpCnt=CmpCnt-1;elseCmpCnt=50;s=0;}}void Init_Ram(void){T0IntCnt = 0;FlagTimerOk = FALSE;CmpCnt = 50;LedVal = 0xff;}void T0_ISR(void) interrupt 1{if(++T0IntCnt >= CmpCnt){T0IntCnt = 0;FlagTimerOk = TRUE;}TH0 =(65536-(FOSC)/1200)/256;TL0 =(65536-(FOSC)/1200)&0xff;TR0 = 1;ET0 = 1;EA = 1;}void LedCtrl(void){static int j=0;LedVal = 0xff & (~(1<<j));if(++j >= 8){j = 0;}P0 = LedVal;HC373_CLK = 1;HC373_CLK = 0;}void delay() //延时函数{int x,y;for(x=0;x<2;x++)for(y=0;y<120;y++);}void main(void){Init_Ram();Init_Uart();Init_T0();EX0=1;IT0=0;EA = 1;while(1){if(FlagTimerOk){FlagTimerOk = FALSE;LedCtrl();}P1_7=1;P1_5=0;P1_6=0;P1_4=0;P0=0x02;delay(); //七段数码管显示 P1_6=1;P1_4=0;P1_5=0;P1_7=0;P0=a[CmpCnt%10];delay(); P1_5=1;P1_4=0;P1_6=0;P1_7=0;P0=a[CmpCnt/10];delay();}}四、实验步骤1、启动Keil C,新建project;2、将写好的文件保存为.c文件;3、译生成hex文件后,用flash magic烧录到单片机中;4、片机复位上电,运行;5、按住INT0键,观察不同的数字显示对应LCD显示的变化;实验结果每按下INT0一次,数码管的显示示数减少10,从启动时的500一直减小到10,然后又恢复500,并且发光二极管的点亮时间和显示的一致,频率越高,LCD跑马灯跑得越快。

单片机中的中断与定时器的原理与应用

单片机中的中断与定时器的原理与应用

单片机中的中断与定时器的原理与应用在单片机(Microcontroller)中,中断(Interrupt)和定时器(Timer)是重要的功能模块,广泛应用于各种嵌入式系统和电子设备中。

本文将介绍中断和定时器的基本原理,并探讨它们在单片机中的应用。

一、中断的原理与应用中断是指在程序执行过程中,当发生某个特定事件时,暂停当前任务的执行,转而执行与该事件相关的任务。

这样可以提高系统的响应能力和实时性。

单片机中的中断通常有外部中断和定时中断两种类型。

1. 外部中断外部中断是通过外部触发器(如按钮、传感器等)来触发的中断事件。

当外部触发器发生状态变化时,单片机会响应中断请求,并执行相应的中断服务程序。

外部中断通常用于处理实时性要求较高的事件,如按键检测、紧急报警等。

2. 定时中断定时中断是通过定时器来触发的中断事件。

定时器是一种特殊的计时设备,可以按照设定的时间周期产生中断信号。

当定时器倒计时完成时,单片机会响应中断请求,并执行相应的中断服务程序。

定时中断常用于处理需要精确计时和时序控制的任务,如脉冲计数、PWM波形生成等。

中断的应用具体取决于具体的工程需求,例如在电梯控制系统中,可以使用外部中断来响应紧急停车按钮;在家电控制系统中,可以利用定时中断来实现定时开关机功能。

二、定时器的原理与应用定时器是单片机中的一个重要模块,可以用于计时、延时、频率测量等多种应用。

下面将介绍定时器的工作原理和几种常见的应用场景。

1. 定时器的工作原理定时器是通过内部时钟源来进行计时的。

它通常由一个计数器和若干个控制寄存器组成。

计数器可以递增或递减,当计数值达到设定值时,会产生中断信号或触发其他相关操作。

2. 延时应用延时是定时器最常见的应用之一。

通过设定一个合适的计时器参数,实现程序的精确延时。

例如,在蜂鸣器控制中,可以使用定时器来生成特定频率和持续时间的方波信号,从而产生不同的声音效果。

3. 频率测量应用定时器还可以用于频率测量。

51单片机中断程序例子

51单片机中断程序例子

51单片机中断程序例子
1. 外部中断:当外部信号引脚检测到高电平时,单片机会触发外部中断服务程序。

可以利用外部中断实现按键扫描功能,当按键按下时,触发中断程序对按键进行处理。

2. 定时器中断:利用定时器中断可以实现精确的时间控制。

例如,我们可以设置定时器中断为1秒,当定时器溢出时,触发中断程序,实现1秒钟执行一次的任务。

3. 串口中断:当接收到串口数据时,单片机会触发串口中断服务程序,可以利用串口中断实现串口通信功能。

4. ADC中断:当模数转换器完成一次转换时,单片机会触发ADC中断服务程序,可以利用ADC中断实现模拟信号的采集和处理。

5. 看门狗中断:看门狗定时器溢出时,单片机会触发看门狗中断服务程序,可以利用看门狗中断实现系统复位或其他相关功能。

6. 外部中断优先级:当多个外部中断同时触发时,可以通过设置外部中断的优先级来确定触发的顺序和优先级。

7. 定时器中断优先级:当多个定时器中断同时触发时,可以通过设置定时器中断的优先级来确定触发的顺序和优先级。

8. 中断嵌套:单片机支持中断嵌套,即在一个中断服务程序中触发
另一个中断服务程序,可以通过中断嵌套实现复杂的任务处理。

9. 中断屏蔽:单片机支持对中断的屏蔽,即可以通过设置中断屏蔽标志位来屏蔽某些中断,使其暂时不被触发。

10. 中断标志位:单片机提供中断标志位,用于标识中断是否被触发。

在中断服务程序中,可以通过读取和清除中断标志位来判断中断是否发生。

以上是根据51单片机中断程序的例子进行的描述,这些例子涵盖了常见的中断类型和相关功能。

通过学习和理解这些例子,可以更好地掌握51单片机中断编程的原理和方法。

51单片机中断总结

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。

51单片机每个外部中断和定时器中断 应用模版

51单片机每个外部中断和定时器中断 应用模版

第一步,中断配置/************************************************************函数名:INT0_Config功能:配置单片机与中断相关的硬件,让单片机能够正常检测中断和执行中断代码。

输入参数:输出参数:************************************************************/void INT0_Config(void){IT0=1; //中断触发方式,IT0=0,低电平触发,INT0=1下降沿触发(下降沿就是由高电平向低电平的跳变);EX0=1; //外部中断0的中断开关,每个中断源都有自己的中断开关。

EA=1; //打开总中断,如果总中断不打开,就是其他中断开关被打开,单片机也不能执行中断。

}第二步,中断服务,也就是cpu被中断后所要做的事。

/************************************************************函数名:Isr_INT0功能:中断服务输入参数:输出参数:************************************************************/void Isr_INT0() interrupt 0 //interrupt表明该函数是中断函数,后面的标号表示是哪个中断源产生的中断。

{ //(INT0)为0, Timer0为1,INT1为2,Timer3,串口中断为4。

// Add your code here //自己想要中断后发生的程序}第三部主函数/************************************************************函数名:main功能:主函数输入参数:输出参数:************************************************************/void main(){INT0_Config();//调用这个函数来配置外部中断while(1){//Add your code here//CPU一直在这里循环的执行代码,一旦发生中断,就停下来去执行中断函数Isr_INT0() interrupt 0,//执行完成后,返回从断点处继续往下执行原来的代码。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

中断使能寄存器
通过设置中断使能寄存器 IE 的 EA 位 使能所有中断 每个中断源都有单独的使能位 可通过软件设置 IE 中相应的使能位在任何时候使能或禁能中断 中断使能寄存器 IE 的各 位如下所示
中断使能寄存器IE
位地址 0AFH 0AEH 0ADH 0ACH 0ABH 0AAH 0A9H 0A8H 位符号 EA
/ ET2 ES
ET1 EX1 ET0 EX0
EA 使能标志位 置位则所有中断使能 复位则禁止所有中断保留 ET2 定时器2 中断使能 ES 串行通信中断使能 ET1 定时器 1 中断使能 EX1 外部中断 1 使能 ET0 定时器0 中断使能 EX0 外部中断 0使能
8051 支持两个中断优先级 有标准的中断机制, 低优先级的中断只能被高优先级的中断所中断 ,而高优先级的中断不能被中断。

中断优先级寄存器
每个中断源都可通过设置中断优先级寄存器IP 来单独设置中断优先级 如果每个中断源的相应位被置位 则该中断源的优先级为高,如果相应的位被复位, 则该中断源的优先级为低, 如果你觉得两个中断源不够用 ,别急以后我会教你如何增加中断优先级 表 A-5 示出了 IP 寄存器的各位 此寄存器可位寻址 IP 寄存器
位地址 0BFH 0BEH 0BDH 0BCH 0BBH 0BAH 0B9H 0B8H 位符号 /
/
/ PS PT1 PX1 PT0 PX0
编号 中断源
中断向量
上电复位 0000H 0 外部中断0 0003H 1 定时器0溢出 000BH 2 外部中断1 0013H 3 定时器1溢出 001BH 4 串行口中断 0023H 5
定时器2溢出 002BH
PT2 定时器 2中断优先级 PS 串行通信中断优先级 PT1 定时器 1中断优先级 PX1 外部中断1 优先级 PT0 定时器0中断优先级 PX0 外部中断0 优先级
定时器控制寄存器 TCON
TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 TF1 定时器1溢出中断标志响应中断后由处理器清零
TR1 定时器1控制位置位时定时器 1 工作复位时定时器 1 停止工作
TF0 定时器0溢出标志位定时器 0 溢出时置位处理器响应中断后清除该位TR0 定时器0控制位置位时定时器 0 工作复位时定时器 0 停止工作
IE1 外部中断1 触发标志位当检测到 P3.3 有从高到低的跳变电平时置位处理器响应中断后由硬件清除该位
IT1 中断1 触发方式控制位置位时为跳变触发复位时为低电平触发
IE0 外部中断1 触发标志位当检测到 P3.3 有从高到低的跳变电平时置位处理器响应中断后由硬件清除该位
IT0 中断1 触发方式控制位置位时为跳变触发复位时为低电平触发
定时器控制寄存器 TMOD
GATE C/T M1 M0 GATE C/T M1 M0 定时器1 定时器0
GATE 当 GATE置位时定时器仅当 TR=1并且 INT=1 时才工作如果 GATE=0 置位TR 定时器就开始工作
C/T 定时器方式选择如果 C/T=1 定时器以计数方式工作 C/T=0 时以
定时方式工作
M1 模式选择位高位
M0 模式选择位低位
定时器:
1、设置TMOD工作方式
2、允许定时器中断设置IE(ET0/ET1)
3、启动定时器设置TCON TR0/TR1
4、设置定时器初值 TH0、TL0
EA=1;
TR0=1;
ET0=1;
中断:
1、设置中断使能寄存器 IE的EX0
2、设置TCON 中断方式上升沿是下降沿(IT0/IT1)
EA=1;
EX0=1;
IT0=1;。

相关文档
最新文档