S3C2440的中断的那些事儿(二) C语言部分讲解

 1 void init_irq( )
 2 {
 3     // S2,S3对应的2根引脚设为中断引脚 EINT0,ENT2
 4     GPFCON &= ~(GPF0_msk | GPF2_msk);
 5     GPFCON |= GPF0_eint | GPF2_eint;
 6 
 7     // S4对应的引脚设为中断引脚EINT11
 8     GPGCON &= ~GPG3_msk;
 9     GPGCON |= GPG3_eint;
10     
11     // 对于EINT11,需要在EINTMASK寄存器中使能它
12     EINTMASK &= ~(1<<11);
13         
14     /*
15      * 设定优先级:
16      * ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2
17      * 仲裁器1、6无需设置
18      * 最终:
19      * EINT0 > EINT2 > EINT11即K2 > K3 > K4
20      */
21     PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;
22 
23     // EINT0、EINT2、EINT8_23使能
24     INTMSK   &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));
25 }

上面就是韦东山的中断源代码:

 第四行和第五行代码分析:把按键的引脚先变成中断引脚

第十二行:

 EINTMASK &= ~(1<<11);  因为前3个中断是不能被masked的从第四个中断开始 当置0的时候是使能中断 这里是使能第十一个中断。 默认初始值是1
这个是对于外部中断使能

第二十一行:

PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;

此实验用到了仲裁器0
ARB_SEL0 = 00b, ARB_MODE0 = 0: REQ1 > REQ3,即EINT0 > EINT2

第24行:
INTMSK   &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));
这个寄存器是对所有的中断 设置为0的时候是开启所有中断

下图中的函数是中断服务函数
 1 void EINT_Handle()
 2 {
 3     unsigned long oft = INTOFFSET;
 4     unsigned long val;
 5     
 6     switch( oft )
 7     {
 8         // S2被按下
 9         case 0: 
10         {   
11             GPFDAT |= (0x7<<4);   // 所有LED熄灭
12             GPFDAT &= ~(1<<4);      // LED1点亮
13             break;
14         }
15         
16         // S3被按下
17         case 2:
18         {   
19             GPFDAT |= (0x7<<4);   // 所有LED熄灭
20             GPFDAT &= ~(1<<5);      // LED2点亮
21             break;
22         }
23 
24         // K4被按下
25         case 5:
26         {   
27             GPFDAT |= (0x7<<4);   // 所有LED熄灭
28             GPFDAT &= ~(1<<6);      // LED4点亮                
29             break;
30         }
31 
32         default:
33             break;
34     }
35 
36     //清中断
37     if( oft == 5 ) 
38         EINTPEND = (1<<11);   // EINT8_23合用IRQ5
39     SRCPND = 1<<oft;
40     INTPND = 1<<oft;
41 }
INTOFFSET 里面的值显示了哪一个中断正在被执行
第三十八行 EINTPEND 如果清除(置1)这里面的位 则清除了中断
第三十九行和第四十行都是一样的清除中断


总结

下面总结一下如何写一个中断的程序:
1. 给中断设置栈 然后进入管理模式
2. 初始化中断 (EINTMSK和INTMSK 两个寄存器都要设置)还要设置优先级
3. 开总中断
4. 进入中断服务函数之后 先保存数据进栈 和计算返回地址
5. 然后执行服务函数里面的程序
6. 之后清除PEND寄存器里面的标志位
7. 退出中断之后POP栈内保存的值
8. 告知PC 现在寄存器的状态(ldmia   sp!,    { r0-r12,pc }^)

猜你喜欢

转载自www.cnblogs.com/shwzh1990/p/10934932.html