何为按键中断?
在了解按键中断之前,我们先来了解一下什么是中断?中断就是程序执行当前代码,当前任务的时候;
突然有自身函数或外部的影响,而使程序执行到别的任务再回来。
举个栗子:
当你在做饭的时候,电话突然响了,这时候你只能停下当前做饭的动作,去执行听电话的动作
(同理,当你的程序要打印一句很长很长的话,突然有个中断出来,你要去执行那个中断,那个中断
可能是算一个数,也可能是让你程序复位程序执行)
中断优先级别
而说起中断,我们的中断也有个先后顺序中断,是先中断去算数还是先去中断复位呢?这就需要看你
程序的定义了,默认情况下,你是先把数算出来,再把程序复位才合理的,要是你把程序复位了,再
去算数,也进不去算了。不过话说回来,你最后复位了程序,算出来的结果,一样回不去显示出来,
毕竟被自己复位清会原始值了。但是做饭期间来电话,中间必定要做的事情还是要有的,因为你不知
道你的这个电话要聊多久,所以你会先把炉子给关了,然后才去接电话的,要不你的这顿饭就吃不下
了。
下面来看个例子怎么设置中断的优先级吧
首先,我们说一下规则
为了保证中断系统正常工作,CC2530的中断系统还存在自然优先级,即:
(1)如果多个组被设置成相同级别,则组号小的要比组号大的优先级高。
(2)同一组中所包含的3个中断源,最左侧的优先级最高,最右侧的优先级最低。
而将6个中断优先级组设置成不同优先级别,使用的是IP0和IP1两个寄存器,两个寄存器的定义见表2-7,。
要为优先级组设置优先级别,可参照表2-6来分别配置IP0和IP1。
例如,要设置的中断源优先级为P0INT>P1INT>P2INT,则可以使用以下代码实现
IP1=0x30; //IPG5级别为3,IPG4级别为2,IPG1级别为1,其他
IP0=0x22; //组级别为0。
看了上面的例子,可能一大部分人还是很懵,没事,我一开始也一样懵。
首先我们来把上面例子的IP1和IP0两个寄存器拆开来看
IP1 0011 0000
IP0 0010 0010
可能拆开来,我们还是不知道什么意思,但是我们看看IP1和IP0的第5位上,合起来后变成11,再回到表2-6,
11便是级别3-highest(最高级别),同理,我们的第4位和第1位,便设置成了级别2和级别1。
而我们为什么不在其他位设置11(级别3),10(级别2)和01(级别1)呢?原因很简单,我们再看回到表2-7。
P0INT在IPG5组上
P1INT在IPG4组上
P2INT在IPG1组上
而剩下的因为不需要分配优先级,便默认成为组级别0。
按键中断
说了半天,中断优先级别在我们今天这个文章里面暂时用不到,但是既然说到中断,我们也要先了解着,因为
CC2530单片机程序上,运用到中断的除了按键(外部)中断外,还有定时器中断和串口中断,后面迟早会用
到的。而同上个教程一样,我们要用中断,同样要用到寄存器。而相关寄存器看下面相关资料,也可百度自行
扩展。
先关寄存器
IEN0:中断使能0,0为中断禁止,1为中断使能
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
总中断EA |
未用 |
睡眠定时器中断 |
AES加密/解密中断 |
USART1 RX中断 |
USART0 RX中断 |
ADC中断 |
RF TX/RF FIFO中断 |
IEN1:中断使能1,0为中断禁止,1为中断使能
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
未用 |
未用 |
端口0 |
定时器4 |
定时器3 |
定时器2 |
定时器1 |
DMA传输 |
P0IFG(P1IFG相同):中断状态标志寄存器,当输入端口有中断请求时,相应的标志位将置1。
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
P0_7 |
P0_6 |
P0_5 |
P0_4 |
P0_3 |
P0_2 |
P0_1 |
P0_0 |
P2INP: D0~D4控制P2_0~P2_4的输入模式,0为上拉/下拉,1为三态;
D5~D7设置对P0、P1和P2的上拉或下拉的选择。0为上拉,1为下拉;
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
端口2选择 |
端口1选择 |
端口0选择 |
P2_4模式 |
P2_3模式 |
P2_2模式 |
P2_1模式 |
P2_0模式 |
P2IFG:D0~D4为P2_0~P2_4的中断标志位
D5为USB D+中断状态标志,当D+线有一个中断请求未决时设置该标志,用于检测USB挂起状态下的USB恢复事件。当USB控制器没有挂起时不设置该标志。
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
未用 |
未用 |
USB D+ |
P2_4 |
P2_3 |
P2_2 |
P2_1 |
P2_0 |
P2IEN:D0~D4控制P2_0~P2_4的中断使能
D5控制USB D+的中断使能
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
未用 |
未用 |
USB D+ |
P2_4 |
P2_3 |
P2_2 |
P2_1 |
P2_0 |
IEN2:中断使能2,0为中断禁止,1为中断使能
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
未用 |
未用 |
看门狗定时器 |
端口1 |
USART1 TX |
USART0 TX |
端口2 |
RF一般中断 |
PICTL:D0~D3设置各个端口的中断触发方式,0为上升沿触发,1为下降沿触发。
D7控制I/O引脚在输出模式下的驱动能力。选择输出驱动能力增强来补偿引脚DVDD的低I/O电压,
确保在较低的电压下的驱动能力和较高电压下相同。0为最小驱动能力增强。1为最大驱动能力增强。
|
|||||||
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
I/O驱动能力 |
未用 |
未用 |
未用 |
P2_0~P2_4 |
P1_4~P1_7 |
P1_0~P1_3 |
P0_0~P0_7 |
程序
下面来两个程序实例,看看效果吧
1 //********************************************* 2 /*利用中断控制方式,使用SW1按键控制LED1的亮/灭状态,具体要求如下: 3 /*①系统上电后LED1熄灭 4 /*②每次按下一次SW1按键并松开时,LED1切换自身的亮/灭状态。 5 /* 6 /* 7 /* 8 //********************************************/ 9 10 #include"ioCC2530.h" 11 #define D4 P1_1//LED1 12 13 typedef unsigned char uint8; 14 typedef unsigned int uint16; 15 16 uint8 flag = 0;//定义LED1的亮灭状态标志 17 18 void port()//初始化LED灯 19 { 20 P1DIR = 0x1b;//设置为输出 21 P1 &=~ 0x1b;//关闭LED灯 22 } 23 24 void inter()//初始化中断 25 { 26 IEN2 = 0x10;//端口1中断使能 27 P1IEN = 0x04;//P1_2中断使能 28 PICTL = 0x02;//P1_3~P1_0下降沿触发中断 29 EA = 1;//开启总中断 30 } 31 32 main() 33 { 34 port(); 35 inter(); 36 while(1) 37 { 38 if(flag==0) 39 { 40 D4=0; 41 } 42 if(flag==1) 43 { 44 D4=1; 45 } 46 } 47 } 48 49 #pragma vector = P1INT_VECTOR 50 __interrupt void P1_INT () 51 { 52 if(P1IFG & 0x04)//如果P1_2端口中断标志位置位 53 { 54 flag = !flag;//每进入一次中断,改变一次中断 55 P1IFG &=~ 0x04;//清除P1_2端口中断标志位 56 } 57 P1IF = 0;//清除P1端口中断标志位 58 }
1 //********************************************* 2 /*使用中断方式,用SW1按键控制LED1和LED2的显示效果,具体要求如下: 3 /*①系统上电后LED1和LED2全部熄灭 4 /*②第一次按下SW1按键后,LED1点亮 5 /*③第二次按下SW1按键后,LED2点亮 6 /*④第三次按下SW1按键后,LED2熄灭 7 /*⑤第四次按下SW1按键后,LED1熄灭 8 /*⑥四次按键过后,从要求②开始进入新的控制周期 9 /* 10 //********************************************/ 11 12 13 14 #include"ioCC2530.h" 15 #define D3 P1_0//LED2 16 #define D4 P1_1//LED1 17 18 typedef unsigned char uint8; 19 typedef unsigned int uint16; 20 21 uint8 flag=0;//每次按键按下,改变LED状态的标志 22 23 void port()//初始化LED 24 { 25 P1DIR = 0x1b;//LED设置为输出 26 P1 &=~ 0x1b;//LED熄灭 27 } 28 29 void inter()//按键中断初始化 30 { 31 IEN2 = 0x10;//P1端口中断使能 32 P1IEN = 0x04;//P1_2中断使能 33 PICTL = 0x02;//P1_3~P1_0设置下降沿触发中断 34 EA = 1;//开启总中断 35 } 36 37 main() 38 { 39 port(); 40 inter(); 41 while(1) 42 { 43 if(flag==1) 44 { 45 D4=1; 46 D3=0; 47 } 48 else if(flag==2) 49 { 50 D4=1; 51 D3=1; 52 } 53 else if(flag==3) 54 { 55 D4=1; 56 D3=0; 57 } 58 else if(flag==4) 59 { 60 D4=0; 61 D3=0; 62 } 63 } 64 } 65 66 67 #pragma vector = P1INT_VECTOR 68 __interrupt void P1_INT() 69 { 70 if(P1IFG & 0x04)//如果P1_2端口中断标志位置位 71 { 72 flag++; 73 if(flag==5) 74 { 75 flag=1; 76 } 77 P1IFG &=~ 0x04;//清除P1_2端口中断标志位 78 } 79 P1IF = 0;//清除P1端口中断标志位 80 }