2011年7月13日 星期三

4.1) Blink with Timer

實驗目的
使用 Timer 計算時間,讓一顆燈號閃爍,每隔一秒切換一次燈號。
材料
  • Arduino 主板 x 1
  • LED x 1
接線
  • 把 LED 接到 Arduino 板子上,LED 長腳 (陽極) 接到 pin13,短腳 (陰極) 接到 GND,如下圖:

image

程式碼

先來看 Arduino 版本的 Blink 程式:

這支程式是 Arduino 的入門程式,相信你應該很熟悉。

接下來我們改用 Timer 改寫程式,利用 Timer1 計算一秒鐘的時間:

以 Arduino UNO 或 Duemilanove 為例,它們的時脈頻率是 16 MHz,如果把 Timer1 的 prescaler 設成 CPU clock/1024,那麼 Timer1 的 clock 便是:

Timer1 的時脈 = 16 MHz/1024 = 15625Hz

所以 Timer1 從 0 數到 15625 就是一秒鐘的時間。Timer1 是 16-bit 的,最大值可以到 65535。

把 Prescaler 設成 CPU clock/1024 的方法是:

使用中斷

底下的程式是改用 Timer Overflow 中斷的版本:

這次 Prescaler 仍然使用 CPU clock/1024,所以,要算一秒鐘,一樣是讓 Timer1 從 0 數到 15625 就可算出。除了啟用 Timer overflow 中斷外,我們還得寫個 ISR:

當發生中斷跑到 ISR 時,代表時間已經經過 1 秒鐘,所以接著就切換燈號,然後再把 -15625 載入到 TCNT1,讓 Timer1 在一秒鐘後再次觸發中斷。

我們也可以不用 Prescaler,像這樣:

不用 Prescaler 的時候,Timer 的 clock 就是 16 MHz:

Timer1 overflow frequency =  16 MHz/65536 = 244 Hz

所以只要發生 244 次 Timer overflow 中斷,就代表已經過了 1 秒鐘的時間。

補充說明

因為 Timer0 已經被 Arduino 拿去用了,所以這篇教學使用 Timer1 示範。

延伸閱讀

3 則留言:

  1. 又要請教您了Cooper~~ 希望不會太麻煩你!

    1.請問TCCR1A跟 TCNT1都是暫存器

    為什麼TCCR1A的編輯方式使用16進位
    而TCNT1使用十進位呢?
    如下:
    TCCR1A=0x00
    TCNT1=0

    2.請問當我們啟動TIMER1中斷後, TIMER1_OVF_vect中斷發生的條件是什麼呢?

    ISR (TIMER1_OVF_vect)
    {
    PORTB ^= _BV(5);
    TCNT1 = -15625;
    }

    請問是超過65535就發生中斷嗎?
    如果是的話 為什麼不設定TCNT1=(65535-15625)呢?

    麻煩Cooper解惑~~~真的很感謝!!

    回覆刪除
  2. Hi, 不麻煩

    1. TCNT1 = 0; 跟 TCNT1 = 0x00; 兩種寫法結果是一樣的,都是歸零,所以怎麼寫都沒差。

    2. 沒錯,是超過 65535 就會發生中斷

    TCNT1 = -15625,這行是利用二的補數 (負數表示法) 來設定 TCNT1。

    這行

    TCNT1 = -15625;

    跟這行

    TCNT1 = 65536 - 15625;

    這兩行其實是異曲同工,作用是一樣的喔!

    回覆刪除

注意:只有此網誌的成員可以留言。