arduinoTimer1定時中斷
2019-11-22 18:46:01 (11793)
arduino定時器包含定時器/計數器0,定時器/計數器1,定時器/計數器2三個。定時器/計數器0和定時器/計數器2是一個8位的計數器,定時器/計數器1是一個16位長的計數器。timer1最大值為65535,在使用之前我們需要進行一些設置,從而使得timer1可以運行起來。進行這些設置,我們需要用內置的寄存器來存儲這些設置。每一個定時器都有很多寄存器,本篇文章主要側重timer1 的介紹和使用。存儲這些初始值的寄存器的兩個寄存器TCCRXA,TCCRXB(其中X代表序號定時器的編號0,1,2).其中TCCR是英文Timer/Counter Control Register簡寫,下麵是TCCR1A和TCCR1B的具體情況。每個寄存器共8位,每位都存儲了一些值來進行定時器的設置。表引用自:http://www.atmel.com/dyn/product ... 60&part_id=4198
開始使用timer1的話,CS12, CS11和CS10的設置是很重要的。這三個值得設置可以讓定時器工作在不同的頻率。不同的設置的頻率如下表所示:
默認的,這些值都是為0的,我們用一個例子來說明問題。下邊這個例子是設置定時器1溢出中斷,在溢出的時候我們讓2號引腳連接的LED燈亮滅轉換。首先我們來進行初始化timer1。
//包含avr-lib庫
#include <avr/io.h>
#include <avr/interrupt.h>
#define LEDPIN 2
void setup()
{
pinMode(LEDPIN, OUTPUT);
// 初始化timer1
cli(); //禁止全局中斷
TCCR1A = 0; //設置TCCR1A全為0
TCCR1B = 0;
// 設置允許timer溢出中斷
TIMSK1 = (1 << TOIE1);
//設置CS10位為1從而使定時器以時鍾的速度運行。
TCCR1B |= (1 << CS10);
/允許全局中斷
sei();
}
在上邊這段代碼中TIMSK1代表的是Timer/Counter1 Interrupt Mask Register.這個寄存器控製著timer允許怎樣的中斷。其中TOIE1表示的溢出中斷。其他的後邊會繼續介紹。
由於我們上班設置了CS10,定時器1就會開始工作。當定時器1溢出時就會執行中斷服務程序中斷服務程序如下:
ISR(TIMER1_OVF_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
這樣,我們就可以讓loop不做任何事情了,加入我們要停止中斷隻用設置TCCR1B為0就可以了。
上班每次的中斷時間大概為((1/16)*e-6)*65535=0.0041us,時間比較短,假若我們想要更長的時間,我們可以設置CS11,CS12,組合來進行設置。這樣我們的時間就可以變化了。
比如下邊的例子:
void setup()
{
pinMode(LEDPIN, OUTPUT);
// 初始化timer1
cli(); //禁止全局中斷
TCCR1A = 0; //設置TCCR1A全為0
TCCR1B = 0;
// 設置允許timer溢出中斷
TIMSK1 = (1 << TOIE1);
//設置CS10位為1從而使定時器以時鍾的速度運行。
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
sei();
}
[size=1em]這樣我們的時間就(1/16000000)*1024*65536=4.1s,
再者,加入我們想要確定的時間而不是定時器溢出來做中斷,怎麼做呢,
在定時器中斷有另外一個模式叫做CTC(Clear Timer on Compare Match),在這個模式下,timer1不在是溢出中斷了,而是在寄存器中設定好的值進行比較,若大於則進入中斷,這種模式的設置例子如下:
void setup()
{
pinMode(LEDPIN, OUTPUT);
// 初始化timer1
cli(); // 進製全局中斷
TCCR1A = 0; //設置TCCR1A全為0
TCCR1B = 0; // [size=1em]設置TCCR1B全為0
//設置比較的值得大小
OCR1A = 15624;
// 開啟CTC模式
TCCR1B |= (1 << WGM12);
// 設置 CS10和CS12位
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
// 允許比較中斷
TIMSK1 |= (1 << OCIE1A);
sei(); // 允許全局中斷
}
ISR(TIMER1_COMPA_vect)
{
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
}
在這裏:
目標時間=時間周期*(時鍾次數+1)
時鍾次數+1=目標時間/時鍾周期,
比如說我們要獲取一秒的時間,則定時器1 的數值改變次數為1000/((1/16000000)*1024)
如果想要獲取更長的時間;比如說10秒,又要防止溢出,可以這樣寫
ISR(TIMER1_COMPA_vect)
{
seconds++;
if (seconds == 10)
{
seconds = 0;
readMySensor();
}
}
本文版权:
http://www.ndfweb.cn/news-737.html