基于MDK创建纯汇编语言的STM32工程——汇编实现LED闪烁

一、创建一个新工程

1.创建工程
①点击Project,选择New uvison Project
在这里插入图片描述
②选择文件保存的路径以及文件的名称
2.环境配置
①选择对应的芯片,本文章采用的STM32F103RC
在这里插入图片描述
②运行环境选择,主要是CMSIS下选择CORE;Device下Startup,其中包含了启动文件
在这里插入图片描述
自此,一个工程的建立就算完成了。

二、添加文件

1.鼠标右键单击Source Group 1,选择Add New Item to Group
在这里插入图片描述
2.选择 Asm File (.s) ,设置源文件的名称,点击Add
在这里插入图片描述
自此,添加文件的过程就完成了,就可以开始编写汇编程序。

三、汇编程序

代码

 AREA MYDATA, DATA
	
 AREA MYCODE, CODE
	ENTRY
	EXPORT __main

__main
	MOV R0, #10
	MOV R1, #11
	MOV R2, #12
	MOV R3, #13
	;LDR R0, =func01

	BL	func01
	;LDR R1, =func02
	BL	func02
	
	BL 	func03
	LDR LR, =func01
	LDR PC, =func03
	B .
		
func01
	MOV R5, #05
	BX LR
	
func02
	MOV R6, #06
	BX LR
	
func03
	MOV R7, #07
	MOV R8, #08	
	BX LR


选择仿真器
设置硬件仿真器为ST_Link(根据自己的实际情况进行选择),仿真器的模式设置为JTAG接口或者SW(根据自己的实际情况进行选择)。设置完成,连接相应的仿真器会有对应信息显示。
仿真调试(断点设置是在代码行前点击,出现红点,即表明断点设置成功)
在这里插入图片描述
调试效果
在这里插入图片描述
最终结果可以看出寄存器的值与设置的值一致。

四、分析编译生成的Hex文件

1.最终生成程序的各部分的大小
在这里插入图片描述
2.分析Hex文件第一行内容
在这里插入图片描述
第一行内容分别是0x02,0x00,0x00,0x04,0x08,0x00,0xF2。

  • 0x02
    该行数据中有两个数据
  • 0x00 0x00
    本行数据的起始地址位
  • 0x04
    用来标识扩展线性地址的记录
    该字节还可以是其他值,下面是其他值的含义
    00:用来记录数据,HEX文件的大部分记录都是数据记录
    01:用来标识文件结束,放在文件的最后,标识HEX文件的结尾
    02:用来标识扩展段地址的记录
    03:开始段地址记录
    05:开始线性地址记录
  • 0x08 0x00
    该行两个字节的数据
    数据类型是 04 ,即该行记录的是一个拓展地址(0x08 0x00 是地址信息,用法是将该地址(0x0800<<16) 后作为基地址
  • 0xF2
    校验和,校验和= 0x100 - 累加和

五、使用汇编实现LED闪烁

1.创建一个新工程
不需要添加启动代码(startup,core),其他步骤跟上面步骤基本一致。
2.添加一个汇编文件
代码内容如下

LED0 EQU 0x40011004;定义引脚PC2 
RCC_APB2ENR EQU 0x40021018;配置RCC寄存器,时钟
GPIOC_CRL EQU 0x40011000;配置CRL寄存器
Stack_Size      EQU     0x00000400;栈的大小
;分配一个STACK段,该段不初始化,可读写,按8字节对齐。分配一个大小为Stack_Size的存储空间,并使栈顶的地址为__initial_sp。
                AREA    STACK, NOINIT, READWRITE, ALIGN=3;NOINIT: = NO Init,不初始化。READWRITE : 可读,可写。ALIGN =3 : 2^3 对齐,即8字节对齐。
Stack_Mem       SPACE   Stack_Size
__initial_sp

                AREA    RESET, DATA, READONLY

__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                    
                    
                AREA    |.text|, CODE, READONLY;开始代码段
                    
                THUMB
                REQUIRE8
                PRESERVE8
                    
                ENTRY
Reset_Handler 
                BL LED_Init;BL:带链接的跳转指令。当使用该指令跳转时,当前地址(PC)会自动送入LR寄存器
MainLoop        BL LED_ON
                BL Delay
                BL LED_OFF
                BL Delay
                
                B MainLoop;B:无条件跳转。
             
LED_Init;LED初始化
                PUSH {
    
    R0,R1, LR};R0,R1,LR中的值放入堆栈
                
                LDR R0,=RCC_APB2ENR;LDR是把地址装载到寄存器中(比如R0)。
                ORR R0,R0,#0x04;ORR 按位或操作,将将R0的第二位置1,其他位不变
                LDR R1,=RCC_APB2ENR
                STR R0,[R1];STR是把值存储到寄存器所指的地址中。
                
                LDR R0,=GPIOC_CRL
                BIC R0,R0,#0x0F;BIC 先把立即数取反,再按位与
                LDR R1,=GPIOC_CRL
                STR R0,[R1]
                
                LDR R0,=GPIOC_CRL
                ORR R0,R0,#0x03
                LDR R1,=GPIOC_CRL
                STR R0,[R1]
                ;将PC2置1
                MOV R0,#1 
                LDR R1,=LED0
                STR R0,[R1]
             
                POP {
    
    R0,R1,PC};将栈中之前存的R0,R1,LR的值返还给R0,R1,PC

             
LED_ON
                PUSH {
    
    R0,R1, LR}    
                
                MOV R0,#0
                LDR R1,=LED0
                STR R0,[R1]
             
                POP {
    
    R0,R1,PC}
             
LED_OFF
                PUSH {
    
    R0,R1, LR}    
                
                MOV R0,#1 
                LDR R1,=LED0
                STR R0,[R1]
             
                POP {
    
    R0,R1,PC}             
             
Delay
                PUSH {
    
    R0,R1, LR}
                
                MOVS R0,#0
                MOVS R1,#0
                MOVS R2,#0
                
DelayLoop0        
                ADDS R0,R0,#1

                CMP R0,#330
                BCC DelayLoop0
                
                MOVS R0,#0
                ADDS R1,R1,#1
                CMP R1,#330
                BCC DelayLoop0

                MOVS R0,#0
                MOVS R1,#0
                ADDS R2,R2,#1
                CMP R2,#15
                BCC DelayLoop0
                
                
                POP {
    
    R0,R1,PC}    
             
    ;         NOP
             END

相关命令说明
AREA命令:AREA 命令指示汇编器汇编一个新的代码段或数据段。段是独立的、指定的、不可见的代码或数据块,它们由链接器处理。

格式如下:AREA 段名,段属性1,段属性2,段属性3
例如:AREA STACK, NOINIT, READWRITE, ALIGN=3

SPACE命令:SPACE 命令保留一个用零填充的存储器块。
ENTRY命令:声明整个程式的入口点,入口点有且仅有一个。
完成后,编译烧录,最终结果是将开发板上的LED点亮,但是,并没有出现闪烁的现象。

六、小结

通过对汇编的初步了解,发现对应汇编理解还不够,还太会使用汇编进行编程。给一段简单的汇编代码,基本能够读懂大部分语句的含义,但是,自己写还不是太会,还需要进一步学习。

七、参考资料

1.HEX文件详解
2.ARM汇编基础之基于MDK创建纯汇编语言的STM32工程
3.简单的STM32 汇编程序—闪烁LED
4.一步一步写ARM汇编(一)
5.ARM 汇编学习——编写简单的ARM汇编程序
6.STM32(一) 汇编操作GPIO

猜你喜欢

转载自blog.csdn.net/qq_43279579/article/details/111717607