CC2530學習(三)CC2530中斷系統以及一些點亮小燈實驗

對中斷的理解

首先我們知道內核與外設需要交互,那交互的方式有哪些呢?
瞭解過一些單片機或者操作系統等知識的應該能想到是:輪詢中斷

輪詢其實就是由CPU定時發出詢問,依序詢問每一個周邊設備是否需要其服務,有即給予服務,服務結束後再問下一個周邊,接着不斷週而復始。這樣我們也就能想到輪詢的方式貌似公平,實際工作效率很低,且不能及時響應緊急事件;

中斷其實就是在執行CPU當前程序時,由於系統中出現了某種急需處理的情況,CPU暫停正在執行的程序,轉而去執行另外一段特殊程序來處理出現的緊急事務,處理結束後,CPU自動返回到原來暫停的程序中去繼續執行。

本次我們主要說說CC2530中斷這種交互方式
有兩個重要概念:
<1> 中斷服務函數: 內核響應中斷後執行的相應處理程序,即上面提到的特殊程序。
<2> 中斷向量:中斷服務程序的入口地址。每個中斷源都對應一個固定的入口地址。當內核響應中斷請求時,就會暫停當前的程序執行,然後跳轉到該入口地址執行代碼。

CC2530中斷系統

CC2530具有18箇中斷源,每個中斷源都由各自的一系列特殊功能寄存器來進行控制。可以編程設置相關特殊功能寄存器,設置18箇中斷源的優先級以及使能中斷申請響應等。我們常用的中斷源有下面幾個:
在這裏插入圖片描述
大家也不需要將全部給記住,我們只需要將一些常用的記熟,然後對於其他的當遇見了網上查查資料就行了。

CC2530的中斷處理函數

當發生中斷請求,需要暫停CPU目前的工作轉去執行另外一份特殊程序。而這個特殊程序就是我們所說的中斷處理函數
中斷服務函數與一般自定義函數不同,有特定的書寫格式
在這裏插入圖片描述
<1> 在每一箇中斷服務函數之前,都要加上一句起始語句
#pragma vector = <中斷向量>
<中斷向量>表示接下來要寫的中斷服務函數是爲那個中斷源服務的,該語句有兩種寫法:
#pragma vector = 0x7B 或者 #pragma vector = P1INT_VECTOR
前者是中斷向量的入口地址,後者是頭文件**“ioCC2530.h”中的宏定義。
<2> _ _interrupt
關鍵字表示該函數是一箇中斷服務函數,<函數名稱>可以 自定義,函數體 不能帶有參數,也不能有返回值

CC2530的外部中斷

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

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

對於這些中斷寄存器的具體介紹就請大家參考這個博客吧
中斷寄存器介紹

點小燈實驗

依次點亮兩燈

首先我們應該初始化led1(藍燈),led2(黃燈)即設置以前講過的PxSEL,PxDIR,PxINP等寄存器。
這裏再次貼下流程圖:
在這裏插入圖片描述
代碼:

#include "led.h"
#include "delay.h"
#include "iocc2530.h"
void main(void)
{
  P1SEL &=~0x03;//設置兩個led爲通用io
  P1DIR |=0x03;//設置兩個led爲輸出模式
  led1=1;//初始化小燈1亮
  led2=0;//初始化小燈2滅
  while(1)
  {
    led1=!led1;
    delay(30000);
    led2=!led2;
    delay(30000);
    
  }
}

具體的led1,led2的引腳定義我也定義在delay.h文件裏面,具體的引腳需要大家根據芯片的硬件原理圖進行定義。delay延遲函數我也在delay.h文件定義好了。延遲函數很簡單大家網上可以搜搜。

按鍵實現亮燈效果

這個任務多了按鍵,其實也是一樣,我們只需要多初始化一個按鍵爲通用io,輸入模式,三態就行。

亮燈效果:按一下藍燈亮,黃燈滅;再按一下藍燈滅,黃燈亮;再按一下兩燈都亮;再按一下兩燈都滅

代碼:

#include "led.h"
#include "delay.h"
#include "iocc2530.h"
void main(void)
{
  uint count=0;
  uint temp=0;
  P1SEL &= ~0x04;//設置按鍵1 P1_2爲通用io
  P1DIR &= ~0x04;//設置按鍵1 P1_2爲輸入模式
  P1INP |= 0x04;//設置爲三態上拉模式

  P1SEL &=~0x03;//設置兩個led爲通用io
  P1DIR |=0x03;//設置兩個led爲輸出模式
  
  led1=0;//初始化小燈1滅
  led2=0;//初始化小燈2滅
  
  while(1)
  {
    if(key1==0) //等待按鍵按下
    {
      delay(100);
      if(key1==0)  //消抖
      {
        while(key1==0);//等待按鍵鬆開
        count++; //記錄按鍵次數
        temp=count%4;
      }
    }
    switch(temp)  //對按鍵取餘
    {
    case 0:    //兩個燈滅
      led1=0;
      //delay(30000);
      led2=0;
      //delay(30000);
      break;    
    case 1:    //小燈1亮小燈2滅
      led1=1;
      delay(30000);
      led2=0;
      delay(30000);
      break;
    case 2:    //小燈1滅小燈2亮
      led1=0;
      delay(30000);
      led2=1;
      delay(30000);
      break;
    case 3:    //兩個燈亮
      led1=1;
      delay(30000);
      led2=1;
      delay(30000);
      break;
    }
  }
}

按鍵中斷實現兩燈效果

這次就是我們用今天所介紹的中斷方式來實現亮燈效果

亮燈效果:按一下藍燈亮,黃燈滅;再按一下藍燈滅,黃燈亮;再按一下兩燈都亮;再按一下兩燈都滅

實現一個基本的中斷功能我們所要完成的步驟有:

<1> 配置IENx寄存器,使能端口組的中斷功能。
<2> 配置PxIEN寄存器,使能具體的外部中斷引腳。
<3> 配置PICTL寄存器,設置中斷觸發方式
<4>設計外部中斷服務函數
在編寫中斷服務函數的時候,書寫格式要正確,中斷向量不能搞錯。特別要注意:在函數裏面把端口組和引腳的標誌位清除,否則CPU將會反覆進入中斷,必須清除引腳標誌位PxIFG清除端口組標誌位PxIF

代碼:

#include "led.h"
#include "delay.h"
#include "iocc2530.h"

//外部中斷1服務函數
#pragma vector=P1INT_VECTOR  //外部中斷1的向量入口
__interrupt void led_show(void)
{
  int count=1;
  do{
      switch(count)  //對按鍵取餘
        {
        case 1:    //小燈1亮小燈2滅
          led1=1;
          delay(50000);
          led2=0;
          delay(50000);
          break;
        case 2:    //小燈1滅小燈2亮
          led1=0;
          delay(50000);
          led2=1;
          delay(50000);
          break;
        case 3:    //兩個燈亮
          led1=1;
          delay(50000);
          led2=1;
          delay(50000);
          break;
        case 4:    //兩個燈滅
          led1=0;
          //delay(50000);
          led2=0;
          //delay(50000);
          break;    
        }
      delay(50000);
      count++;
  }while(count<=4);
  P1IFG &= ~0x04;//軟件清除P1_2引腳標誌位
  P1IF =0;//軟件清除P1端口組的標誌位
}
void main(void)
{
  
  P1SEL &= ~0x04;//設置按鍵1 P1_2爲通用io
  P1INP |= 0x04;//設置爲三態上拉模式
  P1IEN |= 0x04;//P1_2設置爲中斷方式
  PICTL |= 0x04;//下降沿觸發
  
  EA=1;//打開總中斷
  IEN2 |=0x10;//端口1中斷使能
  P1IFG |=0x00;//初始化中斷標誌位

  P1SEL &=~0x03;//設置兩個led爲通用io
  P1DIR |=0x03;//設置兩個led爲輸出模式
  
  led1=0;//初始化小燈1滅
  led2=0;//初始化小燈2滅
  while(1)
  {
    
  }
}

本次介紹就到這了,謝謝大家的觀看!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章