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

Posted

技术标签:

【中文标题】Avr-gcc:定时器/计数器中断与 UART 冲突?【英文标题】:Avr-gcc: Timer/counter interrupts conflicting with UART? 【发布时间】:2011-08-10 06:31:17 【问题描述】:

请考虑以下示例(在 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 上使用过相同的方法。

所以,我想知道我想做的事情(串行打印输出和引脚脉冲)在这种架构下是否根本不可能 - 或者我只是在设置中遗漏了一些东西?

提前感谢您的任何回答, 干杯!

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

编辑:转发Avr-gcc: Timer/counter interrupts conflicting with UART? - Arduino Forum

【问题讨论】:

【参考方案1】:

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

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

有关更多信息,请参阅 Arduino 论坛上的转贴)。

干杯!

【讨论】:

以上是关于Avr-gcc:定时器/计数器中断与 UART 冲突?的主要内容,如果未能解决你的问题,请参考以下文章

外部中断和计时器要点

定时器计数器中断

实验1定时与中断接口程序设计

AVR单片机教程——定时器中断

如何在 avr-gcc 中定义定时器

STM32怎么接收不定长串口数据