AVR-C中函数为何按定义顺序执行而非main内的调用顺序?
问题描述
我正在学习AVR C,基于ATmega328P微控制器进行实验,使用Linux Mint系统下的avr-gcc工具链编译并烧录代码到Arduino板。我编写了两个LED闪烁函数:blinkPin13用于控制引脚13的LED,blinkPin7用于控制引脚7的LED。函数本身可正常工作,但实验中发现异常现象:在main函数中我先调用blinkPin7,再调用blinkPin13,然而烧录代码后,只有引脚13的LED闪烁,函数执行顺序始终与定义顺序一致,而非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
请问这一现象的原因是什么?
问题原因与解决方案
核心原因:死循环导致函数无法返回
两个闪烁函数blinkPin7和blinkPin13内部都包含while(1)死循环,一旦进入这个循环,程序会一直执行循环内的代码,永远不会退出函数返回main。所以main中调用blinkPin7()后,程序会卡在这个死循环里,根本没有机会执行后续的blinkPin13()调用。关于"执行顺序与定义顺序一致"的误解
你看到只有引脚13的LED闪烁,并不是函数执行顺序和定义顺序有关,大概率是之前烧录过仅包含blinkPin13的代码,或是某次烧录失败导致旧代码仍留在芯片中。当前代码逻辑下,只要blinkPin7被正确执行,引脚7的LED会持续闪烁,永远不会轮到引脚13。修复方案
要让两个LED都工作,需要去掉函数内的死循环,改成单次闪烁逻辑,再在主循环中轮流调用:#include <avr/io.h> #include <util/delay.h> void initPins() { // 预先初始化引脚为输出模式,避免重复设置 DDRB |= (1 << DDB5); DDRD |= (1 << DDD7); } void blinkPin13() { PORTB |= (1 << PORTB5); _delay_ms(5000); PORTB &= ~(1 << PORTB5); _delay_ms(500); } void blinkPin7() { PORTD |= (1 << PORTD7); _delay_ms(1000); PORTD &= ~(1 << PORTD7); _delay_ms(500); } int main(void) { initPins(); while(1) { blinkPin7(); blinkPin13(); } return 0; }
内容的提问来源于stack exchange,提问作者Shobhit
相关产品推荐
相关产品推荐

