几个月前,我问,如果我定义了 ISR,为什么我的用 C 语言编写并闪存到 Arduino R3 Uno 上的 ATmega328p 的眨眼程序不断失败。我最终将问题范围缩小到我的 Makefile 的编写方式(我将其与
avr-gcc
和 avrdude
一起使用),并通过将代码复制粘贴到 Arduino IDE 中并使用内置的上传来解决这个问题。工具。
现在,我想回去准确理解 Makefile 失败的原因。我一直在浏览
avr-gcc
和 avrdude
的文档,并相信我已将问题范围缩小到我正在写入的内存区域。我正在使用的示例 C 项目如下:
int main(void)
{
// set the data direction for the pin connected to
// onboard LED
DDRB |= _BV(DDB5);
PORTB |= _BV(PORTB5);
// no-op loop
while (1) ;;
// keep compiler happy
return 0;
}
程序故意简单;它只是打开板载 LED 并使其保持亮起状态。此时,使用以下 make 文件进行刷新就可以正常工作了:
AVRFLAGS = -F -v -p m328p -c arduino -P /dev/ttyACM0 -U flash:w:blink.hex
default: blink.elf
avr-objcopy -O ihex blink.elf blink.hex
blink.o:
avr-gcc -g -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o blink.o blink.c
blink.elf: blink.o
avr-gcc -o blink.elf blink.o
flash:
sudo avrdude ${AVRFLAGS} blink.hex
clean:
rm -rf *.o *.hex *.elf
但是,当我将 ISR 添加到文件顶部时:
ISR (TIMER1_COMPA_vect)
{
PORTD ^= _BV(PORTB5);
}
并尝试闪光,一切都崩溃了。我在使用和不使用定时器/计数器 1 设置代码(出于演示目的而在此处进行了编辑)的情况下都尝试过此操作,并且不认为它会影响闪存的成功。我已经在其他程序中使用了这个完全相同的 ISR——以及与定时器/计数器 1 完全相同的设置代码——只要我使用 Arduino IDE 内置工具来刷新它们,就可以正常工作;否则,Arduino Uno 会闪烁表明正在接收数据,然后板载 LED 开始闪烁并持续闪烁。每当任何程序刷新不佳时,就会出现完全相同的闪烁模式。我用 -j .text -j .data
、
.eeprom
和其他选项进行编译,但没有效果。我只是想知道为什么会失败。
-mmcu=atmega328p
传递到链接阶段。如果没有此选项,则不会添加 CRT 和中断向量表。虽然您只有一个
main()
函数,但它从地址 0(重置向量)开始,并且一切似乎都正常。由于您添加了 ISR,现在它的代码位于地址 0。对于 GNU Make,您可以使用
COMPILE.c
和
LINK.c
内置变量来获取正确的编译和链接命令。