Встановлення таймера3 в режимі CTC - конфлікт із сервісною бібліотекою


10

Я хотів би встановити таймер, щоб викликати функцію 800 разів за секунду. Я використовую Arduino Mega і Timer3 з дозволом 1024. Для вибору фактора дозволення я розглянув наступні кроки:

  • Частота процесора: 16 МГц
  • Дозвіл таймера: 65536 (16 біт)
  • Розділити частоту процесора обраного предделителя: 16x10 ^ 6 / тисячі двадцять чотири = 15625
  • Решту розподіліть на бажану частоту 62500/800 = 19 .
  • Поставте результат + 1 в регістр OCR3.

Я використовував наступну таблицю для встановлення реєстрів TCCR3B:

введіть тут опис зображення

Помилка

Неможливо скласти код. Це помилка, повернута компілятором:

Servo \ Servo.cpp.o: У функції '__vector_32': C: \ Програмні файли (x86) \ Arduino \ бібліотеки \ Servo / Servo.cpp: 110: кратне визначення '__vector_32' AccelPart1_35.cpp.o: C: \ Програмні файли (x86) \ Arduino / AccelPart1_35.ino: 457: тут вперше визначено c: / програмні файли (x86) / arduino / hardware / tools / avr / bin /../ lib / gcc / avr / 4.3.2 /. ./../../../avr/bin/ld.exe: вимкнення розслаблення: воно не працюватиме з кількома визначеннями

Код

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
}

Як вирішити конфлікт із бібліотекою сервоприводів?

РІШЕННЯ

Конфлікт вирішується за допомогою наступного коду. Він компілюється, але лічильник, пов'язаний з таймером 800 Гц, не збільшує значення.

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

Оскільки основна проблема вирішена, я створив тут ще одне питання, пов’язане з проблемою збільшення лічильника.


Ви використовуєте сервісну бібліотеку у своїй програмі чи ні?
jfpoilpret

2
Servo.cpp ймовірний також ISR (TIMER3_COMPA_vect)
TMa

1
Просто використовуйте Timer1, 4 або 5 замість цього.
Гербен

1
Серво визначає функції переривань для таймерів 1,3,4 та 5 на мегаси для COMPA. Як щодо використання COMPB?
BrettAM

1
Ви маєте рацію . Вони просто розвішують усіх таймерів. Я думаю, вам доведеться трохи змінити бібліотеку, видаливши #define _useTimer3рядок, або спробуйте поставити #undef _useTimer3праворуч після включення.
Гербен

Відповіді:


4

На жаль, вихідні запаси бібліотеки Servo порівнюють A (OCR * A) на таймерах 1,3,4 та 5 при завантаженні на аргуїно-мега. Кожен може мати лише один ISR, тому ви не зможете визначити свій власний TIMER * _COMPA_vect під час використання сервоприводу, не змінюючи бібліотеку.

Однак кожен апаратний таймер обладнаний двома реєстраторами порівняння вихідних даних. Сервопристрій не вимагає жодних перерв TIMER * _COMPB_vect, тому вони вільні у використанні та працюють точно так само.

Ви повинні стежити за діяльністю бібліотек Servo, це може змінити конфігурацію вашого таймера. Замовлення за замовчуванням на мегас - 5,1,3,4 і давати кожен 12 сервоприводів. Він налаштовує таймер лише після того, як він потребує, тому вам слід добре використовувати таймер 3, поки ви не додасте 25-й сервопривід.

Щоб змінити свій код, використовуйте OCR3B замість OCR3A (регістри порівняння вихідних даних) і встановіть біт OCIE3B замість OCIE3A в TIMSK3 (біт увімкнення переривання порівняння). Тоді вам потрібно змінити функцію ISR на ISR(TIMER3_COMPB_vect){}

Режим CTC працює лише з OCR3A, але якщо встановити TCNT3 у 0 у функції переривання, ви можете отримати подібну поведінку. Не забудьте видалити рядок, що перетворює режим CTC на використання WGM12.


Добре, дякую! Будь-яка порада щодо збільшення лічильника ?
UserK
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.