Zamanlayıcı3'ü CTC modunda ayarlama - servo kitaplık ile çakışma


10

Saniyede 800 kez bir işlevi çağırmak için bir zamanlayıcı ayarlamak istiyorum. 1024 ölçekleyici ile Arduino Mega ve Timer3 kullanıyorum.

  • CPU frekansı: 16MHz
  • Zamanlayıcı çözünürlüğü: 65536 (16 bit)
  • 16x10 ^ 6 /: Seçilen ön ölçekleme bölün işlemci frekans 1024 = 15625
  • Kalanı istediğiniz frekans 62500/800 = 19'a bölün .
  • Sonucu + 1'i OCR3 kaydına koyun.

TCCR3B kayıtlarını ayarlamak için aşağıdaki tabloyu kullandım:

resim açıklamasını buraya girin

Hata

Kodu derlemek imkansızdır. Derleyici tarafından döndürülen hata:

Servo \ Servo.cpp.o: '__vector_32' fonksiyonunda: C: \ Program Dosyaları (x86) \ Arduino \ libraries \ Servo / Servo.cpp: 110: '__vector_32' çoklu tanımı AccelPart1_35.cpp.o: C: \ Program Dosyaları (x86) \ Arduino / AccelPart1_35.ino: 457: ilk önce burada tanımlanmıştır c: / program dosyaları (x86) / arduino / donanım / araçlar / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: Gevşemeyi devre dışı bırakma: çoklu tanımlarla çalışmaz

Kod

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
}

Servo kütüphanesi ile çatışma nasıl çözülür?

ÇÖZÜM

Çatışma aşağıdaki kod kullanılarak çözüldü. Derler, ancak 800Hz zamanlayıcı ile ilişkili sayaç değerini arttırmaz.

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++;
}

Ana sorun çözüldüğünden, burada karşı artım sorunuyla ilgili başka bir soru yarattım .


Programınızda servo kütüphanesini kullanıyor musunuz?
jfpoilpret

2
Servo.cpp olası da ISR (TIMER3_COMPA_vect)
TMa

1
Bunun yerine Timer1, 4 veya 5 kullanın.
Gerben

1
Servo, COMPA için megas üzerindeki 1,3,4 ve 5 zamanlayıcıları için kesme fonksiyonlarını tanımlar. COMPB kullanmaya ne dersiniz?
BrettAM

1
Haklısın . Sadece tüm zamanlayıcıları çalıyorlar. Sanırım #define _useTimer3çizgiyi kaldırarak kütüphaneyi biraz değiştirmelisiniz ya #undef _useTimer3da içerme işleminden hemen sonra bir tane koymayı deneyin .
Gerben

Yanıtlar:


4

Ne yazık ki, Servo kütüphanesi, bir arduino mega üzerine yüklendiğinde 1,3,4 ve 5 zamanlayıcılarında A (OCR * A) çıkış karşılaştırmasını ayırır. Her birinin yalnızca bir ISR'si olabilir, bu nedenle kütüphaneyi değiştirmeden Servo kullanırken kendi ZAMANLAYICI * _COMPA_vect'inizi tanımlayamazsınız.

Ancak, her donanım zamanlayıcı 2 çıkış karşılaştırma kayıtları ile donatılmıştır. Servo herhangi bir TIMER * _COMPB_vect kesintisi talep etmiyor, bu yüzden bunları kullanmak serbest ve aynı şekilde çalışıyor.

Servo kütüphanelerinin aktivitelerine dikkat etmelisiniz, zamanlayıcının yapılandırmasını değiştirebilir. Varsayılan sipariş megagazda 5,1,3,4'tür ve her 12 servoyu vermek içindir. Zamanlayıcıyı yalnızca ihtiyaç duyduktan sonra yapılandırır, bu yüzden 25. servoyu ekleyene kadar zamanlayıcı 3'ü kullanmanız gerekir.

Kodunuzu değiştirmek için OCR3A (Çıktı Karşılaştırma Kayıtları) yerine OCR3B kullanın ve TIMSK3'te (Çıktı Karşılaştırma Kesme Etkinleştir bitleri) OCIE3A yerine OCIE3B bitini ayarlayın. Sonra ISR işlevinizi ISR(TIMER3_COMPB_vect){}

CTC modu yalnızca OCR3A ile çalışır, ancak kesme fonksiyonunuzda TCNT3'ü 0 olarak ayarlarsanız benzer davranışlar elde edebilirsiniz. WGM12 kullanarak CTC modunu açan hattı kaldırmayı unutmayın.


Tamam teşekkürler! Sayacın artırılması hakkında herhangi bir tavsiye var mı?
UserK
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.