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

Arm Cortex-M4子程序异常:偶发无法进入BinaryCount问题排查

嵌入式LED按键程序异常排查请求

需求描述

  • 按住按键时,依次让绿色、橙色、蓝色、红色LED各闪烁1秒
  • 松开按键后,所有LED熄灭,程序等待再次按键
  • 再次按键时进入BinaryCount子程序执行计数功能

问题现象

程序行为不稳定:有时功能符合预期,但有时始终无法进入BinaryCount子程序。

完整代码

主程序文件

.include "Equates.s"

        .syntax unified
        .text
        .global main
        .global Delay
        .global Top

Delay:    mov     r1,r3
          ldr    r2,=#0x000AAE60
          mul    r1,r2
Dloop:    subs    r1, #1
          bne     Dloop
          bx      lr

BlinkLed:   push    {lr}

Blink:
            mov             r3,#2
            bl      LEDGreenOn
            bl      Delay
            bl      LEDGreenOff
            bl      Delay
            bl      CheckButton
            cmp     r0,#1
            bne             ButtonNotPressed

            bl      LEDOrangeOn
            bl      Delay
            bl      LEDOrangeOff
            bl      Delay
            bl      CheckButton
            cmp     r0,#1
            bne     ButtonNotPressed

            bl      LEDBlueOn
            bl      Delay
            bl      LEDBlueOff
            bl      Delay
            bl      CheckButton
            cmp     r0,#1
            bne     ButtonNotPressed

            bl      LEDRedOn
            bl      Delay
            bl      LEDRedOff
            bl      Delay
            bl      CheckButton
            cmp     r0,#1
            beq     Blink
                bne             ButtonNotPressed


ButtonNotPressed:
            bl      CheckButton
            cmp     r0,#1
            bne     ButtonNotPressed
                bl              BinaryCount
            pop     {lr}
            b       Top

main:
            bl      InitButton
            bl      InitLEDs

Top:                bl      CheckButton
            cmp     r0,#1
            bne     Top
            bl      BlinkLed

            .end

按键驱动文件

.include "Equates.s"

        .syntax unified
        .text
        .global InitButton
        .global CheckButton


InitButton:

            ldr     r0,=RCC
            ldr     r1,[r0,AHBENR]
            orr     r1,#GPIOAEN
            str     r1,[r0,AHBENR]
            ldr     r0,=GPIOA
            ldr     r1,[r0,#MODER]
            bic     r1,#0x03
            str     r1,[r0,#MODER]
            bx      lr


CheckButton:

            ldr     r0,=GPIOA
            ldrh    r0,[r0,#IDR]
            and     r0,#0x01
            bx      lr

            .end

BinaryCount模块文件

.include "Equates.s"

        .syntax unified
        .text
        .global BinaryCount

BinaryCount:
            mov     r5,#-1

CountLoop:
            add     r5,#1
            cmp     r5,#15
            bgt     ResetCount
            ldr     r0,=GPIOB
            mov     r1,r5
            lsl     r1,r1,#6
            ldrh    r2,[r0,#ODR]
            bic     r2,#0x0FC0
            orr     r2,r1
            strh    r2,[r0,#ODR]
            mov     r3,#1
            bl      Delay
            bl      CheckButton
            cmp     r0,#1
            beq     CountLoop
            bl      AllLEDsOff
            b       Top

ResetCount:

            mov     r5,#0
            b       CountLoop

            .end

LED驱动文件

.include "Equates.s"

        .syntax unified
        .text
        .global InitLEDs
        .global LEDGreenOff
        .global LEDOrangeOff
        .global LEDBlueOff
        .global LEDRedOff
        .global LEDGreenOn
        .global LEDOrangeOn
        .global LEDBlueOn
        .global LEDRedOn
        .global AllLEDsOff

InitLEDs:

            ldr     r0,=RCC
            ldr     r1,[r0,AHBENR]
            orr     r1,#GPIOBEN
            str     r1,[r0,AHBENR]
            ldr     r0,=GPIOB
            ldr     r1,[r0,#MODER]
            bic     r1,#0x000FF000
            orr     r1,#0x00055000
            str     r1,[r0,#MODER]

            ldrh    r1,[r0,#ODR]
            bic     r1,#0x03C0
            strh    r1,[r0,#ODR]
            bx      lr

LEDGreenOn:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            orr     r1,#0x0200
            strh    r1,[r0,#ODR]
            bx      lr

LEDGreenOff:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            bic     r1,#0x0200
            strh    r1,[r0,#ODR]
            bx      lr

LEDOrangeOn:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            orr     r1,#0x0100
            strh    r1,[r0,#ODR]
            bx      lr

LEDOrangeOff:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            bic     r1,#0x0100
            strh    r1,[r0,#ODR]
            bx      lr

LEDBlueOn:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            orr     r1,#0x0080
            strh    r1,[r0,#ODR]
            bx      lr

LEDBlueOff:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            bic     r1,#0x0080
            strh    r1,[r0,#ODR]
            bx      lr

LEDRedOn:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            orr     r1,#0x0040
            strh    r1,[r0,#ODR]
            bx      lr

LEDRedOff:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            bic     r1,#0x0040
            strh    r1,[r0,#ODR]
            bx      lr

AllLEDsOff:
            ldr     r0,=GPIOB
            ldrh    r1,[r0,#ODR]
            bic     r1,#0x0FC0
            strh    r1,[r0,#ODR]
            bx      lr

            .end

问题定位与解决方向

1. 栈失衡导致程序流程混乱

BinaryCount子程序结尾直接跳转到Top,没有返回调用者BlinkLed,导致BlinkLed中压入栈的lr值从未被弹出,栈结构被破坏。后续再次进入BlinkLed时,lr值错误,无法正确跳转执行BinaryCount。

修复方案:

  • 修改BinaryCount的结尾逻辑,将b Top改为bx lr,让子程序返回调用者:
    cmp     r0,#1
    beq     CountLoop
    bl      AllLEDsOff
    bx      lr  // 返回BlinkLed,而非直接跳Top
    
  • 调整BlinkLed中的ButtonNotPressed代码块,确保调用BinaryCount后正确清理栈并跳转:
    ButtonNotPressed:
        bl      CheckButton
        cmp     r0,#1
        bne     ButtonNotPressed
        bl      BinaryCount
        pop     {lr}
        b       Top
    

2. 按键无消抖导致状态误判

机械按键按下/松开时存在抖动,短时间内会出现多次电平跳变,程序可能误判按键状态,导致流程异常。

修复方案:

  • 在CheckButton函数中添加消抖逻辑,检测到电平变化后延时10ms左右再次确认状态:
    CheckButton:
        ldr     r0,=GPIOA
        ldrh    r1,[r0,#IDR]
        and     r1,#0x01
        mov     r3,#10  // 延时10ms,需根据Delay函数的参数调整
        bl      Delay
        ldrh    r2,[r0,#IDR]
        and     r2,#0x01
        cmp     r1,r2
        bne     CheckButton  // 状态不稳定,重新检测
        mov     r0,r1
        bx      lr
    

3. 冗余分支逻辑优化

Blink循环最后一个分支判断存在冗余代码,可简化为:

bl      CheckButton
cmp     r0,#1
beq     Blink
b       ButtonNotPressed

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:24:56