项目3外部中断 3.1项目任务和指标 本项目将完成通过按键中断控制LED灯任务。 通过本项目的实施,读者应掌握中断的概述、中断屏蔽寄存器和中断的处理方法及应用。 3.2项目的预备知识 3.2.1中断概述 CC2530有18个中断源,每个中断源都有它自己的、位于一系列特殊功能寄存器(Special Function Register,SFR)中的中断请求标志。每个中断可以分别使能或禁用。 中断是指计算机在执行期间,系统内发生任何非寻常的或非预期的急需处理的事件,使得CPU暂时中断当前正在执行的程序而转去执行相应的事件处理程序,待处理完毕后又返回原来被中断处继续执行的过程。 CC2530中断描述如表3.1所示。 表3.1CC2530中断概览 中断号码 描述 中断名称 中断向量 中断屏蔽,CPU 中断标志,CPU 0 RF发送FIFO队列空或RF接收FIFO队列溢出 RFERR 03h IEN0.RFERRIE TCON.RFERRIE 续表 中断号码 描述 中断名称 中断向量 中断屏蔽,CPU 中断标志,CPU 1 ADC转换结束 ADC 0Bh IEN0.ADCIE TCON.ADCIF 2 USART0 RX完成 URX0 13h IEN0.URXOIE 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输入/USB P2INT 33h IEN2.P2IE IRCON2.P2IF 7 USART0 TX完成 UTX0 3Bh IEN2.UTX0IE IRCON2.UTX0IF 8 DMA传送完成 DMA 43h IEN1.DMAIE IRCON.DMAIF 9 定时器1(16位)捕获/比较/溢出 T1 4Bh IEN1.T1IE IRCON.T1IF 10 定时器2 T2 53h IEN1.T2IE IRCON.T2IF 11 定时器3(8位)捕获/比较/溢出 T3 5Bh IEN1.T3IE IRCON.T3IF 12 定时器4(8位)捕获/比较/溢出 T4 63h IEN1.T4IE IRCON.T4IF 13 端口0输入 P0INT 6Bh IEN1.P0IE IRCON.P0IF 14 USART1 TX完成 UTX1 73h IEN2.UTX1IE 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 3.2.2中断屏蔽 1. 中断屏蔽寄存器 中断屏蔽是指在中断请求产生之后,系统用软件方式有选择地封锁部分中断而允许其余部分的中断仍能得到响应。 中断使能是让中断可以被触发,可以进入中断服务程序; 如果是中断禁止状态的话,即使中断信号来了也不会触发中断,也就不会进入中断服务程序。中断使能寄存器有IEN0、IEN1和IEN2,通常用1表示中断禁止,用0表示中断使能。 每个中断请求可以通过设置中断使能寄存器IEN0、IEN1或者IEN2的中断使能位使能或禁止。某些外部设备会因为若干中断时间产生中断请求。这些中断请求可以作用于P0端口、P1端口、P2端口、DMA、计数器或者RF上。对于每个内部中断源对应的特殊功能寄存器,这些外部设备都有中断屏蔽位。寄存器IEN0、IEN1和IEN2如表3.2~表3.4所示。 表3.2IEN0——中断使能寄存器0 位 名称 复位 R/W 描述 7 EA 0 R/W 禁用所有中断 0: 无中断被禁用 1: 通过设置对应的使能位将每个中断源分别使能和禁止 6 — 0 RO 不使用,读出来是0 5 STIE 0 R/W 睡眠定时器中断使能 0: 中断禁止 1: 中断使能 4 ENCIE 0 R/W AES加密/解密中断使能 0: 中断使能 1: 中断禁止 3 URX1IE 0 R/W USART 1 RX中断使能 0: 中断使能 1: 中断禁止 2 URX0IE 0 R/W USART 0 RX中断使能 0: 中断使能 1: 中断禁止 1 ADCIE 0 R/W ADC中断使能 0: 中断使能 1: 中断禁止 0 RFERRIE 0 R/W RF TX/RX FIFO中断使能 0: 中断使能 1: 中断禁止 表3.3IEN1——中断使能寄存器1 位 名称 复位 R/W 描述 7∶6 — 00 RO 没有使用,读出来是0 5 P0IE 0 R/W 端口0中断使能 0: 中断禁止 1: 中断使能 4 T4IE 0 R/W 定时器4中断使能 0: 中断禁止 1: 中断使能 3 T3IE 0 R/W 定时器3中断使能 0: 中断禁止 1: 中断使能 2 T2IE 0 R/W 定时器2中断使能 0: 中断禁止 1: 中断使能 续表 位 名称 复位 R/W 描述 1 T1IE 0 R/W 定时器1中断使能 0: 中断禁止 1: 中断使能 0 DMAIE 0 R/W DMA传输中断使能 0: 中断禁止 1: 中断使能 表3.4IEN2——中断使能寄存器2 位 名称 复位 R/W 描述 7∶6 — 00 RO没有使用,读出来是0 5 WDTIE 0 R/W 看门狗定时器中断使能 0: 中断禁止 1: 中断使能 4 P1IE 0 R/W 端口1中断使能 0: 中断禁止 1: 中断使能 3 UTX1IE 0 R/W USART1 TX中断使能 0: 中断禁止 1: 中断使能 2 UTX0IE 0 R/W USART0 TX中断使能 0: 中断禁止 1: 中断使能 1 P2IE 0 R/W 端口2中断使能 0: 中断禁止 1: 中断使能 0 RFIE 0 R/W RF一般中断使能 0: 中断禁止 1: 中断使能 在上面3个寄存器中,IEN0.EA对总中断进行中断使能控制,其余部分对所有中断源进行中断使能控制(包括P1、P2和P3三个端口中断的使能及外设中断使能)。 寄存器P0IEN、P11EN、P2IEN为P0、P1和P2端口每个引脚设置中断使能,如表3.5~表3.7所示。 表3.5P0IEN——端口0位中断屏蔽 位 名称 复位 R/W 描述 7∶0 P0_[7∶0]IEN 0x00 R/W 端口P0.7~P0.0中断使能 0: 中断禁用 1: 中断使能 表3.6P1IEN——端口1位中断屏蔽 位 名称 复位 R/W 描述 7∶0 P1_[7∶0]IEN 0x00 R/W 端口P1.7~P1.0中断使能 0: 中断禁用 1: 中断使能 表3.7P2IEN——端口2位中断屏蔽 位 名称 复位 R/W 描述 7∶6 — 00 R/W未使用 5 DPIEN 0 R/W USB D+中断使能 4∶0 P2_[4∶0]IEN 0 0000 R/W 端口P2.4~P2.0中断使能 0: 中断禁用 1: 中断使能 2. 中断使能的步骤 按键中断控制的步骤如下: (1) PxIEN: 在引脚中断功能配置时,常需要设置P0IEN,主要是开启/关闭引脚的中断功能。为1时开启,为0时关闭中断。例如,开启S1按钮中断为P0IEN|=BIT4。 (2) PICTL: 可以控制Px口中断触发信号,上升沿触发、下降沿触发。由于按键在未按下时处于高电平,按下后为低电平,松开后又为高电平,所以会产生下降沿触发信号,配置为下降沿触发即可,PICTL|=BITO。 (3) IEN1: 除了配置引脚,还需要开启端口引脚中断使能,如开启P0端口中断使能,IEN1|=BIT5。 (4) PxIFG: 在开启中断前需要先清除中断标志,以免误入中断造成系统混乱,如P0IFG&=~BIT4。 图3.1中断使能的步骤 (5) 系统中断使能: 在任何中断操作时,都需要开启系统中断,如EA=1。 中断使能的步骤如图3.1所示。 (1) 使IEN0中IEN0.EA位为1,开中断。 (2) 设置寄存器IEN0、IEN1和IEN2中相应中断使能位为1。 (3) 如果需要,则设置P0、P1、P2各引脚对应的各中断使能位为1。 (4) 最后在寄存器PICTL中设置中断是上升沿还是下降沿触发。 3.2.3中断处理 当中断发生时,无论该中断使能或禁止,CPU都会在中断标志寄存器中设置终端标志位,在程序中可以通过中断标志来判断是否发生了相应的中断。如果当设置中断标志时中断使能,那么在下一个指令周期,由硬件强行产生一个长调用指令LCALL到对应的向量地址,运行中断服务程序,中断的响应需要不同的时间,取决于该中断发生时CPU的状态。当CPU正在运行的中断服务程序,其优先级大于或等于新的中断时,新的中断暂不运行,直至新的中断的优先级高于正在运行的中断服务程序。 TCON、SCON、S1CON、IRCON、IRCON2是CC2530的5个中断标志寄存器,如表3.8~表3.12所示。 表3.8TCON——中断标志寄存器1 位 名称 复位 R/W 描述 7 URX1IF 0 R/WH0 USART 1 RX中断标志。当USART 1 RX中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 6 — 0 R/W没有使用 5 ADCIF 0 R/WH0 ADC中断标志。当ADC中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 4 — 0 R/W 没有使用 3 URX0IF 1 R/WH0 USART 0 RX中断标志。当USART0中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 2 IT1 1 R/W保留。必须一直设为1。设置为0将使能低级别中断探测,几乎总是如此(启动中断请求时执行一次) 1 RFERRIF 0 R/WH0 RF TX、RX FIFO中断标志。当RFERR中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 0 IT0 1 R/W保留。必须一直设为1。设置为0将使能低级别中断探测,几乎总是如此(启动中断请求时执行一次) 表3.9S0CON——中断标志寄存器2 名称 复位 R/W 描述 — 0000 00 R/W没有使用 ENCIF_1 0 R/W AES中断。ENC有两个中断标志。当AES协处理器请求中断时两个标志都要设置 0: 无中断未决 1: 中断未决 ENCIF_0 0 R/W AES中断。ENC有两个中断标志。当AES协处理器请求中断时两个标志都要设置 0: 无中断未决 1: 中断未决 表3.10S1CON——中断标志寄存器3 位 名称 复位 R/W 描述 7∶2 — 0000 00 R/W没有使用 1 RFIF_1 0 R/W RF一般中断。RF有两个中断标志,RFIF_1和RFIF_0,设置其中一个标志就会请求中断服务。当无线设备请求中断时两个标志都要设置 0: 无中断未决 1: 中断未决 0 RFIF_0 0 R/W RF一般中断。RF有两个中断标志,RFIF_1和RFIF_0,设置其中一个标志就会请求中断服务。当无线电请求中断时两个标志都要设置 0: 无中断未决 1: 中断未决 表3.11IRCON——中断标志寄存器4 位 名称 复位 R/W 描述 7 STIF 0 R/W 睡眠定时器中断标志 0: 无中断未决 1: 中断未决 6 — 0 R/W必须写为0。写入1总是使能中断源 5 P0IF 0 R/W 端口0中断标志 0: 无中断未决 1: 中断未决 4 T4IF 0 R/WH0 定时器4中断标志。当定时器4中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 续表 位 名称 复位 R/W 描述 3 T3IF 0 R/WH0 定时器3中断标志。当定时器3中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 2 T2IF 0 R/WH0 定时器2中断标志。当定时器2中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 1 T1IF 0 R/WH0 定时器1中断标志。当定时器1中断发生时设为1,当CPU指向中断向量服务例程时清除 0: 无中断未决 1: 中断未决 0 DMAIF 0 R/W DMA完成中断未决 0: 无中断未决 1: 中断未决 表3.12IRCON2——中断标志寄存器5 位 名称 复位 R/W 描述 7∶5 — 000 R/W 没有使用 4 WDTIF 0 R/W 看门狗定时器中断标志 0: 无中断未决 1: 中断未决 3 P1IF 0 R/W 端口1中断标志 0: 无中断未决 1: 中断未决 2 UTX1IF 0 R/W USART 1 TX中断标志 0: 无中断未决 1: 中断未决 1 UTX0IF 0 R/W USART 0 TX中断标志 0: 无中断未决 1: 中断未决 0 P2IF 0 R/W 端口2中断标志 0: 无中断未决 1: 中断未决 P0IFG、P1IFG、P2IFG是端口0、端口1、端口2每一位的中断标志寄存器,如表3.13~表3.15所示。 表3.13P0IFG——端口0位中断标志位 位 名称 复位 R/W 描述 7∶0 P0IF[7∶0] 0x00 R/W0 端口0,位7~位0输入中断状态标志。当输入端口中断请求未决信号时,其相应的标志位将置1 表3.14P1IFG——端口1位中断标志位 位 名称 复位 R/W 描述 7∶0 P0IF[7∶0] 0x00 R/W0 端口1,位7~位0输入中断状态标志。当输入端口中断请求未决信号时,其相应的标志位将置1 表3.15P2IFG——端口2位中断标志位 位 名称 复位 R/W 描述 7∶6 — 0 R0 不用 5 DPIF 0 R/W USB D+中断状态标志。当D+线有一个中断请求未决时设置该标志,用于检测USB挂起状态下的USB恢复事件。当USB控制器没有挂起时不设置该标志 4∶0 P2IF[4∶0] 0 R/W 端口2,位4~位0输入中断状态标志。当输入端口引脚有中断请求未决信号时,其相应的标志位将置1 3.3项目实施 1. 项目环境 (1) 硬件: ZigBee(CC2530)模块、ZigBee下载调试板、USB仿真器和PC。 图3.2按键接口原理图 (2) 软件: IAR Embedded Workbench for MCS51。 2. 项目原理 1) 硬件接口原理 按键接口如图3.2所示。 CC2530开发板有三个按键: 一个复位按键,其余两个按键可以通过编程进行控制。当按键按下时,相应的管脚输出低电平。在此采用下降沿触发中断的方式检测是否有按键按下。 2) CC2530相关寄存器 P1SEL寄存器的详细信息如表3.16所示。 表3.16P1SEL寄存器 位 名称 复位 R/W 描述 7∶0 SELP1_[7∶0] 0x00 R/W P1_7~P1_0功能选择 0: 通用I/O 1: 外设功能 P1DIR寄存器的详细信息如表3.17所示。 表3.17P1DIR寄存器 位 名称 复位 R/W 描述 7∶0 DIRP1_[7∶0] 0x00 R/W P1_7~P1_0的I/O方向 0: 输入 1: 输出 P1INP寄存器的详细信息如表3.18所示。 表3.18P1INP寄存器 位 名称 R/W 描述 7∶2 MDP1_[7∶2] R/W P1_7~P1_2的I/O输出模式 0: 上拉/下拉 1: 三态 1∶0 MDP1_[1∶0] RO 未使用 P2INP寄存器的详细信息如表3.19所示。 表3.19P2INP寄存器 位 名称 R/W 描述 7 PDUP2 R/W 端口2上拉/下拉选择,对所有端口2引脚设置为上拉/下拉输入 0: 上拉 1: 下拉 6 PDUP1 R/W 端口1的设置 0: 上拉 1: 下拉 5 PDUP0 R/W 端口0的设置 0: 上拉 1: 下拉 4∶0 MDP2_[4∶0] R/W P2_4~P2_0的输入模式 0: 上拉/下拉 1: 三态 PICTL寄存器的详细信息如表3.20所示。 表3.20PICTL寄存器 位 名称 复位 R/W 描述 7 PADSC 00 RO 控制I/O引脚在输出模式下的驱动能力,选择输出驱动能力补偿引脚DVDD的低I/O电压(为了确保在较低电压下的驱动能力和较高电压下的驱动能力相同) 0: 最小驱动能力增强,DVDD1/2等于或大于2.6V 1: 最大驱动能力增强,DVDD1/2小于2.6V 6∶4 — 000 RO 保留 3 P2ICON 0 R/W 端口2的P2.4~P2.0输入模式下的中断配置,该位为所有端口2的输入P2.4~P2.0选择中断请求条件 0: 输入的上升沿引起中断 1: 输入的下降沿引起中断 2 P1ICONH 0 R/W 端口1的P1.7~P1.4输入模式下的中断配置,该位为所有端口1的输入P1.7~P1.4选择中断请求条件 0: 输入的上升沿引起中断 1: 输入的下降沿引起中断 1 P1ICONL 0 R/W 端口1的P1.4~P1.0输入模式下的中断配置,该位为所有端口1的输入P1.4~P1.0选择中断请求条件 0: 输入的上升沿引起中断 1: 输入的下降沿引起中断 0 P0ICON 0 R/W 端口0的P0.7~P0.0输入模式下的中断配置,该位为所有端口0的输入P0.7~P0.0选择中断请求条件 0: 输入的上升沿引起中断 1: 输入的下降沿引起中断 3. 软件设计 /* 包含头文件 */ /****************************************************************/ #include "ioCC2530.h" // CC2530的头文件,包含对CC2530的寄存器、中断向量等的定义 /****************************************************************/ /**************************************************************** * 函数名称: delay * 功 能: 软件延时 * 入口参数: t 延时参数,值越大延时时间越长 * 出口参数: 无 * 返 回 值: 无 ****************************************************************/ void delay(unsigned short t) { unsigned char i,j; while(--t) { j = 200; while(--j) while(--i); } } /***************************************************************** * 函数名称: EINT_ISR * 功 能: 外部中断服务函数 * 入口参数: 无 * 出口参数: 无 * 返 回 值: 无 *****************************************************************/ #pragma vector=P1INT_VECTOR __interrupt void EINT_ISR(void) { EA = 0; // 关闭全局中断 /* 若是P2.0产生的中断 */ if(P1IFG & 0x40) { /* 切换LED1(绿色)的亮灭状态 */ if(P1_0 == 0) // 若之前是控制LED1(绿色)点亮,则现在熄灭LED1 { P1_0 = 1; } else // 若之前是控制LED1(绿色)熄灭,则现在点亮LED1 { P1_0 = 0; } /* 切换LED2(红色)的亮灭状态 */ if(P1_1 == 0) // 若之前是控制LED2(红色)点亮,则现在熄灭LED2 { P1_1 = 1; } else // 若之前是控制LED2(红色)熄灭,则现在点亮LED2 { P1_1 = 0; } /* 切换LED3(黄色)的亮灭状态 */ /* 等待用户释放按键,并消抖 */ while(P1_6 & 0x40); delay(10); while(P1_6 & 0x40); /* 清除中断标志 */ P1IFG &= ~0x40; // 清除P1.6中断标志 IRCON2 &= ~0x08; // 清除P1端口中断标志 } if(P1IFG & 0x80) { /* 切换LED1(绿色)的亮灭状态 */ if(P1_0 == 0) // 若之前是控制LED1(绿色)点亮,则现在熄灭LED1 { P1_0 = 1; } else // 若之前是控制LED1(绿色)熄灭,则现在点亮LED1 { P1_0 = 0; } /* 切换LED2(红色)的亮灭状态 */ if(P1_1 == 0) // 若之前是控制LED2(红色)点亮,则现在熄灭LED2 { P1_1 = 1; } else // 若之前是控制LED2(红色)熄灭,则现在点亮LED2 { P1_1 = 0; } /* 切换LED3(黄色)的亮灭状态 */ /* 等待用户释放按键,并消抖 */ while(P1_7 & 0x80); delay(10); while(P1_7& 0x80); /* 清除中断标志 */ P1IFG &= ~0x80; // 清除P1.7中断标志 IRCON2 &= ~0x08; // 清除P1.0端口中断标志 } EA = 1; // 使能全局中断 } /***************************************************************** * 函数名称: main * 功 能: main函数入口 * 入口参数: 无 * 出口参数: 无 * 返 回 值: 无 *****************************************************************/ void main(void) { /* 由于CC253x系列片上系统上电复位后,所有21个数字I/O均默认为具有上拉的通用输入I/O,因此本实验只需要改变作为LED控制信号的P1.0、P1.1和P1.4方向为输出即可。另外还需要将P2.0设置为输入下拉模式。 在用户的实际应用开发中,我们建议用户采用如下步骤来配置数字I/O: (1) 设置数字I/O为通用I/O; (2) 设置通用I/O的方向; (3) 若通用I/O的方向被配置为输入,可配置上拉/下拉/三态模式,在此实验中不需要配置; (4) 若通用I/O的方向被配置为输出,可设置其输出高/低电平。 */ P1SEL=0; /* 配置P1.0、P1.1和P1.4的方向为输出 */ P1DIR |= 0x03; // 0x13 = 0B00010011 P1_0 = 1; // P1.0输出低电平熄灭其所控制的LED1(绿色) P1_1 = 1; // P1.1输出低电平熄灭其所控制的LED2(红色) /* 配置P1端口的中断边沿下降沿产生中断 */ PICTL |= 0x02; /* 使能P1.6和P1.7 中断 */ P1IEN |= 0xC0; /* 使能P1端口中断 */ IEN2 |= 0x10; /* 使能全局中断 */ EA = 1; while(1); } 4. 实施步骤 (1) 启动IAR开发环境,新建工程。 (2) 在IAR开发环境中编译、运行、下载程序。 (3) 通过两个按键来控制两个LED的亮灭。