CC2530外部中斷


一、中斷基礎概念

 內核外設之間的主要交互方式有兩種:輪詢中斷。中斷系統使得內核具備了應對突發事件的能力。

在執行CPU當前程序時,由於系統中出現了某種急需處理的情況,CPU暫停正在執行的程序,轉而去執行另外一段特殊程序來處理出現的緊急事務,處理結束后,CPU自動返回到原來暫停的程序中去繼續執行。 這種程序在執行過程中由於外界的原因而被中間打斷的情況,稱為中斷

 

采用中斷技術后,可以為計算機系統帶來以下好處:

1)實現分時操作

速度較快的CPU和速度較慢的外設可以各做各的事情,外設可以在完成工作后再與CPU進行交互,而不需要CPU去等待外設完成工作,能夠有效提高CPU的工作效率。

2)實現實時處理

在控制過程中,CPU能夠根據當時情況及時做出反應,實現實時控制的要求。

3)實現異常處理

系統在運行過程中往往會出現一些異常情況,中斷系統能夠保證CPU及時知道出現的異常,以便CPU去解決這些異常,避免整個系統出現大的問題。

 

 兩個重要的概念:

        <1> 中斷服務函數: 內核響應中斷后執行的相應處理程序。例如ADC轉換完成中斷被響應后,CPU執行相應的中斷服務函數,該函數實現的功能一般是從ADC結果寄存器中取走並使用轉換好的數據。

        <2> 中斷向量:中斷服務程序的入口地址,當CPU響應中斷請求時,會跳轉到該地址去執行代碼。

 

二、 CC2530中斷

CC2530具有18個中斷源,每個中斷源都有它自己的位於一系列SFR 寄存器中的中斷請求標志。相應標志位請 求的每個中斷可以分別使能或禁用。

 

 

Tip:

(1)當調用中斷服務例程時清除硬件。

(2)另外的 IRQ 掩碼和 IRQ 標志位存在。

 

三、CC2530中斷處理函數格式書寫

中斷服務函數與一般自定義函數不同,有特定的書寫格式

#pragma vector = 中斷向量
__interrupt void 函數名稱 (void)
{
/*此處編寫中斷處理函數的具體程序*/
PxIFG = 0; //先清除Px引腳的中斷狀態標志位
PxIF = 0; //再清除Px端口組的中斷狀態標志位
}

 

<1> 在每一個中斷服務函數之前,都要加上一句起始語句

  #pragma vector = <中斷向量>

   <中斷向量>表示接下來要寫的中斷服務函數是為那個中斷源服務的,該 語句有兩種寫法:

 #pragma  vector = 0x7B或者#pragma  vector = P1INT_VECTOR

 前者是中斷向量的入口地址,后者是頭文件“ioCC2530.h”中的宏定義。

<2> _ _interrupt關鍵字表示該函數是一個中斷服務函數,<函數名稱>可以 自定義,函數體不能帶有參數,也不能有返回值

 

四、外部中斷

(1)CC2530的P0、P1和P2端口中的每個引腳都具有外部中斷輸入功能,要使某些引腳具有外部中斷功能,需要對IENx寄存器、PxIEN寄存器和PICTL寄存器進行適當的設置。 除了各個中斷源都有自己的中斷使能開關之外,中斷系統還有一個總開關,可以同“EA = 1;”來打開總中斷。

 

IENx寄存器   使能端口組的中斷功能。

 

 

 

PxIEN寄存器   使能具體的外部中斷引腳。

 

 

 

 

PICTL寄存器    設置中斷觸發方式。

 

 

 

(2)P0、P1和P2端口分別使用P0IFP1IFP2IF作為中斷標志位,任何一個端口組上的引腳產生外部中斷時,都會將對應端口組的中斷標志自動置位。注意,外部中斷標志必須在中斷服務函數中手工清除,否則CPU會反復進入中斷。 端口狀態標志寄存器P0IFGP1IGFP2IFG,分別對應3個端口中各引腳的中斷觸發狀態,當某引腳發生外部中斷觸發時,對應的標志位會自動置位,這個標志同樣需要手工清除。

 

 

 

 

 

 

題目:

Zigbee小模塊上SW1按鍵設置為外部中斷輸入引腳。在中斷服務函數中,控制一個LED6燈的開關切換,也就是原來LED是點亮的熄滅,原來熄滅的點亮。同時在主程序中,運行一段跑馬燈程序,使LED3和LED4輪流點亮和熄滅。

思路:

1)端口初始化和跑馬燈程序

2)定義一個外部中斷初始化函數,將SW1引腳,即P1_ _2引腳配置成外部中斷輸入端口,將其中斷觸發方式設置為下降沿觸發。

3)為外部中斷定義-一個中斷服務函數,要照中斷服務函數的書寫格式編程,注意要在中斷服務函數中把相應的中斷標志位清除。必須先清除引腳的中斷標志,再清除端口組的中斷標志。

解題:

1】設計外部中斷初始化函數Init_INTP()

        外部中斷初始化函數,主要是完成跟中斷相關的特殊功能寄存器配置工作:

        <1> 配置IENx寄存器,使能端口組的中斷功能。

        <2> 配置PxIEN寄存器,使能具體的外部中斷引腳。

        <3> 配置PICTL寄存器,設置中斷觸發方式。

1 void Init_INTP()
2 {
3   IEN2 |= 0x10;         //端口1中斷使能 0001 0000 端口1 中斷使能
4   P1IEN |= 0x04;        //端口P1_2外部中斷使能   0000 0100 P1_2 使能具體的外部中斷引腳。
5   PICTL |= 0x02;        //端口P1_0到P1_3下降沿觸發  0000 0010 P1_0和P1_1  下降沿觸發
6   EA = 1;               //使能總中斷   
7 }

 

2設計外部中斷服務函數Int1_Sevice()

        在編寫中斷服務函數的時候,書寫格式要正確,中斷向量不能搞錯。特別要注意:在函數里面把端口組和引腳的標志位清除,否則CPU將會反復進入中斷,必須先清除引腳標志位PxIFG,再清除端口組標志位PxIF。

 

#pragma vector = P1INT_VECTOR     //外部中斷1的向量入口
__interrupt void Int1_Sevice()
{
  LED6 = ~LED6;
/*先清除引腳標志位,再清除端口標志位,否則會不斷進入中斷*/
  P1IFG &= ~ 0x04;        //軟件清除P1_2引腳的標志位  
  P1IF = 0;               //軟件清除P1端口組的標志位
}

 

最終代碼:

 1 #include "ioCC2530.h"
 2 
 3 #define  LED6   P1_4
 4 #define  LED3   P1_0
 5 #define  LED4   P1_1
 6 /*===================延時函數=========================*/
 7 void Delay(unsigned int t)
 8 {
 9   while(t--);
10 }
11 /*==================端口初始化函數=====================*/
12 void Init_Port()
13 {
14   //將P1_0、P1_1和P1_4設置為通用I/O端口功能
15   P1SEL &= ~0x13;   
16   //將P1_0、P1_1和P1_4的端口傳輸方式設置為輸出
17   P1DIR |= 0x13;   
18   
19   P1SEL &= ~0x04;     //P1_2作為通用I/O端口
20   P1DIR &= ~0x04;     //P1_2端口輸入
21   P1INP &= ~0x04;     //P1_2設置為上拉/下拉模式
22   P2INP &= ~0x40;     //P1_2設置為上拉
23   
24   LED6 = 0;
25   LED3 = 0;
26   LED4 = 0;
27 }
28 /*==================跑馬燈子函數=====================*/
29 void LED_Running()
30 {
31   LED3 = 1;
32   Delay(50000);
33   LED4 = 1;
34   Delay(50000);
35   LED3 = 0;
36   Delay(50000);
37   LED4 = 0;
38   Delay(50000);
39 }
40 /*===============外部中斷初始化函數==================*/
41 void Init_INTP()
42 {
43   IEN2 |= 0x10;         //端口1中斷使能 0001 0000 端口1 中斷使能
44   P1IEN |= 0x04;        //端口P1_2外部中斷使能   0000 0100 P1_2 使能具體的外部中斷引腳。
45   PICTL |= 0x02;        //端口P1_0到P1_3下降沿觸發  0000 0011 P1_0和P1_1  下降沿觸發
46   EA = 1;               //使能總中斷   
47 }
48 /*================外部中斷1服務函數====================*/
49 #pragma vector = P1INT_VECTOR     //外部中斷1的向量入口
50 __interrupt void Int1_Sevice()
51 {
52   LED6 = ~LED6;
53 /*先清除引腳標志位,再清除端口標志位,否則會不斷進入中斷*/
54   P1IFG &= ~ 0x04;        //軟件清除P1_2引腳的標志位  
55   P1IF = 0;               //軟件清除P1端口組的標志位
56 }
57 /*====================主函數==========================*/
58 void main()
59 {
60   Init_Port();          //初始化通用I/O端口
61   Init_INTP();          //初始化外部中斷
62   while(1)
63   {
64     LED_Running();     //跑馬燈
65   }
66 }
View Code

 

總結

void Init_INTP() //中斷初始化函數
{
EA = 1; //開總中斷
IENx = ? ; //要用哪一個端口組?P0,P1還是P2?
/*
IEN1 |= 0x20;開P0端口組中斷
IEN2 |= 0x10;開P1端口組中斷
IEN2 |= 0x01;開P2端口組中斷
以上都為固定開各個端口組中斷的寫法,至於為什么是這樣子才能開P0,P1,或P2端口組的中斷,翻看手冊就知道了
*/
PxIEN = ? ; //開端口組中斷之后,要選擇用哪一個引腳?
PICTL = ? ; //開引腳中斷之后,選擇沿觸發方式,上升沿還是下降沿?
}

#pragma vector = 中斷向量
__interrupt void 函數名稱 (void)
{
/*此處編寫中斷處理函數的具體程序*/
PxIFG = 0; //先清除Px引腳的中斷狀態標志位
PxIF = 0; //再清除Px端口組的中斷狀態標志位
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM