STM32不使用启动文件 用汇编点亮一个LED灯并闪烁

本文为使用汇编开发STM32系列文章之----STM32不使用启动文件 用汇编点亮一个LED灯并闪烁,全部文章目录点此跳转。

1.LED灯电路

在这里插入图片描述

2.LED灯闪烁 汇编程序

;本程序使用纯汇编编写
;功能:使PA0引脚连接的LED灯闪烁
;具体步骤:	1.配置中断向量表
;         	2.使能GPIOA时钟
;         	3.配置GPIOA 0引脚为输出模式、推挽、最大速度50MHZ
;			4.编写LED点亮,LED熄灭,DELAY延时函数
;			5.编写跳转逻辑,实现功能


				PRESERVE8										;配置以下代码8字节对齐
				THUMB											;配置以下代码为THUMB代码
	
	
RCC_APB2ENR		EQU		0x40021018								;定义APB2外设时钟使能寄存器地址
GPIOA_CRL 		EQU		0x40010800								;定义GPIOA端口配置低寄存器地址
GPIOA_CRH 		EQU		0x40010804								;定义GPIOA端口配置高寄存器地址
GPIOA_IDR 		EQU		0x40010808								;定义GPIOA端口输入数据寄存器地址
GPIOA_ODR 		EQU		0x4001080C								;定义GPIOA端口输出数据寄存器地址
GPIOA_BSRR 		EQU		0x40010810								;定义GPIOA端口位设置/清除寄存器地址
GPIOA_BRR 		EQU		0x40010814								;定义GPIOA端口位清除寄存器地址
GPIOA_LCKR 		EQU		0x40010818								;定义GPIOA端口配置锁定寄存器地址
	
				AREA    RESET, DATA, READONLY					;创建一个名为RESET的只读数据段

				DCD     0x80000200								;设置栈顶MSP地址
				DCD     MAIN									;设置PC(程序指针计数器)指向的地址值
	

				AREA    |.text|, CODE, READONLY					;创建一个名为|.text|的只读代码段
	
				ENTRY											;程序入口处
				
MAIN  			PROC											;主函数开始
		
																;配置RCC_APB2ENR寄存器,使能GPIOA时钟
				LDR		R0, =RCC_APB2ENR						;将寄存器RCC_APB2ENR的地址值放到R0寄存器
				LDR		R1, [R0]								;将R0保存地址处的值读取出来放到R1寄存器,即读取寄存器RCC_APB2ENR的值。
				ORR     R1, R1, #0x00000004						;使寄存器RCC_APB2ENR的GPIOA时钟使能位为1,并将值暂时放置到R1寄存器,为不破坏原有设置使用ORR指令只改变GPIOA时钟使能位为1。
				STR		R1, [R0]								;将R1寄存器保存的值放到R0寄存器保存的地址值所在的地址处,即完成对寄存器RCC_APB2ENR的配置


																;配置GPIOA_CRL寄存器,使GPIOA 0为推挽输出模式,最大速度为50MHZ
				LDR		R0, =GPIOA_CRL							;将寄存器GPIOA_CRL的地址值放到R0寄存器
				LDR		R1, [R0]								;将R0保存地址处的值读取出来放到R1寄存器,即读取寄存器GPIOA_CRL的值。
				ORR     R1, R1, #0x00000003						;改变寄存器GPIOA_CRL的GPIOA 0的设置,并将值暂时放置到R1寄存器,为不破坏原有设置使用ORR指令只改变GPIOA 0的设置。
				STR		R1, [R0]								;将R1寄存器保存的值放到R0寄存器保存的地址值所在的地址处,即完成对寄存器GPIOA_CRL的配置
				
				B		LOOP									;跳转到死循环函数

				ENDP											;主函数结束


LOOP			PROC											;死循环函数开始,相当于while(1){}
				
				BL		LED_ON									;带返回的跳转到LED_ON执行,B后带L会将此指令的下一条指令的地址存放到LR寄存器,用于返回此处继续运行
				LDR		R0, =1000000							;设置延时值,DELAY中使用R0的值自减进行延时
				BL		DELAY									;带返回的跳转到DELAY执行,进行延时操作,B后带L会将此指令的下一条指令的地址存放到LR寄存器,用于返回此处继续运行
				
				BL		LED_OFF									;带返回的跳转到LED_OFF执行,B后带L会将此指令的下一条指令的地址存放到LR寄存器,用于返回此处继续运行
				LDR		R0, =1000000							;设置延时值,DELAY中使用R0的值自减进行延时
				BL		DELAY									;带返回的跳转到DELAY执行,进行延时操作,B后带L会将此指令的下一条指令的地址存放到LR寄存器,用于返回此处继续运行

				B		LOOP									;跳转到LOOP函数继续运行,因为无需返回,所以B后不带L
	
				ENDP											;死循环函数结束


LED_ON			PROC											;LED点亮函数开始
		
				LDR		R0, =GPIOA_ODR							;将寄存器GPIOA_ODR的地址值放到R0寄存器
				LDR		R1, [R0]								;将R0保存地址处的值读取出来放到R1寄存器,即读取寄存器GPIOA_ODR的值。
				AND     R1, R1, #0xFFFFFFFE						;使寄存器GPIOA_ODR的ODR0位为0,并将值暂时放置到R1寄存器,为不破坏原有设置使用AND(按位与)指令只改变寄存器GPIOA_ODR的ODR0位为0。
				STR		R1, [R0]								;将R1寄存器保存的值放到R0寄存器保存的地址值所在的地址处,即完成寄存器GPIOA_ODR的配置。对应GPIOA_0输出低电平
				
				BX		LR										;跳转到LR(连接寄存器)保存的地址处执行。因为LR保存的是返回地址,故此句执行会返回之前的位置执行。访问LR时,必须使用B后带X。

				ENDP											;LED点亮函数结束


LED_OFF			PROC											;LED熄灭函数开始
		
				LDR		R0, =GPIOA_ODR							;将寄存器GPIOA_ODR的地址值放到R0寄存器
				LDR		R1, [R0]								;将R0保存地址处的值读取出来放到R1寄存器,即读取寄存器GPIOA_ODR的值。
				ORR     R1, R1, #0x00000001						;使寄存器GPIOA_ODR的ODR0位为1,并将值暂时放置到R1寄存器,为不破坏原有设置使用ORR(按位或)指令只改变寄存器GPIOA_ODR的ODR0位为1。
				STR		R1, [R0]								;将R1寄存器保存的值放到R0寄存器保存的地址值所在的地址处,即完成寄存器GPIOA_ODR的配置。对应GPIOA_0输出高电平
				
				BX		LR										;跳转到LR(连接寄存器)保存的地址处执行。因为LR保存的是返回地址,故此句执行会返回之前的位置执行。访问LR时,必须使用B后带X。
				
				ENDP											;LED熄灭函数结束
					
					
DELAY			PROC											;延时函数开始
				
				SUBS	R0, R0 , #1								;SUB指令是减法,相当于 R0 = R0 -1。SUB后带S表示,计算结果会更新到 程序状态寄存器 的相关标志位。
				BNE		DELAY									;B是跳转,B后跟NE,表示程序状态计数器的Z位等于0时,执行跳转。因为Z是零标志位,Z=0表示上一句话的计算结果不为0,则在不为0之前一直执行跳转操作,以实现延时。
				BX		LR										;跳转到LR(连接寄存器)保存的地址处执行。因为LR保存的是返回地址,故此句执行会返回之前的位置执行。访问LR时,必须使用B后带X。
	
				ENDP											;延时函数结束
				
				ALIGN 											;将代码4字节对齐

				END												;整个程序结束
					
			

3. keil5 如何使用程序

  无特殊使用方法,工程中包含一个 .s 文件,文件内放此代码即可成功编译执行。编译后有一个警告,不用理会。此警告是因为未调用 “__main” 函数报的警告,在分散加载文件里有设置 *(InRoot$$Sections) 段,而此段是在 “__main” 函数中进行创建的,主要用于将程序中的一些数据进行指定位置搬移,对汇编程序来说没影响。关于分散加载函数,以后有机会再详细说明。

在这里插入图片描述

4.程序中一些值的计算和寻找方法

在stm32寄存器手册中可找到。详细方法待写…

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

超级网吧

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

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

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

打赏作者

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

抵扣说明:

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

余额充值