之前使用MCU做產品,Timer可以說是和GPIO一樣一定會用的到的介面。
但學習Arduino時,發現硬體暫存器都包在Arduino自己的library,一般使用者
難以窺見原貌。

我的Arduino Timer的學習主要從此網站
http://letsmakerobots.com/node/28278
而我只節錄部分段落

Timer是什麼?
Timer是一個內建在Arduino控制器晶片內的一塊硬體,它像是一個clock用來處理和時間有關的事件。
Arduino Controller使用Atmel AVR系列的晶片

ATmega168/ATmega368 均配有3個Timer: timer 0, timer1, timer2。其中timer 0, timer 2是8bit timer;而timer 1是16bit timer。
ATmega1280/ATmega2560則配有6個Timer,其中timer 0 ~timer 2功能和ATmega168/ATmega368一樣,而timer 3, timer 4, timer 5則和timer 1一樣均是16bit timer。

所有的timer都會相依於Arduino的system clock。大部分Arduino的System clock是16MHz,但是有些電源使用3.3V的System Clock是8MHz,所以再設置timer function時要注意當時的System clock。
使用Arduino自帶的library,timer都被設置成1kHz freqency並且打開中斷。

Timer 0
Timer 0是一個8bit timer
在Arduino自帶的function,像是delay()、millis()、micros()都是使用到timer 0
因此改變timer 0的設置會影響到上述function

Timer 1
Timer 1是一個16bit timer
在Arduino的世界,Servo library使用timer 1在Arduino uno

Timer 2
Timer 2是一個8bit timer
在Arduino世界,tone()使用到timer 2

Timer 3, Timer 4, Timer 5
Timer 3,4,5只能在Arduino mega Board上獲得
它們都是16bit timer

Timer Register
可以藉由修改timer register來改變Timer的行為
最重要的timer register是
TCCRx - Timer/Counter Control Register. The prescaler can be configured here.

TCNTx - Timer/Counter Register. The actual timer value is stored here.

OCRx - Output Compare Register
ICRx - Input Capture Register (only for 16bit timer)
TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts.
TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt.

Clock select and timer frequency
每一個Timer的clock source均是各自獨立,可以個別設置
這邊有一個範例,使用timer 1產生2Hz,你將需要下列條件
1. Arduino Controller的主頻是16MHz
2. maximun timer counter value(256 for 8bit, 65536 for 16bit)
3. 藉由主頻除以prescaler來產生除頻後的頻率 (16000000/256 = 62500)
4. 再把上一個結果除以渴望輸出的頻率,範例是2Hz (62500 / 2Hz = 31250)
5. 驗證計算後的結果是否有超過最大timer counter value (31250 < 65536)。如果超過,必須重新選擇prescalar值

Timer modes
Timer可以透過設定而有不同的mode

PWM mode( Pulth width modulation mode),the OCxy outputs are used to generate PWM signals.

CTC mode( Clear timer on compare match). When the timer counter reaches the compare match register, the timer will be cleared.

 Interrupt是什麼?
MCU上的程式一般而言都是一條條指令依序執行下去,而中斷(Interrupt)就是一個外部的事件會打斷原先依序進行的指令,而進入到一個稱為「Interrupt service rotine」(ISR) 的程序。當完成ISR程序後,原先被打斷的程式,會繼續下一個指令執行。
這邊的指令是指一個單一機器語言的指令而非C語言或C++的一行

要使用ISR前必須要確認
1.Enable Interrupt
2.對應的Interrupt mask也有打開

Interrupts在Arduino被打開或關閉透過Function,interrupts()/nointerrupts()
在Arduino的Firmware,中斷預設是被打開的
而Interrupt masks打開或關閉使用的中斷是透過TIMSKx對bit做setting或clearing的動作。

當中斷發生時,TIFRx內的flag會被set. Flag會自動被clear當進入ISR程序後或也可手動clear flag

而Arduino function, attachInterrupt()和detachInterrupt()只能使用在外部中斷源,而非內部中斷源。

經由上述解釋Interrupt及Timer後,可以開始學習怎麼使用Timer Interrupt
Timer Interrupts
每一個timer可以產生不同種類的中斷
TIMSKx , x=0...5 ex. TIMSK1(timer1 interrupt mask register)
OCRxy, x=0...5,y=A,B,C ex.OCR2A(timer2 output compare register A)

Timer Overflow
Timer Overflow表示timer達到上限值時,會觸發overflow interrupt,並且timer overflow bit在TIFRx會被setting。如果有設置TOIEx(the timer overflow interrupt enable bit)在TIMSKx,則會進入ISR(TIMERx_OVF_vect)程序

Output Compare Match
當output compare match interrupt發生,OCFxy bit將在TIFRx被set
如果有設置OCIExy在TIMSKx,則會進入ISR(TIMERx_COMPy_vect)程序

Examples

Time for some examples

Blinking LED with compare match interrupt

第一個範例使用timer1的CTC mode和the compare match interrupt去變化一個LED燈。Timer設定頻率為2Hz,LED燈被變化在ISR程序內

#include "Arduino.h"

void Timer1Init(void)
{
    noInterrupts();
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1 = 0;

    OCR1A = 31250; /* compare match register 16MHz/256/2Hz */
    TCCR1B |= (1 << WGM12);    /* CTC Mode */
    TCCR1B |= (1 << CS12);    /* 256 prescalar */
    TIMSK1 |= (1 << OCIE1A);    /* Enable timer compare interrupt */
    interrupts();
}

ISR(TIMER1_COMPA_vect)
{
    digitalWrite(13,digitalRead(13)^1);
}

// the setup function runs once when you press reset or power the board
void setup() {
    pinMode(13, OUTPUT);
    Timer1Init();
}

// the loop function runs over and over again forever
void loop() {

}

 

 

arrow
arrow
    文章標籤
    arduino
    全站熱搜
    創作者介紹
    創作者 凱文先生的部落格 的頭像
    凱文先生的部落格

    凱文的八卦俱樂部小天地

    凱文先生的部落格 發表在 痞客邦 留言(0) 人氣()