请考虑以下示例(在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
答案 0 :(得分:0)
好的,我只是在ATMega168和ATMega328上重新运行相同的代码 - 它按预期工作(主要循环Serial.write
和ISR例程正在运行);所以它必须是ATMEGA2560特定的问题 - 而不是一般的编程问题......
编辑:简短的回答是 - 使用不同的计时器,因为Arduino API已经在使用Timer0。
(了解更多信息,请参阅Arduino论坛上的重新发布)。
干杯!