ZigBee_CC2530_06H_中断的使用
扫描二维码
随时随地手机看文章
CC2530的中断系统是为了让CPU对内部或外部的突发事件及时地做出响应,并执行相应的终端程序。中断由中断源引起,中断源由相应的寄存器来控制。当需要使用中断时,需配置相应的中断寄存器来开启中断,当终端发生时将跳入中断服务函数中来执行此中断所需处理的事件。
1.终端源和中断向量
CC2530有18个中断源,每个中断源都可以产生中断请求,中断请求可以通过设置中断使能SFR寄存器的中断使能位IEN0、IEN1或IEN2使能或禁止中断。
中断号码
描述
中断名称
中断向量
中断屏蔽
中断标志
0
RF TX RFIO下溢 或
RX FIFO溢出
RFERR
03H
IEN0.RFERRIE
TCON.RFERRIF
1
ADC转换结束
ADC
0BH
IEN0.ADCIE
TCON.ADCIF
2
USART0 RX完成
URX0
13H
IEN0.URX0IE
TCON.URX0IF
3
USART1 RX 完成
URX1
1BH
IEN0.URX1IE
TCON.URX1IF
4
AES加密解密完成
ENC
23H
IEN0.ENCIE
S0CON.ENCIF
5
睡眠定时器完成
ST
2BH
IEN0.STIE
IRCON.STIF
6
端口2中断
P2INT
33H
IEN2.P2IE
IRCON2.P2IF
7
USART0 TX完成
UTX0
3BH
IEN2.UTX0IE
IRCON2.UTX0IF
8
DMA传输完成
DMA
43H
IEN1.DMAIE
IRCON.DMAIF
9
Timer1(16位)捕获/比较/溢出
T1
4BH
IEN1.T1IE
IRCON.T1IF
10
Timer2(MAC Timer)
T2
53H
IEN1.T2IE
IRCON.T2IF
11
Timer3(8位)捕获/比较/溢出
T3
5BH
IEN1.T3IE
IRCON.T3IF
12
Timer4(8位)捕获/比较/溢出
T4
63H
IEN1.T4IE
IRCON.T4IF
13
端口0中断
P0INT
6BH
IEN1.P0IE
IRCON.P0IF
14
USART1 TX 完成
UTX1
73H
IEN2.UTXIE
IRCON2.UTX1IF
15
端口1中断
P1INT
7BH
IEN2.P1IE
IRCON2.P1IF
16
RF通用中断
RF
83H
IEN2.RFIE
S1CON.RFIF
17
看门狗计时溢出
WDT
8BH
IEN2.WDTIE
IRCON.WDTIF
当相应的中断源使能并发生时,中断标志位将自动置1,然后程序跳往中断服务程序的入口地址执行中断服务程序。待中断服务程序处理完毕后,由硬件清除中断标志位。
中断服务程序的入口地址即中断向量,CC2530的18个中断源对应了18个中断向量,中断向量定义在头文件"ioCC2530.h"中,定义如下:
/* ------------------------------------------------------------------------------------------------ * Interrupt Vectors * ------------------------------------------------------------------------------------------------ */ //RF内核错误中断(RF TX RFIO下溢或RF FIFO溢出) #define RFERR_VECTOR VECT( 0, 0x03 ) /* RF TX FIFO Underflow and RX FIFO Overflow */ //ADC转换结束 #define ADC_VECTOR VECT( 1, 0x0B ) /* ADC End of Conversion */ //USART0 RX完成 #define URX0_VECTOR VECT( 2, 0x13 ) /* USART0 RX Complete */ //USART1 RX 完成 #define URX1_VECTOR VECT( 3, 0x1B ) /* USART1 RX Complete */ //AES加密解密完成 #define ENC_VECTOR VECT( 4, 0x23 ) /* AES Encryption/Decryption Complete */ //睡眠定时器完成 #define ST_VECTOR VECT( 5, 0x2B ) /* Sleep Timer Compare */ //端口2中断 #define P2INT_VECTOR VECT( 6, 0x33 ) /* Port 2 Inputs */ //USART0 TX完成 #define UTX0_VECTOR VECT( 7, 0x3B ) /* USART0 TX Complete */ //DMA传输完成 #define DMA_VECTOR VECT( 8, 0x43 ) /* DMA Transfer Complete */ //Timer1(16位)捕获/比较/溢出 #define T1_VECTOR VECT( 9, 0x4B ) /* Timer 1 (16-bit) Capture/Compare/Overflow */ //Timer2(MAC Timer) #define T2_VECTOR VECT( 10, 0x53 ) /* Timer 2 (MAC Timer) */ //Timer3(8位)捕获/比较/溢出 #define T3_VECTOR VECT( 11, 0x5B ) /* Timer 3 (8-bit) Capture/Compare/Overflow */ //Timer4(8位)捕获/比较/溢出 #define T4_VECTOR VECT( 12, 0x63 ) /* Timer 4 (8-bit) Capture/Compare/Overflow */ //端口0中断 #define P0INT_VECTOR VECT( 13, 0x6B ) /* Port 0 Inputs */ //USART1 TX 完成 #define UTX1_VECTOR VECT( 14, 0x73 ) /* USART1 TX Complete */ //端口1中断 #define P1INT_VECTOR VECT( 15, 0x7B ) /* Port 1 Inputs */ //RF通用中断 #define RF_VECTOR VECT( 16, 0x83 ) /* RF General Interrupts */ //看门狗计时溢出 #define WDT_VECTOR VECT( 17, 0x8B ) /* Watchdog Overflow in Timer Mode */
2.中断优先级
中断优先级将决定中断响应的先后顺序,在CC2530中分为6个中断优先组,即IPG0~IPG5,每一组中断优先组中有三个中断源:
组
中断
中断
中断
IPG0
RFERR
RF
DMA
IPG1
ADC
T1
P2INT
IPG2
URX0
T2
UTX0
IPG3
URX1
T3
UTX1
IPG4
ENC
T4
P1INT
IPG5
ST
P0INT
WDT
中断优先组的优先级设定由寄存器IP0和IP1来设置。CC2530的优先级有4级,即0~3级,其中0级的优先级最低,3级的优先级最高。IP1_X
IP0-X
优先级
0
0
0(优先级别最低)
0
1
1
1
0
2
1
1
3(优先级别最高)
其中IP1_X和IP0_X的X取值为优先组IPG0~IPG5中的任意一个。例如设置优先组IPG0为最高优先组:
//设置IPG0优先级组为最高优先级别 IP1_IPG0 = 1; IP0_IPG0 = 1;
如果同时收到相同优先级或同一优先级组中的中断请求时,将采用轮流检测顺序来判断中断优先级别的响应。
中断向量编号 中断名称 优先级排序 0 RFERR 高 16 RF 8 DMA 1 ADC 9 T1 2 URX0 10 T2 3 URX1 11 T3 4 ENC 12 T4 5 ST 13 P0INT 6 P2INT 7 UTX0 14 UTX1 15 P1INT 17 WDT 低 例如在中断优先级组IPG0中的终端RFERR、RF和DMA的中断优先级相同,如果同时使用这三个中断,就需要使用轮流探测顺序来判断哪一个优先级最高。由轮流探测顺序表查得RFERR中断优先级最高,RF中断次之,DMA中断与其他两个中断相比中断优先级最低。
3.中断处理过程
中断发生时,CC2530硬件自动完成以下处理:
中断申请:中断源向CPU发出中断请求信号(中断申请一般需要在程序初始化中配置相应的终端寄存器开启中断);中断响应:CPU检测中断申请,把中断的地址保存到堆栈,转入中断向量入口地址;中断处理:按照中断向量中设定好的地址,转入相应的中断服务程序;中断返回:中断服务程序执行完毕后,CPU执行中断返回指令,把堆栈中保存的数据从堆栈中弹出,返回原来程序。
4.中断编程
中断编程的一般过程如下:
中断设置:根据外设的不同,具体的设置是不同的,一般至少包含启用中断。中断函数编写:这是中断编程的主要工作,需要注意的是,中断函数应尽可能地减少耗时或不进行耗时操作。
CC2530所使用的编译器为IAR,在IAR编译器中用关键词_interrupt来定义一个中断函数。使用#progma vector来提供中断函数的入口地址,并且中断函数没有返回值,没有函数参数。中断函数的一般格式如下:
#progma vector = 中断向量 _interrupt void 函数名(void) { //中断函数代码 }
在中断函数的编写中,当程序进入中断服务程序之后,需要执行以下四个步骤: 将对应的中断关掉(不是必须的,需要根据具体情况来处理);其次如果需要判断具体的中断源,则根据中断标志位进行判断(所有I/O中断共用1个中断向量,需要通过中断标志区分是哪个引脚引起的中断);清中断标志(不是必须的,CC2530中中断发生后由硬件自动清中断标志位);处理中断事件,此过程要尽可能地减少耗时;最后,如果在第一步中关闭了相应的中断源,则需要在退出中断服务程序之前打开相应的中断。
一般情况下,中断函数的编写是根据实际项目中的需求来定的。以CC2530端口0的P0_4、P0_5外部中断为例,中断程序编写如下所示:
//中断函数入口地址 #pragma vector = POINT_VECTOR //定义一个终端函数 _interrupt void P0_ISR(void) { //关端口P0_4、P0_5中断 P0IEN &= ~0x30; //判断中断发生 if(P0IFG > 0) { //清中断标志 P0IFG = 0; /***中断事件的处理***/ } }