【发布时间】:2023-06-14 02:22:01
【问题描述】:
我正在尝试让我的 Arduino Uno R3 上的两个 LED 闪烁(用于学习目的)。我使用 avr-gcc 和 avrdude 来编译和加载我的程序。
我在 main 的 while 循环中使第一个闪烁。我正在尝试使用 Timer0 打开和关闭第二个。
首先,有效的代码:
#include <avr/io.h>
#include <util/delay.h>
int main() {
TCCR0B |= (1 << CS02) | (1 << CS00);
TIMSK0 |= (1 << TOIE0);
DDRD = 1 << PD3;
DDRB = 1 << PB5;
PORTB = 0;
while(1) {
PORTD ^= 1 << PD3;
_delay_ms(500);
}
return 0;
}
正如预期的那样,这段代码让我的 LED 闪烁,然后每秒重新开始。我也在设置(但不使用)第二个 LED 和计时器。
现在,当我添加一个中断向量时,问题就开始了:
...
#include <avr/interrupt.h>
volatile uint8_t intrs;
ISR(TIMER0_OVF_vect) {
if (++intrs >= 62) { // meant to execute every second
PORTB ^= (1 << PB5);
intrs = 0;
}
}
int main() {
intrs = 0;
... // old setup
sei();
while(1) { ... }
}
现在,所有 LED 都没有闪烁。更奇怪的是,当我删除 sei() 时,它们都不会眨眼。我发现让第一个 LED 再次闪烁的唯一方法是注释掉 ISR 声明或将其标记为 ISR_NAKED。
那么,什么给了?
PS:我使用 makefile 来编译和加载。当我运行它时,它看起来像这样:
$ make
avr-gcc -c -Os -DF_CPU=16000000UL -mmcu=atmega328p -Wall -Wextra main.c
avr-gcc -o prog.elf main.o
avr-objcopy -O ihex -R .eeprom prog.elf prog.hex
avrdude -C/etc/avrdude.conf -v -V -carduino -patmega328p -P/dev/ttyACM0 -b115200 -D -Uflash:w:prog.hex
.. # avrdude logs
【问题讨论】:
-
如果你设置了一个 0.5Hz 的定时器(TIMER1 可以做到这一点,请参阅8bit-era.cz/arduino-timer-interrupts-calculator.html),这样中断就不会经常被调用并使用
if (++intrs >= 2),然后会发生什么?顺便说一句,您的 LED 上有合适的电阻吗?只是检查。 -
还是不行;我使用了 1Hz 计时器,因为那是我真正想要的,并且摆脱了
intrs。现在两个 LED 都很暗,而且它们似乎每隔一段时间就会非常短暂地闪烁。是的,我只是在它们后面加了一个 220 欧姆的电阻。 -
刚刚想到
intrs,循环一直将intrs设置为0,所以中断可能永远不会看到++intrs >= 62(循环比62Hz中断调用快得多),但你说即使不使用intrs,它也不起作用。嗯。感觉好像我们在这里遗漏了一些非常明显的东西,但我没有看到。 -
问题似乎不在于程序逻辑。即使添加一个愚蠢的 ISR(例如 INT0_vect 或其他)似乎也会破坏程序 - 将其注释掉使其工作。
-
我看不出有什么问题。也许您可以检查此处的示例是否有效:microchipdeveloper.com/8avr:interrupts-mega-configuration#toc11 并从中恢复,尽管它看起来与您已经尝试过的非常相似。
标签: avr arduino-uno atmega avr-gcc