使用按键逐个开启10路LED无响应问题排查求助
AVR单片机按键逐路点亮LED问题排查
我编写了一段AVR单片机代码,希望通过按键手动逐个开启10路LED,但代码可运行、硬件连接无误的情况下,LED始终无法点亮,请问问题出在哪里?
#define __SFR_OFFSET 0 #include <avr/io.h> .global main main: ldi R16, 0xFD ; Set PD1–PD6 as outputs, PD0 as input out DDRD, R16 ldi R16, 0x01 ; Enable pull-up resistor on PD0 out PORTD, R16 ldi R16, 0b00000111 ; Set PB0 and PB1 and PB2 as outputs out DDRB, R16 wait_button: sbis PIND, 0 ; Skip if bit in PIND.0 is SET (button NOT pressed) rjmp start_sequence ; Jump if it's 0 (button pressed) rjmp wait_button ; Keep waiting wait_release: sbic PIND, 0 ; Wait until button is released (PIND.0 == 1) rjmp wait_release ; Now wait for the next button press rjmp wait_button start_sequence: ; Turn on PD1 ldi R16, 0b00000010 out PORTD, R16 cbi PORTB, 0 cbi PORTB, 1 cbi PORTB, 2 rjmp wait_release ; Now wait for the next button press ; Blink PD2 ldi R16, 0b00000100 out PORTD, R16 rjmp wait_release ; Now wait for the next button press ; Blink PD3 ldi R16, 0b00001000 out PORTD, R16 rjmp wait_release ; Now wait for the next button press ; Blink PD4 ldi R16, 0b00010000 out PORTD, R16 rjmp wait_release ; Now wait for the next button press ; Blink PD5 ldi R16, 0b00100000 out PORTD, R16 rjmp wait_release ; Now wait for the next button press ; Blink PD6 ldi R16, 0b01000000 out PORTD, R16 rjmp wait_release ; Now wait for the next button press ; Blink PB0 clr R16 out PORTD, R16 sbi PORTB, 0 cbi PORTB, 1 cbi PORTB, 2 rjmp wait_release ; Now wait for the next button press ; Blink PB1 cbi PORTB, 0 sbi PORTB, 1 cbi PORTB, 2 rjmp wait_release ; Now wait for the next button press ; Blink PB2 cbi PORTB, 0 cbi PORTB, 1 sbi PORTB, 2 rjmp wait_release ; Now wait for the next button press ; Turn everything off clr R16 out PORTD, R16 cbi PORTB, 0 cbi PORTB, 1 cbi PORTB, 2 ret
核心问题:程序流程逻辑错误,后续LED代码永远无法执行
你的代码存在致命的流程设计问题:
- 每次按下按键进入
start_sequence后,点亮第一个LED(PD1)就直接跳转到wait_release,而wait_release执行完毕后又跳回wait_button。 - 下次再按下按键时,程序会重新从
start_sequence的开头执行,永远不会走到PD2、PD3以及PB口LED的点亮代码,导致除PD1外的LED根本没机会被触发,甚至PD1的状态也会因为重复触发被反复重置。
次要问题补充
- PORTD上拉电阻被意外关闭:初始设置
PORTD=0x01开启PD0上拉,但在start_sequence中设置PORTD为其他值时,PD0位被设为0,导致上拉电阻失效。松开按键后PIND.0会进入浮空状态,可能导致wait_release的判断逻辑出错。 - 代码缩进混乱:原代码中
wait_release被错误缩进在wait_button代码块内,虽然汇编不依赖缩进,但会严重降低代码可读性,建议调整为同级结构。
修正思路
需要引入状态计数器来记录当前点亮的LED序号,每次按键触发时切换到下一个状态,而非重复执行开头代码。示例核心逻辑:
main: ; 原初始化代码保留 ldi R17, 0x00 ; 状态计数器,记录当前LED序号 wait_button: sbis PIND, 0 rjmp handle_button rjmp wait_button handle_button: ; 根据计数器值执行对应LED操作 cpi R17, 0 breq turn_on_pd1 cpi R17, 1 breq turn_on_pd2 ; ... 依次添加剩余LED的判断 ... ; 计数器递增,超过上限重置 inc R17 cpi R17, 10 brlt wait_release ldi R17, 0x00 wait_release: sbic PIND, 0 rjmp wait_release rjmp wait_button turn_on_pd1: ldi R16, 0b00000011 ; 保留PD0上拉位 out PORTD, R16 cbi PORTB, 0 cbi PORTB, 1 cbi PORTB, 2 ret ; ... 依次添加剩余LED的处理函数 ...
内容的提问来源于stack exchange,提问作者Lerato Shiburi
相关产品推荐
相关产品推荐

