一、Arduino定時器簡介
Arduino UNO有三個定時器,分別是timer0,timer1和timer2。每個定時器都有一個計數器,在計時器的每個時鐘週期遞增。當計數器達到存儲在比較匹配寄存器中指定值時觸發CTC定時器中斷。一旦定時器計數器達到該值,它將在定時器時鐘的下一個定時器上清零(復位爲零),然後它將繼續再次計數到比較匹配值。通過選擇比較匹配值並設置定時器遞增計數器的速度,你可以控制定時器中斷的頻率。
下面引出定時器各個寄存器的配置關係。
二、定時器基本概念
1、預分頻係數與比較匹配器
Arduino時鐘以16MHz運行。計數器的一個刻度值表示1 / 16,000,000秒(~63ns),跑完1s需要計數值16,000,000。
1、Timer0和timer2是8位定時器,可以存儲最大計數器值255。
2、Timer1是一個16位定時器,可以存儲最大計數器值65535。
一旦計數器達到其最大值,它將回到零(這稱爲溢出)。因此,需要對時鐘頻率進行分頻處理,即預分頻器。通過預分頻器控制定時計數器的增量速度。預分頻器與定時器的計數速度如下:
定時器速度(HZ) = Arduino時鐘速度(16MHz) / 預分頻器係數
因此,1預分頻器將以16MHz遞增計數器,8預分頻器將在2MHz遞增,64預分頻器= 250kHz,依此類推。
三個定時器的預分頻係數配置如表:
我將在下一步中解釋CS12,CS11和CS10的含義。
現在您可以用以下步驟計算中斷頻率。以下公式:
中斷頻率(Hz)=(Arduino時鐘速度16MHz)/(預分頻器*(比較匹配寄存器+ 1))
重新排列上面的等式,給出你想要的中斷頻率,你可以求解比較匹配寄存器值:
比較匹配寄存器= [16,000,000Hz /(預分頻器*所需的中斷頻率)] - 1
記住,當你使用定時器0和2時,這個數字必須小於256,對於timer1小於65536。
所以如果你想每秒一次中斷(頻率爲1Hz):
比較匹配寄存器= [16,000,000 /(預分頻器 * 1)] -1
預分頻器爲1024,你得到:
比較匹配寄存器= [16,000,000 /(1024 * 1)] -1 = 15,624
因爲256 <15,624 <65,536,你必須使用timer1來實現這個中斷。
定時器0:
Timer0是一個8位定時器。
在Arduino世界中,timer0用於定時器功能,如delay(),millis()和micros()。如果更改timer0寄存器,這可能會影響Arduino定時器功能。 所以你應該知道你在做什麼。
定時器1:
Timer1是一個16位定時器。
在Arduino世界中,Servo庫492在Arduino Uno上使用timer1(Arduino Mega上的timer5)。
定時器2:
Timer2是一個8bit定時器,如timer0。
在Arduino工作中,tone()函數使用timer2。
Timer3,Timer4,Timer5:
定時器3,4,5僅適用於Arduino Mega主板。 這些定時器都是16位定時器。
三、定時器配置代碼
int toggle0,toggle1,toggle2;
void setup(){
cli();////關閉全局中斷
//設置定時器0爲10kHz(100us)
TCCR0A = 0;//將整個TCCR0A寄存器設置爲0
TCCR0B = 0;//將整個TCCR0B寄存器設置爲0
TCNT0 = 0;//將計數器值初始化爲0
//設置計數器爲10kHZ,即100us
OCR0A = 24;//比較匹配寄存器= [16,000,000Hz /(預分頻器*所需中斷頻率)] - 1
//比較匹配寄存器=24,中斷間隔=100us即中斷頻率10khz
TCCR0A |= (1 << WGM01);//打開CTC模式
TCCR0B |= (1 << CS01) | (1 << CS00); //設置CS01位爲1,CS00位爲1(64倍預分頻)
TIMSK0 |= (1 << OCIE0A);//啓用定時器比較中斷
//設置定時器1爲1kHz
TCCR1A = 0;//將整個TCCR1A寄存器設置爲0
TCCR1B = 0;//將整個TCCR1B寄存器設置爲0
TCNT1 = 0;//將計數器值初始化爲0
//設置計數器爲1kHZ,即1ms
OCR1A = 1999;// = (16*10^6)/(1000*8) - 1 (must be <65536)
TCCR1B |= (1 << WGM12);//打開CTC模式
TCCR1B |= (1 << CS11);//設置CS11位爲1(8倍預分頻)
TIMSK1 |= (1 << OCIE1A);
//設置定時器2爲8kHz
TCCR2A = 0;// set entire TCCR2A register to 0
TCCR2B = 0;// same for TCCR2B
TCNT2 = 0;//initialize counter value to 0
// set compare match register for 8khz increments
OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
// turn on CTC mode
TCCR2A |= (1 << WGM21);//打開CTC模式
// Set CS21 bit for 8 prescaler
TCCR2B |= (1 << CS21);
// enable timer compare interrupt
TIMSK2 |= (1 << OCIE2A);
sei();//打開全局中斷
}
//中斷0服務函數
ISR(TIMER0_COMPA_vect){
//產生頻率爲10kHz / 2 = 5kHz的脈衝波
if(toggle0){
digitalWrite(8,HIGH);
toggle0 = 0;
}
else{
digitalWrite(8,LOW);
toggle0 = 1;
}
}
ISR(TIMER1_COMPA_vect){// timer1中斷2Hz切換引腳13(LED)
//產生頻率爲2Hz / 2 = 1Hz的脈衝波
if(toggle1>=500)
digitalWrite(13,HIGH);
if(toggle1<=500)
digitalWrite(13,LOW);
toggle1 += 1;
if(toggle1 >= 1000)
toggle1 = 0;
}
ISR(TIMER2_COMPA_vect){// timer1中斷8kHz切換引腳9
//產生頻率爲8kHz / 2 = 4kHz的脈衝波
if(toggle2){
digitalWrite(9,HIGH);
toggle2 = 0;
}
else{
digitalWrite(9,LOW);
toggle2 = 1;
}
}
void loop(){
}