天天看點

飛思卡爾16位單片機(四)——GPIO輸入功能測試

一、介紹

        在這篇文章中,我們以按鍵作為輸入器件對飛思卡爾XEP100單片機的GPIO的輸入功能進行測試。對應的硬體電路如下圖所示。

飛思卡爾16位單片機(四)——GPIO輸入功能測試

        當按鍵未按下時,由于有上拉電阻R39~R312的作用,單片機檢測到的電平為高電平;當按鍵按下時,單片機引腳與地短接,單片機檢測到引腳為低電平。

         當按鍵按下時,按鍵輸出端的原始電平如下圖所示:

飛思卡爾16位單片機(四)——GPIO輸入功能測試

        由圖中可以看出,在按鍵按下和松開時,按鍵的電平信号存在波動,一般為10~15ms,這樣有可能導緻誤判。為了消除抖動,可行的方法有:硬體去抖和軟體去抖兩種方法。本文的電路上使用的方法為硬體去抖,即在按鍵的兩端加了一個去抖電容。軟體去抖的方法是在檢測到按鍵按下後,延時10~15ms,跳過抖動的這段信号,再進行檢測,如果是低電平則判斷按鍵按下。

        本文的硬體電路的按鍵與單片機引腳的連接配接關系如下:

PTH3——KEY1

PTH2——KEY2

PTH1——KEY3

PTH0——KEY4

單片機的PH口是有中斷功能的I/O口,是以對按鍵狀态的讀入有查詢和中斷兩種方式。

        所謂查詢方式是指,單片機以一定的時間間隔按時對輸入口的電平進行讀取。中斷是指計算機在執行程式的過程中,當出現異常情況或特殊請求時,計算機停止現在執行的程式,轉向對這些異常情況或特殊請求的處理,處理結束後再傳回之前的程式的間斷處,繼續執行原程式。中斷時單片機實時處理内部事件或外部事件的一種機制,當某種内部事件或外部事件發生時,單片機的中斷系統将迫使CPU暫停正在執行的程式轉而去執行中斷事件,中斷事件處理完畢後,再傳回被中斷的程式處,繼續執行下去。中斷機制如下圖所示。   

飛思卡爾16位單片機(四)——GPIO輸入功能測試

在程式中使用中斷具有以下優點:

(1)提高了CPU的效率。CPU與外圍裝置的工作方式有查詢和中斷兩種方式,查詢方法是無論外圍裝置是否需要服務,CPU每隔一段時間都要依次查詢一遍,這種方法CPU需要花費時間做查詢工作。而中斷則是在外圍裝置需要服務時主動告訴CPU,CPU則停下目前的工作去進行中斷程式,進而可以提高CPU的效率。

(2)可以實作實時處理。外圍裝置任何時刻都可以送出請求中斷信号,CPU接到請求後及時處理,以滿足實時的需求。

(3)可以及時處理故障。單片機系統運作過程中難免會出現故障,有許多事情是無法預料到的。如:電源掉電、存儲器出錯、外圍裝置工作不正常等,這時可以通過中斷系統向CPU發送中斷請求,由CPU及時轉到相應的出錯處理程式,進而提高了系統的可靠性。

        産生中斷時,中斷服務程式執行完畢後恢複單片機狀态,單片機從被中斷打斷的地方繼續執行。當某一中斷事件發生,與該事件相對應的标志将被置位。如果該中斷未使能,那麼單片機不會對該中斷作出反應。CCR寄存器中的全局中斷屏蔽位I在複位之後為1,屏蔽掉所有中斷事件。在使用者程式完成堆棧指針和其他設定之後,清除I,允許單片機響應中斷事件,程式中的 “EnableInterrupts;”語句就是實作使能中斷的功能。當單片機接收到一個有效的中斷請求,在響應之前,它會執行完目前運作的指令,然後逐周期執行以下過程:

        儲存CPU寄存器到堆棧中

        設定CCR寄存器中的I=1,禁止全局中斷

        擷取目前所有挂起的待進行中斷事件中最高優先級中斷向量

        預取中斷向量的位址排列到指令隊列中

當單片機響應中斷後,I自動置為1,避免中斷嵌套。通常,ISR執行完畢後,I恢複為0(CCR從堆棧彈出)。如果在ISR中,清除I(即設定I=0),那麼MCU有可能在目前中斷事件未完成之前響應其他中斷事件,即中斷嵌套。中斷嵌套可能對使用者程式調試帶來麻煩。

        當ISR執行到RTI指令,CCR,A,X,PC從堆棧恢複。

        使用者可在自己的中斷服務程式一開始将I清零,進而使能全局中斷。那麼目前運作的中斷服務程式可以被其他中斷打斷,MCU運作新的中斷服務程式,進而形成中斷嵌套。使用者在使用中斷嵌套時會對調試帶來不便,故建議避免使用中斷嵌套。在中斷服務程式的開始,使用者程式應清掉産生該中斷的标志位,其目的是同一中斷源産生另外一個中斷事件能夠被記錄,并在完成目前中斷服務程式之後能夠得到MCU的響應。

       每一個中斷對應一個中斷向量。這個向量指向這個中斷的服務程式。用CodeWarrior程式設計時,在工程的“Project Settings\Linker Files”檔案夾下的“Project.prm”檔案中設定相應中斷的中斷向量。

二、查詢方式讀取按鍵

        在這個實驗中,我們采用查詢方式對按鍵的狀态進行讀取,主要代碼如下,(完整代碼可以從本文的資源中下載下傳)

void main(void) {
	DisableInterrupts;
  init_led_key();	
  EnableInterrupts;


  for(;;) 
  {
      delay();
      data=data<<1;         //左移一位
      if(data==0)
          data=0x01;
      if(KEY1==0&&KEY1_last==1)   //按鍵F1按下
          mode=1;
      if(KEY2==0&&KEY2_last==1)   //按鍵F2按下
          mode=2;          
      KEY1_last=KEY1;             //儲存F1的狀态
      KEY2_last=KEY2;             //儲存F2的狀态
      if(mode==1)
          LED = ~data;
      else
          LED = data;
  } 
}
           

在這段代碼中,發光二極管以流水燈的方式進行閃爍,每個周期經過delay();函數延時之後,讀取KEY1和KEY2的狀态,并且與上個周期的轉态進行比較,如果上個周期為1(沒有按下),這個周期為0(按鍵按下),則改變燈閃的模式,如果按下按鍵“KEY2”,則8個燈中隻有一個熄滅,并且熄滅的燈循環向右移動。按下按鍵“KEY1”,則8個燈中隻有一個點亮,并且點亮的燈循環向右移動。

三、中斷方式讀取按鍵

        在這個實驗中,我們通過中斷來進行按鍵的讀取,為了使能中斷功能,首先要對按鍵進行初始化,代碼如下所示。

void init_key(void) 
{
     KEY1_dir =0;       //設定為輸入
     KEY2_dir=0;
     KEY3_dir=0;
     KEY4_dir=0;
     PPSH = 0x00;		      //極性選擇寄存器,選擇下降沿;
     PIFH = 0x0f;					//對PIFH的每一位寫1來清除标志位;
     PIEH = 0x0f;		      //中斷使能寄存器;
}
           

在這段代碼中,首先将每個按鍵的方向寄存器設定為輸入狀态,然後通過PPSH寄存器設定PH0~PH3的輸入極性為下降沿觸發中斷。PIFH = 0x0f; 将标志位清除,PIEH=0x0f; 将中斷功能使能。

        這個程式的主函數代碼如下所示。

void main(void) {
	DisableInterrupts;
  init_led();
  init_key();
	EnableInterrupts;


  for(;;) 
  {
      delay(time);
      if(direction==1)
      {
          data=data<<1;         //左移一位
          if(data==0)
              data=0x01;
      } 
      else 
      {
          data=data>>1;         //右移一位
          if(data==0)
              data=0x80;
      }
      
      LED = ~data;
  } 
}
           

這段代碼中,初始化了按鍵和LED,然後主循環中控制LED閃爍,LED的狀态根據time和direction進行變化,time決定了延時的長短,進而影響閃爍的快慢,direction影響燈閃爍的方向。

        中斷的處理函數如下所示

interrupt void PTH_inter(void) 
{
   if(PIFH != 0)     //判斷中斷标志
   {
      PIFH = 0xff;     //清除中斷标志
      if(KEY1 == 0)         //按鍵1按下
      {
          time-=1;
          if(time==0)
              time=1;
      }
      if(KEY2 == 0) 
      {
          time+=1;
          if(time>10)
              time=10;
      }
      if(KEY3 == 0)
          direction=0;
      if(KEY4 == 0)
          direction=1;
   }
}
           

由于中斷設定的是下降沿觸發中斷,當有按鍵按下時,會進入中斷函數,在中斷函數中,首先确認标志位,判斷是否确實有中斷發生,然後判斷是哪個按鍵按下,用KEY1和KEY2來改變time的值,用KEY3和KEY4來改變direction的值。

        需要注意的是,要設定中斷向量,在工程的“Project Settings\Linker Files”檔案夾下的“Project.prm”檔案中設定,如下所示,

VECTOR ADDRESS 0xffcc PTH_inter
           

這個實驗的現象是,8個LED燈中有一個點亮,并且點亮的燈循環向右移動。按下按鍵“KEY1”,燈移動的速度加快;按下按鍵“KEY2”,燈移動的速度減慢;按下按鍵“KEY3”,燈向左移動;按下按鍵“KEY4”,燈向右移動。

繼續閱讀