我正在尝试学习 AVR C,并且正在修补 atmega328p 微控制器。我正在 Linux Mint 上使用 avr-gcc 工具链来编译我的代码并将其刷新到 Arduino 板。
所以我尝试使用函数调用来闪烁两个 LED 灯。我制作了两个函数 - 一个用于连接到 Arduino 板的引脚 7 的闪烁 LED,另一个用于连接到 Arduino 板的引脚 13 的闪烁 LED。
这些功能正在运行,但是当我修改代码时,我注意到一个奇怪的行为。这些函数按照它们定义的顺序在 main() 之外被调用和执行;而不是按照从int main()
内部调用它们的顺序。这是我的代码
#include <avr/io.h>
#include <util/delay.h>
void blinkPin13() {
while(1) {
DDRB = DDRB | (1 << DDB5);
PORTB = PORTB | (1 << PORTB5);
_delay_ms(5000);
PORTB = PORTB & ~(1 << PORTB5);
_delay_ms(500);
}
}
void blinkPin7() {
while(1) {
DDRD = DDRD | (1 << DDD7);
PORTD = PORTD | (1 << PORTD7);
_delay_ms(1000);
PORTD = PORTD & ~(1 << PORTD7);
_delay_ms(500);
}
}
int main(void) {
blinkPin7();
blinkPin13();
return 0;
}
这是用于编译和刷新代码的 makefile
default:
avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c
avr-gcc -o led.bin led.o
avr-objcopy -O ihex -R .eeprom led.bin led.hex
sudo avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex
因此,当我将上述代码刷新到 Arduino 板时,即使首先调用函数 blinkPin7()
,连接到引脚 13 的 LED 也会闪烁。我注意到函数的执行顺序始终对应于函数在 main() 外部定义的顺序,而不是对应于从 main() 内部调用函数的顺序。为什么会这样?
avr-gcc -o led.bin led.o
链接阶段没有通过-mmcu=atmega328p
。如果没有此选项,您应该会收到如下所示的 ld 错误:
avr:103 architecture of input file `led.o' is incompatible with avr output
意味着您没有目标 MCU。使用正确的链接器脚本,main() 从地址 0(重置向量)开始,一切都会正常工作。但是如果链接器脚本错误,那么现在首先出现的任何函数都将位于地址 0 处,并且将按照您观察到的情况开始执行。添加目标 MCU 即可解决问题:
avr-gcc -o led.bin led.o -mmcu=atmega328p