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
相关产品推荐
相关产品推荐

