(转)ARM9(S3C2440)的中断系统——…

来源:互联网 发布:java项目开发技术难点 编辑:程序博客网 时间:2024/06/08 10:19

转载地址:http://www.360doc.com/content/11/1123/11/7725999_166692855.shtml

中断控制程序编写步骤

主程序

1.先清除中断源挂起寄存器(SRCPND)和中断挂起寄存器(INTPND),可用rSRCPND= rSRCPNDrINTPND=rINTPND来完成;

 SRCPND 寄存器包括 32位,每位与一个中断源相关。如果相应的中断源产生中断请求且等待中断服务,则每个位置1。因此这个寄存器指出那个中断源在等待请求服务。注意SRCPND 的每个位都由中断源自动置位,不管 INTMASK 寄存器的屏蔽位。此外,SRCPND寄存器不会受到中断控制器的优先级逻辑的影响。 

对于一个特定中断源的中断服务程序中,SRCPND寄存器的相应位必须被清除目的是下次能正确得到同一个中断源的中断请求。如果你从中断服务程序返回却没有清除该位,中断控制器将操作好像又有同一个中断源的中断请求到来。换言之,如果SRCPND的一个特殊位置1,其总是认为一个有效的中断请求等待服务。

清除相应位的时间依赖于用户的需求。如果你想收到另一个来此同一个中断源的有效请求,你应该清除相应的位,然后使能中断。 

你可以通过写数据到这个寄存器来清除 SRCPND寄存器的某个位。你可以通过对相应位置1 来清除相应位。如果你对相应位写 0,则该位的数值保持不变。 

 2.设中断模式,这里使用通用中断,rINTMOD=0x00000000因上电或复位时rINTMOD是清0的,这步也可以不做。 

中断模式寄存器 INTMOD 

该寄存器包括 32位,每位与一个中断源相关。如果某位置 1,相应的中断将在FIQ模式下处理。否则在IRQ模式下操作。请注意仅有一个中断源能够在FIR模式下服务,也就是说,INTMOD仅有一个位可以被置1 

 3.I/O 口初始化,有些中断源要通过I/O口向 CPU申请中断,如外部中断 0EXTINT0通过F口的GPF0 、外部中断11EXTINT11)通过G口的GPG3 CPU 申请中断,此时两个口的控制寄存器 GPFCON GPGCON的要设置成:GPFCON[10]=10GPGCON[76]=10 

4.设中断服务函数地址,S3C2410 2410addr.h中定义了 40个宏,设置了系统支持的中断服务函数的指针,设中断服务函数地址就是把我们编写的中断服务函数的地址(就是中断服务函数的名字)赋予相应的函数指针。每个中断源的中断服务函数指针名是固定的:pISR+中断源。 

5.设中断触发方式,触发方式有5种,有上升沿、下降沿、双沿、低电平、高电平触发方式,外部中断触发方式在外部中断控制寄存器(EXTINTn)中设定。如EINT0 触发方式在 EXTINT0[20] 中设定,[20]=000 低电平、 001高电平、 01X下降沿、 10X上升沿、 11X双沿触发, 

6.取消总中断屏蔽和子中断屏蔽,等待中断。例如通过rEINTMASKrEINTMASK&=~(1<<11)

rINTMASK&=~(BIT_EINT0|BIT_EINT8_23);来实现。


中断服务程序

1.在中断服务程序中,先屏蔽中断,防止其他中断产生干扰我们中断服务程序的执行; 

2.执行中断服务程序;

3.清中断源挂起寄存器(SRCPND)和中断挂起寄存器(INTPND);

4.取消总中断屏蔽和子中断屏蔽,等待新中断产生; 

5.中断返回 

下面是具体的程序应用:

#include"2440addr.h"   //头文件,包含宏定义及清除挂起寄存器的ClearPending()函数 

static void __irqKey_ISR();//中断函数声明 

void delay(intx)//延时函数 

{ 

while(x) 

 {

   int k,j;

  for(k=0xff;k>0;k--)

   for(j=0xff;j>0;j--);

   x--;

 }

}

voidledMain(void)

{

rGPBCON = 0x1dd7fc; //GPB5,GPB6,GPB8,GPB10设置为输出,连接了4LED

rGPBDAT|=0x560;//4LED全灭

rGPFCON&=~((3<<0)|(3<<4)|(3<<6)|(3<<8));

   rGPFCON |=((2<<0)|(2<<4)|(2<<6)|(2<<8));//GPF0GPF2GPF3GPF4工作在第二功能状态,即中断

 //rEXTINT0=0x0;

rEINTPEND=(1<<4);//清外部中断挂起寄存器,清的是外部中断4

   ClearPending(BIT_EINT0|BIT_EINT2|BIT_EINT3|BIT_EINT4_7);//清外部中断0234

   pISR_EINT0= pISR_EINT2 =pISR_EINT3 =pISR_EINT4_7=(int)Key_ISR;//设中断服务函数地址

   EnableIrq(BIT_EINT0|BIT_EINT2|BIT_EINT3|BIT_EINT4_7);//使能中断,即使INTMSK相应位为0

   rEINTMASK=~(1<<4);//使能外部中断4

   while(1);//等待中断发生

}

static void __irqKey_ISR()//中断服务函数,__irq用来声明通用中断函数

{

charkey;//用来标识是哪一个按键按下

   unsigned int r;

   rINTMSK=0xffffffff;//这是屏蔽所有中断

   if(rINTPND==BIT_EINT0){         //因为4个中断用的是同一个中断服务函数,所以判断是哪一个中断发生

    ClearPending(BIT_EINT0);        //并清除挂起寄存器,获得键值

   key=1;

   }

    elseif(rINTPND==BIT_EINT2) {

   ClearPending(BIT_EINT2);

   key=2; 

    }

    else if(rINTPND==BIT_EINT3) {

     ClearPending(BIT_EINT3);

     key=3;

    }

    else if(rINTPND==BIT_EINT4_7){

     rEINTPEND=(1<<4);

     ClearPending(BIT_EINT4_7); 

     key=4; 

    } 

    switch(key){     //根据键值控制4LED亮灭变化 

   case1: 

    rGPBDAT^=(1<<5);

    break; 

   case 2:

    rGPBDAT^=(1<<6); 

    break; 

   case3: 

    rGPBDAT^=(1<<8);

    break;

   case 4:

    rGPBDAT^=(1<<10);

    break;

     }

 EnableIrq(BIT_EINT0|BIT_EINT2|BIT_EINT3|BIT_EINT4_7);//再打开中断

}

下面在说一下用到的ClearPending()

该函数在头文件2440addr.h中:

__inline voidClearPending(int bit)//输入参数是相应位为1的值

{

  registeri;//定义一个寄存器变量

 rSRCPND=bit;//向相应位置写1清除源挂起寄存器

  rINTPND =bit;//向相应位置写1清除源挂起寄存器

  i =rINTPND;//没有该语句也能正常运行,可能是保证寄存器能清除的

}

 

0 0
原创粉丝点击