一、中断编写总框图
二、分步介绍
1、初始化引脚
#define GPGCON (*(volatile unsigned long *)0x56000060)
对照上图将所有引脚设置为【10】变成外部中断功能(以GPG0 GPG3为例)
GPGCON &= (~(3<<0)) & (~(3<<6));//清除设置位
GPGCON |= (2<<0) | (2<<6);//设置为外部中断功能
2、初始化中断
#define EINTMASK (*(volatile unsigned long *)0x560000A4)
#define INTMSK (*(volatile unsigned long *)0x4A000008)
EINTMASK
EINTMASK &= (~(1<<8))&(~(1<<11));
INTMSK &= (~(1<<EINT8_23));
打开总中断:
/*打开总中断*/
__asm__ volatile(
"mrs r0, cpsr\n"
"bic r0, r0,#0x80\n"
/*只写控制位*/
"msr cpsr_c, r0\n"
:
:
);
3、进入中断
①保存环境
sub lr, lr,#4 /*保证返回时执行的是下一条命令*/
stmfd sp!, {r0-r12, lr}
②中断处理函数
bl handle_int
③恢复环境
ldmfd sp!, {r0-r12, pc}^ /*恢复环境*/
4、中断处理函数
//宏定义
#define EINTPEND (*(volatile unsigned long *)0x560000A8)
#define SRCPND (*(volatile unsigned long *)0x4A000000)
#define INTPND (*(volatile unsigned long *)0x4A000010)
//处理函数
//判断中断源
unsigned long value = INTOFFSET;
unsigned long value2 = 0;
//根据中断源执行不同的中断处理
switch(value)
{
case 5: //EXINT8_23
value2 = EINTPEND & ((1<<8)|(1<<11));
switch(value2)
{
case (1<<EINT8): //K1
led2_on();
break;
case (1<<EINT11): //K2
led2_off();
break;
default:
break;
}
//清除EINT8_23中断标志
EINTPEND = value2;
break;
default:
break;
}
//清除中断标志
SRCPND = 1<<value;
INTPND = 1<<value;
5、注意问题
由于使用中断功能,当程序进入中断时,此时系统处于irq模式下,正常情况系统处于svc模式,而两者的r13是不一样的,所以初始化堆栈时需要分别进行初始化
init_stack:
msr cpsr_c, 0xd2
ldr sp, =0x33000000 @irq模式下初始化的是r13_irq
msr cpsr_c, 0xd3
ldr sp, =0x34000000 @svc模式下初始化的是r13_svc
mov pc, lr
|