Mengatur timer3 dalam mode CTC - konflik dengan pustaka servo

10

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:

masukkan deskripsi gambar di sini

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.

UserK
sumber
Apakah Anda menggunakan perpustakaan servo di progam Anda atau tidak?
jfpoilpret
2
Servo.cpp probable juga melakukan ISR (TIMER3_COMPA_vect)
TMa
1
Cukup gunakan Timer1, 4 atau 5 sebagai gantinya.
Gerben
1
Servo mendefinisikan fungsi interupsi untuk timer 1,3,4 dan 5 pada megas untuk COMPA. Bagaimana kalau menggunakan COMPB?
BrettAM
1
Anda benar . Mereka hanya memonopoli semua penghitung waktu. Saya kira Anda harus mengubah perpustakaan sedikit dengan menghapus #define _useTimer3garis, atau mencoba meletakkan #undef _useTimer3tepat setelah menyertakan.
Gerben

Jawaban:

4

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.

BrettAM
sumber
Ok terima kasih! Adakah saran tentang penambahan penghitung ?
UserK