PIC18x Timer 分享 III

經過 Timer0 的洗禮,會不會覺得 8-bit 的計數太 Low end 呢?還得自己數 125 次才能得到 1ms。接下來讓我們看看 Timer1 + CCP 模組的威力吧!



這是 Timer1 16-bit 讀寫模式的方塊圖,紅色的部份是需求的功能,藍色的部份是對應的暫存器設定。我們只是很單純地使用內部 Clock (Fosc / 4) 計數 1000 次輸出 (需要 16-bit)

(Page 129)

對應的暫存器設定如上,只要設定 T1CON = 0x01 就可以將 Timer1 打開了,簡單吧

(Page 144)

上圖為 CCP 模組 (Capture / Compare / PWM 的縮寫) 在比較模式 (Compare) 的方塊圖。目前的需求是將 CCPR1 (分成 CCPR1H 與 CCPR1L) 與 TMR1 (分成 TMR1H 與 TMR1L) 做比較若兩者的值相等則設定 CCP1IF 旗標同時將 Timer1 歸零 (在 Mode 0x0B 的情況下)。後面還可以有 CCP1 的輸出,不過等我們用到時再說吧

(Page 141)

這裡也很簡單,只要設定 CCP1CON = 0x0B 為 Reset Timer1 的功能就可以了。

另外在方塊圖中的 T3CCP2 (位於 T3CON) 是用來選擇 Timer1 或 Timer3 與 CCP1 做比較的,原本應該設定為 0,只是 Power-on Reset 時初始值為 0,所以就不用設定了。

(Page 98)

至於 CCP1IF 則是位於 PIR1 bit 2,其中要特別注意的是:當這個旗標觸發後,必須以軟體的方式清除

有了這些資訊後,我們就可以開始來觀察了


請依照先前設定的方式將下列暫存器抓進來,並設定初始值以便觀察

T1CON = 0x01
CCP1CON = 0x0B
CCPR1 = 0x02
TMR1 = 0x00
PIR1 = 0x00


每次按單步執行可以發現 TMR1 + 1,當 TMR1 到 0x02 時會自動歸零,同時設定 PIR1 bit2 (CCP1IF)

將 PIR1 bit2 設為 0 後,繼續執行則會重覆上述的動作。有了這些觀察結果後,就可以開始撰寫程式碼了


#include <myapp.h>

void main(void)
{
 unsigned int PP;   // 1ms 的計數器
 unsigned char SS, MM, HH; // 秒、分、時
 
 PP = SS = MM = HH = 0;  // 初始值歸零
 CCP1CON = 0x0B;    // 設定 CCP1 工作在自動 Reset Timer1 的模式
 CCPR1 = 1000;    // 設定計數 1000 次
 TMR1H = TMR1L = 0;          // Timer1 歸零
 T1CON = 0x01;    // 開始 Timer1
 
 while (1)
 {
  CLR(PIR1, BIT2);   // 將 CCP1IF 旗標歸零
  while (!GET(PIR1, BIT2)) // 等待計數結束
  {
  }
  
  if (++PP == 1000)   // 若 1ms 計數 1000 次結束
  {
   PP = 0;     // 則將 PP 歸零,同時將 SS + 1
   
   if (++SS == 60)   // 若 1 秒鐘計數 60 次結束
   {
    SS = 0;    // 則將 SS 歸零,同時將 MM + 1
    
    if (++MM == 60)  // 若 1 分鐘計數 60 次結束
    {
     MM = 0;   // 則將 MM 歸零,同時將 HH + 1
     
     if (++HH == 24) // 若 1 小時計數 24 次結束
     {
      HH = 0;  // 則將 HH 歸零
     }
    }
   }
  }
  
  // 顯示時間
 }
}

跟先前的程式碼比起來是不是精簡許多,初始化完後,只要判斷 CCP1IF 旗標就可以了。

在 p18f4520.h 中並未定義 TMR1,所以要分別對 TMR1H 與 TMR1L 做歸零的動作。

另外這裡用了一個寫程式的小技巧,就是將

PP++;
if (PP == 1000)

合併成 (記得要用前置式)

if (++PP == 1000)

讓程式更容易閱讀。最後就來看一下執行的結果吧


先在第 21 行設定中斷點,按 Reset 回到程式的開頭後,先按 Stopwatch 的 Zero 將時間歸零,然後執行到中斷點後的時間為 1.027ms,其中 27us 是前面初始化所花費的時間,之後再執行就可以發現每次都是很精確的 1ms,這就是硬體計時的好處,不像軟體計時還要考慮指令週期的問題。

又完成一次艱鉅的任務了,在這次任務中我們認識了 CCP 模組,後面將有更多關於它的介紹,敬請期待。。。

留言

Unknown寫道…
Johnny

我快變成你的小粉絲了
我原本都看不懂怎樣對應data sheet

真的萬分感謝
牧童叔寫道…
一回生,二回熟
我想照老師說的方式:挑需求的重點看
這樣應該就足夠了

這個網誌中的熱門文章

Linux 批次檔的寫法

【分享】如何顯示 Debug Message

[分享] Visual Studio 遠端偵錯