我正在尝试直接使用 C 代码对 ATmega328P 微控制器(在 Az-delivery arduino 卡上)进行编程。
当我运行一个简单的闪烁程序以测试计算机和开发板之间的编译和通信时,我在闪烁内置 LED 时遇到了任何问题。
下面是完美运行的代码:
#include <avr/io.h>
#include <util/delay.h>
int main(void){
DDRB |= (1 << DDB5);
while(1){
PORTB |= 1 << PORTB5;
_delay_ms(500);//0.35
PORTB &= ~(1 << PORTB5);
_delay_ms(500);
}
}
(十六进制文件:
:10000000259A2D9A2FEF89E698E121508040904063
:10001000E1F700C000002D982FEF89E698E121500C
:0C00200080409040E1F700C00000EBCFF2
:00000001FF
)
当我开始编写简单的函数时,就会出现问题。我的 LED 快速闪烁 3 次,然后在 1 秒内关闭,并且一遍又一遍地重复......
我试图找出问题所在。因此,为了做到这一点,我逐行删除了所有内容...当我尝试这两个代码时,第一个代码什么也没做,但第二个代码有前面解释过的奇怪行为。
代码谁做了我想做的事:
#include <avr/io.h>
#include <util/delay.h>
int main(void){
while(1){}
}
(十六进制文件:
:02000000FFCF30
:00000001FF
)
代码让我的 LED 一次又一次闪烁 3 次: (即使在 while 循环之前添加行
DDRB |= (1 << DDB5);
进行端口初始化)
#include <avr/io.h>
#include <util/delay.h>
void setHigh_Led(void);
int main(void){
while(1){
}
}
void setHigh_Led(void){
}
(十六进制文件
:060000000895259AFFCFD0
:00000001FF
:040000000895FFCF91
:00000001FF
)
下面的代码更接近原始代码,它打开了我的 LED,但在它应该关闭的时候,它闪烁了:
void setHigh_Led(void);
int main(void){
DDRB |= (1 << DDB5);
while(1){
setHigh_Led();
_delay_ms(500);
PORTB &= ~(1 << PORTB5);
_delay_ms(500);
}
}
void setHigh_Led(void){
PORTB |= 1 << PORTB5;
}
(十六进制文件:
:100000002D9A0895259A0E9400002FEF89E698E125
:10001000215080409040E1F700C000002D982FEF64
:1000200089E698E1215080409040E1F700C000004F
:02003000EACF15
:00000001FF
)
为了完成这些是我执行来编译代码并将其发送到卡的脚本行:
avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o blink/blink.o blink/blink.c
avr-gcc -o blink/blink.bin blink/blink.o
avr-objcopy -O ihex -R .eeprom blink/blink.bin blink/blink.hex
avrdude -F -V -c arduino -p ATMEGA328P -P COM3 -b 115200 -U flash:w:blink.hex
你能帮我了解发生了什么事吗?
我反编译了这个
:060000000895259AFFCFD0
:00000001FF
如
00000000 <.sec1>:
0: 08 95 ret
2: 25 9a sbi 0x04, 5 ; 4
4: ff cf rjmp .-2 ; 0x4
如您所见,源文件中只是纯代码。由于该函数为空,因此仅将其编译为返回指令。然而,由于缺少函数调用,因此发生了堆栈溢出。
您没有正确的链接,缺少 -mmcu=atmega328p 选项。 如果没有 -mmcu avr-gcc 则无法链接正确的 crt.o,因此不会调用 main。
更改命令
avr-gcc -o blink/blink.bin blink/blink.o
到
avr-gcc -mmcu=atmega328p -o blink/blink.bin blink/blink.o
然后你就得到了正确调用主函数的正确代码