MPLAB C18不自动把中断服务程序放在中断向量处。通常将GOTO 指令放在中断向量处,从而把控制权转交给相应的中断服务程序。
PIC18系列的低优先级中断入口地址在0x0018地址,下面的代码是在入口地址处放置一个向量函数,这个向量函数里就是一个内嵌汇编的GOTO指令,GOTO到低优先级的中断服务函数InterruptHandlerLow。
//----------------------------低优先级中断入口-----------------------------------
1 #pragma code InterruptVectorLow = 0x18 //用#pragma伪指令定义一个名字叫InterruptVectorLow的段,并把这个段放到0x18地址起始的代码空间
2 void InterruptVectorLow (void) //低优先级中断向量函数
3 {
4 _asm
5 goto InterruptHandlerLow //内嵌汇编指令
6 _endasm
7 }
8 #pragma code //这里不是多余的,它是告诉连接器回到默认的代码段,如果不加的话,连接器就会傻傻地把后面的代码紧跟着上面的代码一直放下去。而LKR文件里定义了向量区最多到0x29地址,所以如果没加此行通常会报错
9
10 #pragma interruptlow InterruptHandlerLow //这里使用interruptlow这个关键词来声明InterruptHandlerLow这个函数是低优先级中断服务函数,用了关键词后,这个函数将会由编译器自动产生基本的现场保护,并且这个函数的返回将是使用RETFIE返回的。
11
12
13 void InterruptHandlerLow (void)
14 {
15 /* 低优先级服务函数的代码写在这里*/
16 }
PIC18系列的高优先级中断入口地址在0x0008地址,下面的代码是在这个入口地址处放置一个向量函数,这个向量函数里就是一个内嵌汇编的GOTO指令,GOTO到高优先级的中断服务函数InterruptHandlerHigh 。
//----------------------------高优先级中断入口-----------------------------------
1 #pragma code InterruptVectorHigh = 0x08 //用#pragma伪指令定义一个名字叫InterruptVectorHigh的段,并把这个段放到0x08地址起始的代码空间
2 void InterruptVectorHigh (void) //高优先级中断向量函数
3 {
4 _asm
5 goto InterruptHandlerHigh //内嵌汇编指令
6 _endasm
7 }
8 #pragma code //回到默认代码段,原因同上
9 #pragma interrupt InterruptHandlerHigh
10
11 void InterruptHandlerHigh (void)
12 {
13 /* 高优先级服务函数的代码写在这里*/
14
15 if (INTCONbits.TMR0IF)
16 {//check for TMR0 overflow
17 INTCONbits.TMR0IF = 0; //clear interrupt flag
18 ;
19 ;
20 }
21 }
对于MPLAB C18,上面的高低优先级的中断向量函数和中断服务函数,各只能出现一次,不能有多个中断服务函数,如果多个中断都是高优先级的,在高优先级中断服务函数里通过判断各自的中断标志位来做对应处理。
CONbits.IPEN = 1; //使能中断优先级
INTCONbits.GIEH = 1; //允许/禁止 所有高优先级中断
INTCONbits.GIEL = 1; //允许/禁止 所有低优先级中断
//RCONbits.IPEN = 0; //禁止中断优先级
//INTCONbits.GIE = 1; //允许/禁止 所有中断源
//INTCONbits.PEIE = 1; //允许/禁止 所有外设中断源
当IPEN=1时,中断源使用高优先级中断时GIEH = 1;GIEL 可以=0;
中断源使用低优先级中断时GIEH = 1;GIEL =1;
当IPEN=0时,所有中断均跳转到08H(使用高优先级中断向量入口)
GIEH = 1;GIEL =1;