中断流程分析与示例

电子说

1.3w人已加入

描述

中断的概念:
      CPU在处理某一事件A时,发生了另一事件B的请求(中断请求);CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返),这一过程称为中断。

cpu中断执行过程图

      如何执行如上图所示:先执行主程序,到达断点的地方出现中断请求,此时执行中断响应,执行中断处理程序,执行完中断返回断点,再继续执行主程序。

中断源:
      引起CPU中断的根源,称为中断源。中断源向CPU提出的中断请求。CPU暂时中断原来的事务A,转去处理事件B。对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。实现上述中断功能的部件称为中断系统(中断机构)。
中断的优点:
      分时操作:CPU可以分时为多个外设服务,提高了计算机的利用率;
      实时响应:CPU能够及时处理应用系统的随机事件,系统的实时性大大增强;
      可靠性高:CPU具有处理设备故障及掉电等突发性事件能力,从而使系统可靠性提高。

定义中断函数的一般形式: 
      viod 函数名() interrupt n
      (1) interrupt必须要加,表示定义成中断服务函数。
      (2)后面n是中断号,中断号是编译器识别不同中断的唯一编号.
中断服务函数和普通函数的异同:
      同:函数的形式非常类似,中断响应过程和普通函数调用过程也非常相似。
      异:①中断服务函数不需要声明,普通函数一般需要声明。②普通函数的执行是可预测的;而中断服务函数的执行是不可预测的。③普通函数的跳转是软件(函数调用语句)完成的;中断的跳转(中断响应)是由硬件完成的,只要发生了中断事件,并且中断被允许,硬件自动会帮我们完成中断的跳转(中断响应)。④普通函数:通过函数名找到被调用函数;中断服务函数:通过中断号找到中断服务函数。所以我们可以知道,中断服务函数中的函数名其实并没有什么作用。
使用中断函数时应遵循以下规则:
      (1)中断函数不能进行参数转递;
      (2)在任何情况下,都不能直接调用中断函数。

那么我们如何通过keil使用51单片机外部中断0触发数码管显示三位数字呢?

下面给予chatGPT示例

#include

sbit LED = P1^0;   //定义LED连接的IO口
sbit KEY = P3^2;   //定义KEY连接的IO口

unsigned int num = 0;   //定义计数器

void delay(unsigned int x)   //延时函数
{
   unsigned int i, j;
   for(i=0; i       for(j=0; j<125; j++);
}

void display(unsigned int n)   //数码管显示函数
{
   unsigned char code table[] = {   //数码管显示表
       0x3f,  //0
       0x06,  //1
       0x5b,  //2
       0x4f,  //3
       0x66,  //4
       0x6d,  //5
       0x7d,  //6
       0x07,  //7
       0x7f,  //8
       0x6f   //9
   };
   unsigned int i, j;
   for(i=0; i<3; i++)
   {
       P2 = 0xff;   //关闭所有数码管
       switch(i)   //选择要显示的数位
       {
           case 0:
               P0 = 0xfe;   //第一位数码管
               break;
           case 1:
               P0 = 0xfd;   //第二位数码管
               break;
           case 2:
               P0 = 0xfb;   //第三位数码管
               break;
       }
       P2 = table[n%10];   //显示个位数字
       delay(1);   //延时一段时间
       P2 = 0xff;   //关闭所有数码管
       switch(i)   //选择要显示的数位
       {
           case 0:
               P0 = 0xfd;   //第二位数码管
               break;
           case 1:
               P0 = 0xfb;   //第三位数码管
               break;
           case 2:
               P0 = 0xf7;   //第四位数码管
               break;
       }
       P2 = table[n/10%10];   //显示十位数字
       delay(1);   //延时一段时间
       P2 = 0xff;   //关闭所有数码管
       switch(i)   //选择要显示的数位
       {
           case 0:
               P0 = 0xfb;   //第三位数码管
               break;
           case 1:
               P0 = 0xf7;   //第四位数码管
               break;
           case 2:
               P0 = 0xef;   //第五位数码管
               break;
       }
       P2 = table[n/100%10];   //显示百位数字
       delay(1);   //延时一段时间
       P2 = 0xff;   //关闭所有数码管
       switch(i)   //选择要显示的数位
       {
           case 0:
               P0 = 0xf7;   //第四位数码管
               break;
           case 1:
               P0 = 0xef;   //第五位数码管
               break;
           case 2:
               P0 = 0xdf;   //第六位数码管
               break;
       }
       P2 = table[n/1000%10];   //显示千位数字
       delay(1);   //延时一段时间
   }
}

void main()
{
   EA = 1;   //开启总中断
   EX0 = 1;   //开启外部中断0
   IT0 = 1;   //设置外部中断0为下降沿触发
   while(1)
   {
       display(num%1000);   //显示后三位数字
   }
}

void Interrupt0() interrupt 0   //外部中断0中断服务函数
{
   num++;   //计数器加1
   LED = ~LED;   //LED翻转
}
      在上面的代码中,我们定义了一个计数器num,并在外部中断0中断服务函数中将其加1。同时,在main函数中,我们使用display函数来显示num的后三位数字。display函数中使用了一个数码管显示表来将数字转换为数码管的显示码,然后通过控制数码管的选择位和段选位来实现数码管的显示。在每次显示完一个数位后,我们都会延时一段时间,以控制数码管的亮度和显示效果。最后,我们在main函数的无限循环中不断调用display函数,以实现数码管的动态显示。

      需要注意的是,在使用外部中断0时,我们需要先开启总中断(EA=1),然后再开启外部中断0(EX0=1)。同时,我们还需要设置外部中断0的触发方式,可以选择下降沿触发(IT0=1)或者上升沿触发(IT0=0),具体根据实际情况而定。在外部中断0中断服务函数中,我们可以进行一些需要立即响应的操作,比如计数器加1、LED翻转等。

我觉得还是太复杂了(主要是太多了不想看又看不懂emmm),下面是我通过keil使用51单片机外部中断0触发数码管显示后三位学号的示例代码:

#include
#define duan P0
#define uchar unsigned char    
sbit wei1 = P2^4;//定义第一位数码管
sbit wei2 = P2^5;//定义第二位数码管
sbit wei3 = P2^6;//定义第三位数码管
sbit wei4 = P2^7;//定义第四位数码管

uchar code sz[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};

void delay (unsigned int xms)
{
unsigned int i,j;
for(i=xms;i>0;i--)        //i=xms即延时xms
 for(j=112;j>0;j--);
}

void main()
{
EX0 = 1;//INT0中断允许
EA = 1;//全局中断打开
IT0 = 0;//触发方式为低电平触发
 
while(1)
 {
  duan = sz[8];
  wei1 = 0;
  wei2 = 0;
  wei3 = 0;
  wei4 = 1;
  delay(0);
  duan = sz[2];//0111 1100 "b"
  wei1 = 0;
  wei2 = 0;
  wei3 = 1;
  wei4 = 0;
  delay(0);
  duan = sz[6];
  wei1 = 0;
  wei2 = 1;
  wei3 = 0;
  wei4 = 0;
  delay(0);
  duan = sz[7];
  wei1 = 1;
  wei2 = 0;
  wei3 = 0;
  wei4 = 0;
  delay(0);  
 }
}

void low()interrupt 0
{
wei1 = 0;
delay(0);    
}
  

cpu运行结果

cpu硬件显示效果

      显示效果:显示4位学号7628,通过外部中断0使第一位数码管不亮,从而显示学号后三位。

总结:P3.2由ITO(TCON.0)选择其为低电平有效。当CPU检测到P3.2引脚上出现有效的中断信号时,中断标志 IEO(TCON.1)置1,向CPU申请中断。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分