|
|
发表于 2013-12-4 14:01:39
|
显示全部楼层
不懂 pPio->PIO_SODR=PIO_PB27; 的用法
digitalWrite() 使用 Timer0 的 震盪頻率, 是不是因此比較起來慢了些? 請先進們解惑一下。
/*
***********************************************************
Digital pins:
 Pins 0 – 7: PORT D [0:7]
 Pins 8 – 13: PORT B [0:5]
 Pins 14 – 19: PORT C [0:5] (Arduino analog pins 0 – 5)
 digital pins 0 and 1 are RX and TX for serial communication
 digital pin 13 connected to the base board LED
By Daniel Lu 2013'11'30
https://www.youtube.com/user/dan59314?feature=watch
http://dan59314.myweb.hinet.net
http://www.facebook.com/rasvector/
ATMEGA 328 晶片,振盪頻率為 16M Hz, 每秒 16*10^6, 每一次 ~ 63 ns(微秒)
1. 有3個Timer
Timer 0: millis() and delay().. 所使用的參考Timer
8 bit 計數暫存器(0~255)
Timer 1: Servo library 所使用
16 bit 計數暫存器(0~65535)
Timer 2:
8 bit 計數暫存器(0~255)
EX:若要讓 Timer2 每一秒中斷一次,則
Timer2有16bit,可以計數 0 ~ 65535, 計數器滿了則中斷一次, 因此
每次中斷間隔時間為 1秒 / 16*10^6次 x 65535 ~= 4 ms
因為 16MHz 太快,如果要每一秒中斷一次,則必須調降16M Hz,因此有 preScaler
---------------------------------------------------------------
CS02 CS01 CS00 功能
0 0 0 無計數功能
0 0 1 無 PreScale
0 1 0 PreScale=8 (Clock / 8)
0 1 1 PreScale=64
1 0 0 PreScale=256
1 0 1 PreScale=1024
1 1 0 在 T0 pin 使用外部 振盪源,下緣觸發 (falling edge)
1 1 1 在 T0 pin 使用外部 振盪源,上緣觸發 (rising edge)
---------------------------------------------------------------
所以如果要每秒一次中斷(暫存器計數 65536), 則每秒必須震盪 65536 次
65535 Hz = 16M Hz / scale ---> scale ~= 244.1406, PreScale 必須至少 >= 256 ,在此我們選 1024
-> (CS02=1, CS01=0, CS00=1) #設定一
因此,公式如下:
interrupt frequency (Hz) = (Arduino clock speed 16,000,000Hz) / (prescaler * (compare match register + 1))
每秒中斷一次
1 Hz = (16M Hz) / (1024 * OCRx) -> OCRx = 16x10^6 / 1024 -1 = 15624
-> #設定二 : Timer1 的中斷計數值 OCR1A = 15624
由 設定一,設定二可設定 Timer1 如下:
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0, 初始化 Timer0 Count (0~65535, 暫存器16bit)
OCR1A = 15624; // 中斷計數值 設定二 (16*10^6) / (1*1024) - 1 (must be <65536)
TCCR1B |= (1 << WGM12); // 啟動 CTC 模式
TCCR1B |= (1 << CS12) | (1 << CS10); // 設定 PreScale = 1024,設定一
TIMSK1 |= (1 << OCIE1A); // 啟動 計數值中斷
完成以上設定後, 就可以讓 Timer1 每秒 (計數值 15624 振盪次數) 產生一次中斷
***********************************************************
*/
//storage variables
boolean toggle0 = 0; // 紀錄 Timer0 的狀態
boolean toggle1 = 0; // 紀錄 Timer1 的狀態
boolean toggle2 = 0;
void setup_Timer()
{//Timer0 設定 -------------------------------------------------------------
TCCR0A = 0;// set entire TCCR0A register to 0, TCCRxA x代表 Timer 編號 0~2
TCCR0B = 0;// same for TCCR0B
TCNT0 = 0;//initialize counter value to 0 , 初始化 Timer0 Count (0~255, 暫存器8bit)
// set compare match register for 2khz increments
OCR0A = 124;// = (16*10^6) / (2000*64) - 1 (must be <256), 中斷計數值,一但到達此值,則產生中斷
TCCR0A |= (1 << WGM01);// turn on CTC mode
TCCR0B |= (1 << CS01) | (1 << CS00);// Set CS01 and CS00 bits for 64 prescaler
TIMSK0 |= (1 << OCIE0A);// enable timer compare interrupt
//Timer1 設定 -------------------------------------------------------------
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; //initialize counter value to 0, 初始化 Timer0 Count (0~65535, 暫存器16bit)
// set compare match register for 1hz increments
OCR1A = 15624; // = (16*10^6) / (1*1024) - 1 (must be <65536)
TCCR1B |= (1 << WGM12);// turn on CTC mode, 注意:不是 TCRR1A
TCCR1B |= (1 << CS12) | (1 << CS10);// Set CS12 and CS10 bits for 1024 prescaler
TIMSK1 |= (1 << OCIE1A);// enable timer compare interrupt
//Timer2 設定 -------------------------------------------------------------
TCCR2A = 0;// set entire TCCR2A register to 0
TCCR2B = 0;// same for TCCR2B
TCNT2 = 0;//initialize counter value to 0, 初始化 Timer0 Count (0~255, 暫存器8bit)
// set compare match register for 8khz increments
OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
TCCR2A |= (1 << WGM21);// turn on CTC mode
TCCR2B |= (1 << CS21); // Set CS21 bit for 8 prescaler
TIMSK2 |= (1 << OCIE2A);// enable timer compare interrupt
}
void setup(){
//set pins as outputs
pinMode(8, OUTPUT); //Timer0
pinMode(13, OUTPUT);
pinMode(9, OUTPUT);
cli(); //關閉 Interrupts 可用 cli(), sei() 在 loop 中, 暫時停用或啟用 interrupt
setup_Timer();
sei(); //啟動 Interrupts
}//end setup
ISR(TIMER0_COMPA_vect){//timer0 interrupt 2kHz toggles pin 8
//generates pulse wave of frequency 2kHz/2 = 1kHz (takes two cycles for full wave- toggle high then toggle low)
if (toggle0){
digitalWrite(8,HIGH);
toggle0 = 0;
}
else{
digitalWrite(8,LOW);
toggle0 = 1;
}
}
ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
if (toggle1){
digitalWrite(13,HIGH);
toggle1 = 0;
}
else{
digitalWrite(13,LOW);
toggle1 = 1;
}
}
ISR(TIMER2_COMPA_vect){//timer1 interrupt 8kHz toggles pin 9
//generates pulse wave of frequency 8kHz/2 = 4kHz (takes two cycles for full wave- toggle high then toggle low)
if (toggle2){
digitalWrite(9,HIGH);
toggle2 = 0;
}
else{
digitalWrite(9,LOW);
toggle2 = 1;
}
}
void loop(){
//do other things here
}
|
|