何為按鍵中斷?
在了解按鍵中斷之前,我們先來了解一下什么是中斷?中斷就是程序執行當前代碼,當前任務的時候;
突然有自身函數或外部的影響,而使程序執行到別的任務再回來。
舉個栗子:
當你在做飯的時候,電話突然響了,這時候你只能停下當前做飯的動作,去執行聽電話的動作
(同理,當你的程序要打印一句很長很長的話,突然有個中斷出來,你要去執行那個中斷,那個中斷
可能是算一個數,也可能是讓你程序復位程序執行)
中斷優先級別
而說起中斷,我們的中斷也有個先后順序中斷,是先中斷去算數還是先去中斷復位呢?這就需要看你
程序的定義了,默認情況下,你是先把數算出來,再把程序復位才合理的,要是你把程序復位了,再
去算數,也進不去算了。不過話說回來,你最后復位了程序,算出來的結果,一樣回不去顯示出來,
畢竟被自己復位清會原始值了。但是做飯期間來電話,中間必定要做的事情還是要有的,因為你不知
道你的這個電話要聊多久,所以你會先把爐子給關了,然后才去接電話的,要不你的這頓飯就吃不下
了。
下面來看個例子怎么設置中斷的優先級吧
首先,我們說一下規則
為了保證中斷系統正常工作,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 }