Avr-gcc:定时器/计数器中断与UART冲突



请考虑以下示例(在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

…然后所有处理将停止(LED引脚13和34都没有动作表示);我猜,这就是你在芯片世界中所说的BSOD:)表面上,一旦ISR例程第一次启动,中断就会发生。

如果您取出"寄存器更新部分",那么串行打印输出将永远运行,正如预期的那样-而且(如预期的那样),没有ISR运行。然而,如果"寄存器更新部分"留下,而两个"Serial.println(..."行被注释,那么程序只打印"Hello from setup",但是中断确实运行(从引脚34上的脉冲可以证明)。

这似乎告诉我,你不能同时在ATMega2560上运行定时器ISR和UART -这是愚蠢的,考虑到我以前在ATMega328上成功地使用了同样的方法。

所以,我在徘徊是否我想做的(有串行打印输出和引脚脉冲)是根本不可能与这种架构-或者我只是错过了一些设置?

提前感谢任何答案,干杯!

(只是想指出,这个串行类实际上在Arduino IDE包中的HardwareSerial.cpp中的类定义上运行;这个类定义了接收USART中断例程;我认为这可能是问题-但再次,我在ATMega328中使用了相同的方法,在那里我看到它的工作…)

编辑:转发Avr-gcc:定时器/计数器中断与UART冲突?- Arduino论坛

好吧,我只是在ATMega168和ATMega328上重新运行了相同的代码-它按预期工作(Serial.write的主循环和ISR例程都在运行);所以这一定是ATMEGA2560特有的问题,而不是一般编程的问题…

编辑:简短的答案是-使用不同的计时器,因为Timer0已经被Arduino API使用。

(更多信息,参见Arduino论坛上的转发)。

干杯!

最新更新