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

STM32 Nucleo-L上HAL_Delay失效求助:寄存器R2/R3冲突及替代方案

STM32 Nucleo-L汇编中HAL_Delay异常问题与解决方案

问题背景

我们在计算机科学课程中使用STM32 Nucleo-L控制器编写汇编代码,我受老师委托测试HAL_Delay指令(老师此前使用该指令遇到问题)。测试发现:

  • 当寄存器R2或/和R3被用于其他用途时,HAL_Delay无法正常工作
  • 自定义的wait_ms指令完全正常
  • 将代码中wait_ms替换为HAL_Delay后,代码可正常编译烧录,但按键按下后无任何反应

想咨询:

  1. 是否应直接改用wait_ms?
  2. 有没有解决HAL_Delay问题的方案?
  3. HAL_Delay子程序在代码中的具体位置?

测试代码

.syntax unified
.equ L152,1
.include "../Core/src/regs.s"
.global mainasm
mainasm:


main:
    bl      startup
    ldr     R1,=GPIOA
    ldr     R2,=GPIOC

    gruenwechsel:  //Wechsel von Rot auf Grün
        ldr     R0,[R2,ODR] //Ampel auf rot setzen
        mov     R0,#0b1
        strb    R0,[R2,ODR]
        mov     R0,#500
        bl      wait_ms     //500ms Warten
        ldr     R0,[R2,ODR]
        mov     R0,#0b101   //Rote und Grüne LED geichzeitig an
        strb    R0,[R2,ODR]
        mov     R0,#500     //500ms Warten
        bl      wait_ms
        b       Gruen       //Ampel auf Grün setzen

    Gruen:      //Grüner Loop
        ldr     R0,[R2,ODR]
        mov     R0,#0b10000 //Ampel auf Grün
        strb    R0,[R2,ODR]
        ldr     R0,[R1,IDR]
        tst     R0,Bit10    //Schauen ob PA10 gedrueckt ist
        bne     rotwechsel  //Falls ja, in rotwechsel springen
        b       Gruen


    rotwechsel:
        ldr     R0,[R2,ODR]
        mov     R0,#0b00100 //Grüne und Gelbe LED Gleichzeitig an
        strb    R0,[R2,ODR]
        mov     R0,#1000    //Warte 1 Sekunde
        bl      wait_ms
        ldr     R0,[R2,ODR]
        mov     R0,#0b00001 //Rote LED an
        strb    R0,[R2,ODR]
        b       Rot

    Rot:                    //Roter Loop
        ldr     R0,[R2,ODR]
        mov     R0,#0b000001 //LED Rot an
        strb    R0,[R2,ODR]
        ldr     R0,[R1,IDR]
        tst     R0,Bit10 //Schauen ob PA10 gedrückt ist, falls ja, in Grünwechsel springen
        bne     gruenwechsel
        b       Rot


.end

解决方案与说明

1. 是否改用wait_ms?

如果wait_ms能满足课程中的延时需求(精度、功能均达标),直接改用是最高效的选择——它在你的代码环境中工作稳定,无需额外调试成本。

2. HAL_Delay问题的修复方案

HAL_Delay依赖STM32 HAL库的SysTick定时器,且遵循ARM Cortex-M的调用约定:R0-R3属于调用者保存寄存器,子程序可直接修改这些寄存器而无需恢复。你的问题大概率是因为HAL_Delay的实现依赖了R2/R3的值,而你在调用前修改了这两个寄存器,导致HAL_Delay运行异常。

修复步骤:

  • 手动保存/恢复寄存器:调用HAL_Delay前将R2、R3压入栈,调用完成后弹出恢复:
    // 替换原有bl HAL_Delay的代码段
    push {r2, r3}
    mov r0, #500
    bl HAL_Delay
    pop {r2, r3}
    
  • 检查SysTick初始化:HAL_Delay需要SysTick定时器正常运行提供延时基准,确认你的startup子程序已正确初始化SysTick,或调用了HAL_Init完成HAL库的初始化流程。

3. HAL_Delay的位置

HAL_Delay是STM32 HAL库的标准函数:

  • 源码层面:位于HAL库对应型号的stm32lxx_hal.c文件中(例如stm32l1xx_hal.c或stm32l4xx_hal.c,取决于你的Nucleo-L具体型号)
  • 编译后:存在于HAL库的静态库文件(如libstm32lxx_hal.a)中,也可在IDE中通过搜索符号HAL_Delay定位其具体位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:11:03