Saya ingin mengatur timer untuk memanggil fungsi 800 kali per detik. Saya menggunakan Arduino Mega dan Timer3 dengan prescaler 1024. Untuk memilih faktor prescaler saya telah mempertimbangkan langkah-langkah berikut:
- Frekuensi CPU: 16MHz
- Resolusi pengatur waktu: 65536 (16 bit)
- Divide CPU freq oleh prescaler yang dipilih: 16x10 ^ 6/ 1024 = 15.625
- Bagilah sisanya melalui freq yang diinginkan 62500/800 = 19 .
- Masukkan hasil +1 di register OCR3.
Saya telah menggunakan tabel berikut untuk mengatur register TCCR3B:
Kesalahannya
Tidak mungkin untuk mengkompilasi kode. Ini adalah kesalahan yang dikembalikan oleh kompiler:
Servo \ Servo.cpp.o: Dalam fungsi '__vector_32': C: \ Program Files (x86) \ Arduino \ libraries \ Servo / Servo.cpp: 110: definisi ganda '__vector_32' AccelPart1_35.cpp.o: C: \ File Program (x86) \ Arduino / AccelPart1_35.ino: 457: pertama kali didefinisikan di sini c: / file program (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Menonaktifkan relaksasi: ini tidak akan berfungsi dengan banyak definisi
Kode
volatile int cont = 0;
unsigned long aCont = 0;
void setup()
{
[...]
// initialize Timer3
cli(); // disable global interrupts
TCCR3A = 0; // set entire TCCR3A register to 0
TCCR3B = 0; // same for TCCR3B
// set compare match register to desired timer count: 800 Hz
OCR3A = 20;
// turn on CTC mode:
TCCR3B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR3B |= (1 << CS30) | (1 << CS32);
// enable timer compare interrupt:
TIMSK3 |= (1 << OCIE3A);
// enable global interrupts:
sei();
}
void loop()
{
// Print every second the number of ISR invoked -> should be 100
if ( millis() % 1000 == 0)
{
Serial.println();
Serial.print(" tick: ");
Serial.println(contatore);
contatore = 0;
}
}
[...]
// This is the 457-th line
ISR(TIMER3_COMPA_vect)
{
accRoutine();
contatore++;
}
void accRoutine()
{
// reads analog values
}
Bagaimana mengatasi konflik dengan perpustakaan servo?
LARUTAN
Konflik diselesaikan dengan menggunakan kode berikut. Ini mengkompilasi tetapi penghitung yang terkait dengan timer 800Hz tidak menambah nilainya.
volatile int cont = 0;
void setup()
{
Serial.begin(9600);
// Initialize Timer
cli(); // disable global interrupts
TCCR3A = 0; // set entire TCCR3A register to 0
TCCR3B = 0; // same for TCCR3B
// set compare match register to desired timer count: 800 Hz
OCR3B = 20;
// turn on CTC mode:
TCCR3B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR3B |= (1 << CS30) | (1 << CS32);
// enable timer compare interrupt:
TIMSK3 |= (1 << OCIE3B);
// enable global interrupts:
sei();
Serial.println("Setup completed");
}
void loop()
{
if (millis() % 1000 == 0)
{
Serial.print(" tick: ");
Serial.println(cont);
cont = 0;
}
}
ISR(TIMER3_COMPB_vect)
{
cont++;
}
Karena masalah utama telah dipecahkan, saya telah membuat pertanyaan lain di sini terkait dengan masalah kenaikan kontra.
sumber
#define _useTimer3
garis, atau mencoba meletakkan#undef _useTimer3
tepat setelah menyertakan.Jawaban:
Sayangnya, perpustakaan Servo cadangan output membandingkan A (OCR * A) pada timer 1,3,4, dan 5 ketika dimuat pada mega arduino. Masing-masing hanya dapat memiliki satu ISR, jadi Anda tidak akan dapat menentukan TIMER Anda sendiri * _COMPA_vect saat Anda menggunakan Servo tanpa memodifikasi perpustakaan.
Namun, setiap pengatur waktu perangkat keras dilengkapi dengan 2 register perbandingan keluaran. Servo tidak mengklaim TIMER * _COMPB_vect menyela, sehingga mereka bebas untuk digunakan, dan bekerja persis sama.
Anda harus berhati-hati dengan aktivitas Servo libraries, itu bisa mengubah konfigurasi timer Anda. Urutan default pada megas adalah 5,1,3,4 dan untuk memberikan masing-masing 12 servos. Ini hanya mengkonfigurasi timer setelah diperlukan, jadi Anda harus baik-baik saja menggunakan timer 3 sampai Anda menambahkan servo ke-25.
Untuk mengubah kode Anda, gunakan OCR3B alih-alih OCR3A (Output Membandingkan Mendaftar) dan mengatur bit OCIE3B bukannya OCIE3A di TIMSK3 (Output Compare Interrupt Enable bits). Kemudian Anda mengubah fungsi ISR Anda menjadi
ISR(TIMER3_COMPB_vect){}
Mode CTC hanya bekerja dengan OCR3A, tetapi jika Anda mengatur TCNT3 ke 0 dalam fungsi interupsi Anda, Anda bisa mendapatkan perilaku serupa. Ingatlah untuk menghapus garis yang mengaktifkan mode CTC menggunakan WGM12.
sumber