Avr-gcc: таймер / счетчик прерывает конфликт с UART? - PullRequest
2 голосов
/ 10 августа 2011

Пожалуйста, рассмотрите следующий пример (пробовал в Arduino IDE 0022, Ubuntu 11.04, Arduino AtMEGA 2560), где я пытаюсь запустить прерывание таймера / счетчика и одновременно использовать класс Arduino Serial:

volatile uint8_t sreg;

// Timer 0 interrupt routine
ISR(TIMER0_COMPA_vect, ISR_NAKED)
{
  sreg = SREG;  /* Save global interrupt flag */
  cli(); /* Disable interrupts */

  digitalWrite(34, not((bool)digitalRead(34)));

  SREG = sreg; /* Restore global interrupt flag */
  reti(); // must for ISR: return and enable interrupt  
}

void setup() {
  pinMode(13, OUTPUT);
  pinMode(34, OUTPUT);
  Serial.begin(115200);
  Serial.println("Hello from setup");
  delay(200); 
}

void loop() {
  digitalWrite(13, HIGH);
  Serial.println("Hello from loop: A");

  digitalWrite(13, LOW);
  delay(200); 

  digitalWrite(13, HIGH);
#if 1 // register update part
  cli(); // disable interrupts
  GTCCR = 0b10000011; // halt timers
  // set up Timer/Counter 0
  TCCR0A = 0b00000010; // CTC; normal mode (don't use output pin)
  TCCR0B = 0b00000101; // no force output; CTC; ... and clock select: prescale 1024
  TCNT0 = 0; // init the actual counter variable
  TIMSK0 = 0b00000010; // enable (only) Compare Match A Interrupt
  OCR0A = 125; //the top value, to which the running counter is compared to

  GTCCR = 0b00000000;
  sei(); // Enable interrupts once registers have been updated

  digitalWrite(13, LOW);
  delay(200); 
#endif

  digitalWrite(13, HIGH);
  Serial.println("Hello from loop: B");

  digitalWrite(13, LOW);
  delay(200);
}

Как пример, распечатка через серийный номер будет:

Hello from setup
Hello from loop: A
Hello from loop: B
Hello from loop: A
Hello from loop: B

... и тогда вся обработка прекратится (на что указывает отсутствие действия на выводах 13 и 34 светодиода); Я думаю, это то, что вы бы назвали BSOD в мире чипов :) Внешне остановка происходит, как только запускается процедура ISR в первый раз.

Если вы удалите «часть обновления регистра», то последовательная распечатка будет выполняться вечно, как и ожидалось, а также (как и ожидалось), ISR не работает. Однако, если «часть обновления регистра» оставлена, а две строки «Serial.println(...» прокомментированы вместо этого - тогда программа печатает только «Hello from setup» - но прерывание действительно выполняется (о чем свидетельствуют импульсы на выводе 34) ,

Что, по-видимому, говорит мне, что вы не можете запустить таймер ISR и UART на ATMega2560 одновременно - что глупо, учитывая, что ранее я с успехом использовал такой же подход на ATMega328.

Итак, я хочу узнать, является ли принципиально невозможным то, что я хочу сделать (иметь последовательную распечатку и импульсы контактов) с этой архитектурой - или я просто что-то упустил в настройке?

Заранее спасибо за любые ответы, Ура!

(Просто хотел заметить, что этот класс Serial на самом деле работает с определением класса в HardwareSerial.cpp в пакете IDE Arduino; и этот класс определяет процедуры приема прерываний USART; подумал, что это может быть проблемой - но опять же, я использовал тот же подход в ATMega328, где я видел, как это работает ..)

РЕДАКТИРОВАТЬ: Репост на Avr-gcc: прерывания таймера / счетчика конфликтуют с UART? - Arduino Forum

1 Ответ

0 голосов
/ 10 августа 2011

Хорошо, я просто повторно запустил один и тот же код на ATMega168 и ATMega328 - и он работает, как и ожидалось (основной цикл с Serial.write и подпрограмма ISR работают);поэтому это должна быть специфическая проблема ATMEGA2560 - а не проблема программирования в целом ...

РЕДАКТИРОВАТЬ: Краткий ответ - используйте другой таймер, потому что Timer0 уже используется API Arduino.

(, подробнее см. В репосте на форуме Arduino ).

Ура!

...