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

树莓派GPIO汇编程序未按按钮时digitalRead返回HIGH的问题解决

此问题为重发,因原问题存在上下文与格式问题,故重新发布

程序功能

本程序实现按下三个按钮中的任意一个时,通过循环控制LED闪烁:

  • 当BTN_LEFT输入读取为HIGH时,程序跳转到BLNKR_LEFT循环,使LED_LEFT闪烁,直到BTN_LEFT读取为LOW;
  • 当BTN_HZRD读取为HIGH时,程序跳转到BLNKR_HZRD循环,使LED_LEFT和LED_RIGHT闪烁,直到BTN_HZRD读取为LOW;
  • 当BTN_RIGHT输入读取为HIGH时,程序跳转到BLNKR_RIGHT循环,使LED_RIGHT闪烁,直到BTN_RIGHT读取为LOW。

在这三个BLNKR循环中,当对应按钮输入返回LOW时,程序跳回INPUT循环,继续监听三个按钮的输入。

// to compile: g++ redLed.s -lwiringPi -g -o redLed
// Program will power an LED when button is pressed, and when button is not pressed, LED will remain off

.equ INPUT, 0
.equ OUTPUT, 1
.equ LOW, 0
.equ HIGH, 1

.equ LED_LEFT, 29   // wiringPi 29 (bcm 21)
.equ LED_RIGHT, 28  // wiringPi 28 (bcm 20)
.equ BTN_LEFT, 23   // wiringPi 23 (bcm 13)
.equ BTN_HZRD, 22   // wiringPi 22 (bcm 6)
.equ BTN_RIGHT, 21  // wiringPi 21 (bcm 5)

.text
.global main
main:
// int main()
    push {lr} // {
    bl wiringPiSetup // wiringPiSetup(); // initialize the wiringPi library
    
    // Initialize our WPI inputs and outputs
    mov r0, #LED_LEFT // pinMode(29,OUTPUT); // set the wpi 29 pin for output
    mov r1, #OUTPUT
    bl pinMode
    
    mov r0, #LED_RIGHT // pinMode(28,OUTPUT); // set the wpi 28 pin for output
    mov r1, #OUTPUT
    bl pinMode
    
    mov r0, #BTN_LEFT  // pinMode(23,INPUT); // set the wpi 23 pin for input
    mov r1, #INPUT
    bl pinMode
    
    mov r0, #BTN_HZRD // pinMode(22,INPUT); // set the wpi 22 pin for input
    mov r1, #INPUT
    bl pinMode
    
    mov r0, #BTN_RIGHT // pinMode(21,INPUT); // set the wpi 21 pin for input
    mov r1, #INPUT
    bl pinMode
    
    // Searches for an input from any button, if there is no input, then the program will keep looping
INPUT:
    // Set both LEDs to LOW
    mov r0, #LED_LEFT
    mov r1, #LOW
    bl digitalWrite
    
    mov r0, #LED_RIGHT
    mov r1, #LOW
    bl digitalWrite
    
    // Read for input from BTN_LEFT, BTN_RIGHT, or BTN_HZRD
    mov r0, #BTN_LEFT
    bl digitalRead    // digitalRead(BTN_LEFT);
    
    mov r1, #HIGH
    cmp r0, r1
    bleq BLNKR_LEFT
    
    // Read for input from BTN_HZRD
    mov r0, #BTN_HZRD
    bl digitalRead
    
    mov r1, #HIGH
    cmp r0, r1
    bleq BLNKR_HZRD
    
    // Read for input from BTN_RIGHT
    mov r0, #BTN_RIGHT
    bl digitalRead
    
    mov r1, #HIGH
    cmp r0, r1
    bleq BLNKR_RIGHT
    b INPUT

BLNKR_LEFT:
    // If BTN_LEFT is not being pressed then the program will return to INPUT
    mov r0, #BTN_LEFT
    bl digitalRead
    
    mov r1, #LOW
    cmp r0, r1
    bleq INPUT
    
    mov r0, #LED_LEFT // digitalWrite(29,HIGH); // write high volt signal to pin 29
    mov r1, #HIGH
    bl digitalWrite

    ldr r0, =#350 // delay(350); // Delay for 350 milliseconds
    bl delay

    mov r0, #LED_LEFT // digitalWrite(29,LOW); // write low voltage to wpi 29 to turn off the led
    mov r1, #LOW
    bl digitalWrite
    
    ldr r0, =#350
    bl delay
    
    b BLNKR_LEFT
    
BLNKR_HZRD:
    // If BTN_HZRD isnt being pressed then the program will branch back to INPUT
    mov r0, #BTN_HZRD
    bl digitalRead
    
    mov r1, #LOW
    cmp r0, r1
    bleq INPUT
    
    // Turn on both LED_LEFT and LED_RIGHT
    mov r0, #LED_LEFT
    mov r1, #HIGH
    bl digitalWrite
    
    mov r0, #LED_RIGHT
    mov r1, #HIGH
    bl digitalWrite
    
    // delay for 350 milliseconds
    ldr r0, =#350 
    bl delay

    // Turn off both LED_LEFT and LED_RIGHT
    mov r0, #LED_LEFT
    mov r1, #LOW
    bl digitalWrite
    
    mov r0,#LED_RIGHT
    mov r1, #LOW
    bl digitalWrite
    
    // Delay for 350 milliseconds
    ldr r0, =#350
    bl delay
    
    b BLNKR_HZRD
    
BLNKR_RIGHT:
    // If BTN_RIGHT isnt being pressed then the program will branch back to INPUT
    mov r0, #BTN_RIGHT
    bl digitalRead
    
    cmp r0, #LOW
    bleq INPUT
    
    // Turn on LED_RIGHT
    mov r0, #LED_RIGHT
    mov r1, #HIGH
    bl digitalWrite
    
    // delay for 350 milliseconds
    ldr r0, =#350 
    bl delay

    // Turn off LED_RIGHT
    mov r0,#LED_RIGHT
    mov r1, #LOW
    bl digitalWrite
    
    // Delay for 350 milliseconds
    ldr r0, =#350
    bl delay
    
    b BLNKR_RIGHT

    mov r0, #0 // return 0;
    pop {pc} // }
问题描述

运行程序时,BLNKR_LEFT或BLNKR_HZRD循环会在未按下任何物理按钮的情况下自动启动,具体取决于哪个cmp指令先执行。
执行BTN_LEFT或BTN_HZRD的digitalRead时,r0寄存器会存储HIGH值,但实际未按下按钮;而BTN_RIGHT的digitalRead能根据是否按下按钮正确返回HIGH或LOW。
尝试更换不同按钮开关后,BTN_LEFT和BTN_HZRD返回HIGH的问题仍未解决,推测问题可能出在面包板接线。

解决方案

经排查,连接按钮的BCM 5和BCM 6引脚默认电平为HIGH,仅BCM 13默认电平为LOW且工作正常。因此将BTN_LEFT和BTN_HZRD分别重新连接到BCM 13和BCM 19,BTN_RIGHT连接到BCM 26。这三个BCM引脚通过gpio readall查看默认电平为LOW,程序现已正常运行。
通过gpio readall可见,BCM引脚5和6显示电压为1,BCM引脚13、19和26显示电压为0。此前曾尝试使用PUD_DOWN内部电阻解决浮空引脚问题。

内容的提问来源于stack exchange,提问作者BeefCake

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 23:35:25