You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用按键逐个开启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的状态也会因为重复触发被反复重置。

次要问题补充

  1. PORTD上拉电阻被意外关闭:初始设置PORTD=0x01开启PD0上拉,但在start_sequence中设置PORTD为其他值时,PD0位被设为0,导致上拉电阻失效。松开按键后PIND.0会进入浮空状态,可能导致wait_release的判断逻辑出错。
  2. 代码缩进混乱:原代码中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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 06:37:33