STM32汇编程序闪烁LED灯1

参考代码:Embedded/stm32/assembly-led · guorong/study - 码云 - 开源中国 (gitee.com)

在main函数中添加如下代码:

            AREA    |.text|, CODE, READONLY  

GPIOB_CRL              EQU    0X40010C00
GPIOB_CRL_OUT          EQU    1<<21        ;1<<21   

GPIOB_ODR              EQU    0X40010C0C
GPIOB_ODR_OUT          EQU     1<<5        ;1<<5
    
GPIOB_BSRR              EQU    0X40010C10
GPIOB_BSRR_OFF          EQU    1<<5        ;1<<5
GPIOB_BSRR_ON           EQU    1<<21    ;1<<21

RCC_APB2ENR            EQU    0x40021018
RCC_APB2ENR_DATA        EQU    1<<3          ;1<<3


main  PROC 
    EXPORT  main

    LDR R1, =RCC_APB2ENR            ; 将寄存器基地址载入R1
    LDR R2, [R1]                    ; 将R1的数据读取到R2
    ORR R2,R2,#RCC_APB2ENR_DATA      ; 将R2的值改为目标值
    STR R2, [R1]                    ; 将R0的值写入目标寄存器
    
    LDR R1, =GPIOB_CRL            ; 将寄存器基地址载入R1
    LDR R2, [R1]                    ; 将R1的数据读取到R2
    ORR R2,R2,#GPIOB_CRL_OUT      ; 将R2的值改为目标值
    STR R2, [R1]                    ; 将R0的值写入目标寄存器

label    
    LDR R1, =GPIOB_BSRR            ; 将寄存器基地址载入R1
    MOV R2,#GPIOB_BSRR_ON
    STR R2, [R1]                    ; 将R0的值写入目标寄存器
    
    LDR  R4, =1000000  ; R4被加载为延时计数的初值,这个值依据时钟频率和需要的延时进行调整
Delay_Loop
    SUBS R4, R4, #1    ; 每个循环递减计数器
    BNE  Delay_Loop    ; 如果R4不为零则继续循环
    
    LDR R1, =GPIOB_BSRR            ; 将寄存器基地址载入R1
    MOV R2,#GPIOB_BSRR_OFF
    STR R2, [R1]                    ; 将R0的值写入目标寄存器

    LDR  R4, =1000000  ; R4被加载为延时计数的初值,这个值依据时钟频率和需要的延时进行调整
Delay_Loop2
    SUBS R4, R4, #1    ; 每个循环递减计数器
    BNE  Delay_Loop2    ; 如果R4不为零则继续循环

    B      label
    ENDP
    ALIGN
    END

即可编译下载实现PB5不断翻转电平,可以看到LED灯在闪烁

        注意,编译的时候,需要带上use microlib,否则可能会有导致代码卡住。原因是在reset handler中,首先调到了__main函数中,这个函数不是main函数,而是在C库中(默认不带micro lib编译的时候),这个函数主要的作用就是内存初始化,包括将初始化过的可读写的全局变量和静态变量拷贝到内存对应的区域,初始化那些初始化为0的静态变量和全局变量,然后将栈顶地址和堆地址设置好,之后跳转到main函数,在这个过程中可能会碰到一个BKPT 0xAB的地方,是内核调试的一个相关指令,导致程序出问题,编译为microlib就可以避免这个问题。microlib是keil专门为 嵌入式实现了的一个更加精简的库函数,用来取代C标准库。在代码编译的时候,勾选和不勾选use microlib的时候,可以明显看到编译出来的代码的大小有变化。

其实对于汇编语言来说,可以不进行__main的那些内存初始化操作,在reset handler中,直接跳转到main函数中执行,可以理解为__main是为了C语言运行准备了环境。即如下所示

可以不带入microlib编译,正常运行。但是问题就是内存区域没有初始化,数据为上电后乱七八糟的数据,可以看到右下角的内存数据是乱的。所以不建议这么做。

另一个有趣的现象是不use microlib的时候,sp指向了0x20000660,即内存空间用了0x660的大小,其中在启动文件的最开始的位置,定义了栈的大小为0x400,堆空间的大小为0x200,剩余的0x60的大小是初始化为bss段的,即初始化为0的区域,双击项目文件里的Target1目录,可以打开map文件,里边有解释内存的分布情况,可以看到是.bss和HEAP和STACK

 而在勾选了use microlib之后,内存空间只保留了栈大小,为0x20000400,没有bss段和堆空间(堆空间只有在使用malloc申请内存的时候,才会使用)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ren guorong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值