Установка таймера3 в режиме CTC - конфликт с серво-библиотекой

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

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

Я использовал следующую таблицу для установки регистров TCCR3B:

введите описание изображения здесь>> </p>

<p> <strong> Ошибка </strong> </p>

<p> Невозможно скомпилировать код. Это ошибка, возвращаемая компилятором: </p>

<blockquote>
  <p> Servo \ Servo.cpp.o: В функции '__vector_32': C: \ Program Files
  (x86) \ Arduino \ libraries \ Servo /Servo.cpp: 110: множественное определение
  '__vector_32' AccelPart1_35.cpp.o: C: \ Program Files
  (x86) \ Arduino /AccelPart1_35.ino: 457: сначала определяется здесь c: /program
  файлы
  (X86) /Arduino /оборудование /инструменты /АРН /бен /../Библиотека /GCC /АРН /4.3.2 /../../../../АВР /бен /ld.exe:
  Отключение релаксации: он не будет работать с несколькими определениями </p>
</blockquote>

<p> <strong> Код </strong> </p>

<pre><code>volatile int cont = 0;
unsigned long aCont = 0;
void setup ()
{
 [...]
  //инициализировать Timer3
  кли (); //отключить глобальные прерывания
  TCCR3A = 0; //установить полный регистр TCCR3A в 0
  TCCR3B = 0; //тот же для TCCR3B

  //установить сравнительный регистр соответствия на требуемый таймер: 800 Гц
  OCR3A = 20;
  //включить режим CTC:
  TCCR3B | = (1 <WGM12);
  //Устанавливаем биты CS10 и CS12 для предикатора 1024:
  TCCR3B | = (1 <CS30) | (1 <CS32);
  //включить прерывание сравнения таймера:
  TIMSK3 | = (1 <OCIE3A);
  //включить глобальные прерывания:
  SEI ();
}

void loop ()
{
 //Напечатайте каждую секунду количество вызываемых ISR -> должно быть 100
 if (millis ()% 1000 == 0)
 {
   Serial.println ();
   Serial.print (

Как разрешить конфликт с серво-библиотекой?

Решение

Конфликт разрешен с использованием следующего кода. Он компилируется, но счетчик, связанный с таймером 800 Гц, не увеличивает его значение.

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
}

Поскольку основная проблема решена, я создал еще один вопрос здесь , связанных с проблемой приращения счетчика.

8 голосов | спросил UserK 9 TueEurope/Moscow2014-12-09T05:20:08+03:00Europe/Moscow12bEurope/MoscowTue, 09 Dec 2014 05:20:08 +0300 2014, 05:20:08

1 ответ


3

К сожалению, библиотека Servo резервирует вывод сравнения A (OCR * A) на таймерах 1,3,4 и 5 при загрузке на arduino mega. У каждого может быть только один ISR, поэтому вы не сможете определить свой собственный TIMER * _COMPA_vect, пока вы используете Servo без изменения библиотеки.

Однако каждый аппаратный таймер оснащен 2 выходными сравнительными регистрами. Servo не требует прерываний 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.

ответил BrettAM 11 ThuEurope/Moscow2014-12-11T03:46:17+03:00Europe/Moscow12bEurope/MoscowThu, 11 Dec 2014 03:46:17 +0300 2014, 03:46:17

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132