微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51单片机之寄存器-3.2单片机中断

51单片机之寄存器-3.2单片机中断

时间:11-21 来源:互联网 点击:
单片机中断之前,先来个通俗的例子。假如今天有快递来,你要知道快递什么时候到有两种方式,第一种,每隔一分钟你到楼下看快递到了没,这样总有一次能碰到快递。第二种,快递来了,给打电话,然后你去取快递。第一种称为查询法,很明显这种方式很浪费体力。第二种就是中断了,比较轻松。这样我们来详细的探讨一下这个过程。假如你在家里正在看电影,忽然电话响了通知你取快递,于是你把电影暂停,下楼取快递,然后回来继续看电影,如下图所示

图1 日常生活中的中断?

这个就是日常生活中的中断场景。我们再概述一下这个过程,当你正在处理某件事情的时候(看电影),外界发生了比较急的事件请求(电话通知快递到了), 你暂停当前的工作(看电影),转而去处理这个比较急的事件(取快递),处理完以后,再回到原来的地方,继续原来的工作(看电影)。把前面这句话中的”你”换成CPU就是单片机的中断过程了。电话铃响就是中断源用来通知你(CPU), 然后你(CPU)暂停当前事情,去取快递。取快递表示CPU进入中断服务程序,也就是你接受中断请求源后决定做什么。日常生活中的中断源多种多样,比如水烧开了,敲门声,闹钟响了等等。同样单片机中也有多种中断源,STC89C52单片机有8种中断源,外部中断(外部中断0-3),定时器中断(0-2),串口中断. 那么问题又来了,既然这么多中断源,如果同时发生应该处理哪个呢?比如电话响起的时候,家里的水也烧开了,你该优先处理哪个,当然要把烧水的先关掉,这个可能产生危险,因此水烧开了的优先级要于取快递。同样在单片机中断源也有优先级高低之分,这样同时向CPU发出请求的时候,CPU能判断回复哪一个。而且这些中断源可以通过软件来设置,一共可以设置成四个优先级。

如上表所示,你可以通过IPH,IP来设置中断源的优先级,比如Timer0通过设置PT0H,PT0为1,1,那么Timer0就是最高优先级3了。这样又有一个问题,如果现在我把Timer1也设置成最高优先级3,Timer0和Timer1同时向CPU发出请求,CPU该怎么办呢?同样在上表中给出了答案,通过相同优先级内的查询次序来解决。每个中断都有两个开关,一个总开关和一个分开关控制。CPU要能顺利进入中断服务程序,每个中断对应的两个中断允许控制位必须打开。如上表中的Timer0中断允许位ET0/EA,其中EA为总中断开关,EA如果关闭,所有中断均无效,另外ET0为分开关。关于中断中的中断(中断嵌套),我们后面讨论,现在我们举个例子体验一下。

例3-2通过定时器0中断来控制LED亮1秒,灭1秒

现在来分析一下这个例子,题目中说要通过定时器中断来控制LED0。既然是中断,那么中断谁?CPU怎么知道发生中断了,如何处理?很容易得出如下解决步骤:

(1) CPU正在干什么(看电影)

(2) 发生了什么比较急的事情(快递来了)

(3) 如何通知CPU(电话铃响)

(4) CPU如何处理(取快递)

(5)处理完后回到原来的工作(看电影)

第1步,CPU正在干什么。这里可以让CPU什么都不干,或者点亮另外一个LED1等待. 第2步,定时器计时并溢出。第3步,硬件TF0置1,通知CPU。第4步,CPU如何处理?就是指CPU进入中断服务程序。在中断服务程序中,我们判断如果定时1秒则点亮或者熄灭LED0. 这里需要注意定时器0的中断号为interrupt 1,其他中断号如下:

  • void MyInt0(void) interrupt 0;//外部中断0
  • //MyInt0中断函数名,可以自己修改,interrupt 0中断号,不能修改,以下类似
  • void MyTimer0(void) interrupt 1;//定时器0中断
  • void MyInt1(void) interrupt 2;//外部中断1
  • void MyTimer1(void) interrupt 3;//定时器1中断
  • void MyUART(void) interrupt 4;//串口中断
  • void MyTimer2(void) interrupt 5;//定时器2中断
  • void MyInt2(void) interrupt 6;//外部中断2
  • void MyInt3(void) interrupt 7;//外部中断3

参考代码如下:

  • #include "reg52.h"

  • void timer0_init(void);
  • sbit LED0=P1^0;//设置LED0引脚
  • sbit LED1=P1^6;//设置LED1引脚
  • unsigned char i=0;
  • void main(void)
  • {
  • ET0=1;//打开定时器0中断
  • EA=1;//打开总中断
  • timer0_init();//发生了什么事件
  • while(1)//CPU正在干什么?
  • {
  • LED0=0;
  • }
  • }
  • void timer0_init(void)
  • {
  • TMOD=0X01;//定时器模式选择16bit
  • TH0=0X4C;
  • TL0=0X00;//TH0,TL0初始值
  • TR0=1;//开启定时器
  • }
  • void timer0_intrrupt () interrupt 1//定时器0中断服务程序
  • {
  • TH0=0X4C;
  • TL0=0X00;
  • i++;
  • if(i==20)//定时次数达到20,那么总定时为1秒
  • {
  • i=0;
  • LED1=~LED1;
  • LED0=1;
  • }
  • }


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top