實驗目的
使用 Timer 計算時間,讓一顆燈號閃爍,每隔一秒切換一次燈號。材料
- Arduino 主板 x 1
- LED x 1
接線
- 把 LED 接到 Arduino 板子上,LED 長腳 (陽極) 接到 pin13,短腳 (陰極) 接到 GND,如下圖:
程式碼
先來看 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 示範。
又要請教您了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解惑~~~真的很感謝!!
Hi, 不麻煩
回覆刪除1. TCNT1 = 0; 跟 TCNT1 = 0x00; 兩種寫法結果是一樣的,都是歸零,所以怎麼寫都沒差。
2. 沒錯,是超過 65535 就會發生中斷
TCNT1 = -15625,這行是利用二的補數 (負數表示法) 來設定 TCNT1。
這行
TCNT1 = -15625;
跟這行
TCNT1 = 65536 - 15625;
這兩行其實是異曲同工,作用是一樣的喔!
Got it!! Thx~~~~ :))
回覆刪除