简单的STM32 汇编程序—闪烁LED
要移植操作系统,汇编是道不得不跨过去的坎。所以承接上篇的思路,我准备用汇编写一个简单的闪烁LED灯的程式。以此练习汇编,为操作系统做准备。
第一步,还是和上篇一样,建立一个空的文件夹。
第二步,因为是要用汇编来写程式,所以不需要启动代码,这里选择否。
第三步,建立一个.s文件,并把文件添加到工程中。
第四步,在LED.s文件中添加如下代码。
LED0 EQU 0x422101a0
RCC_APB2ENR EQU 0x40021018
GPIOA_CRH EQU 0x40010804 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=
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
MainLoop BL LED_ON
BL Delay
BL LED_OFF
BL Delay B MainLoop LED_Init
PUSH {R0,R1, LR} LDR R0,=RCC_APB2ENR
ORR R0,R0,#0x04
LDR R1,=RCC_APB2ENR
STR R0,[R1] LDR R0,=GPIOA_CRH
BIC R0,R0,#0x0F
LDR R1,=GPIOA_CRH
STR R0,[R1] LDR R0,=GPIOA_CRH
ORR R0,R0,#0x03
LDR R1,=GPIOA_CRH
STR R0,[R1] MOV R0,#
LDR R1,=LED0
STR R0,[R1] POP {R0,R1,PC} LED_ON
PUSH {R0,R1, LR} MOV R0,#
LDR R1,=LED0
STR R0,[R1] POP {R0,R1,PC} LED_OFF
PUSH {R0,R1, LR} MOV R0,#
LDR R1,=LED0
STR R0,[R1] POP {R0,R1,PC} Delay
PUSH {R0,R1, LR} MOVS R0,#
MOVS R1,#
MOVS R2,# DelayLoop0
ADDS R0,R0,# CMP R0,#
BCC DelayLoop0 MOVS R0,#
ADDS R1,R1,#
CMP R1,#
BCC DelayLoop0 MOVS R0,#
MOVS R1,#
ADDS R2,R2,#
CMP R2,#
BCC DelayLoop0 POP {R0,R1,PC} ; NOP
END
///////////////////////////////////////////////////////
代码的简单讲解
1,预定义
LED0 EQU 0x422101a0 ;PA8的Bit-Bond地址。
RCC_APB2ENR EQU 0x40021018
GPIOA_CRH EQU 0x40010804
为方便操作,给每个需要用到的寄存器地址定义一个名字,类似于C语言的#define。PA8的Bit-Bond地址的计算方法可按上篇文章中C语言的算法算出。后面的两个地址时固定的,可从STM32的手册查询,或者根据ST官方的库文件查找计算。
2,分配栈空间
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
这一段摘自启动文件。要读懂这段代码,首先要了解两个命令。
AREA命令:AREA 命令指示汇编器汇编一个新的代码段或数据段。段是独立的、指定的、不可见的代码或数据块,它们由链接器处理。格式如下:
AREA 段名,段属性1,段属性2,段属性3。。。
AREA STACK, NOINIT, READWRITE, ALIGN=3
NOINIT: = NO Init,不初始化。
READWRITE : 可读,可写。
ALIGN =3 : 2^3 对齐,即8字节对齐。
SPACE命令:SPACE 命令保留一个用零填充的存储器块。
所以整段的意思为:分配一个STACK段,该段不初始化,可读写,按8字节对齐。分配一个大小为Stack_Size的存储空间,并使栈顶的地址为__initial_sp。
3,分配向量表
AREA RESET, DATA, READONLY
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
这里的向量可参考我之前写的《STM32向量表详细分析》。
4,开始代码段
AREA |.text|, CODE, READONLY
通知汇编器,开始代码段。
THUMB
REQUIRE8
PRESERVE8
这段的意思是,汇编器支持THUMB指令,代码段按8字节对齐。
ENTRY命令:声明整个程式的入口点,入口点有且仅有一个。不管哪种语言,编译器都得有个入口点,这没什么好说的。
5,程序正式开始。
后面的代码,皆用标准的THUMB2汇编指令。首先了解下代码中用到的指令。
BL:带链接的跳转指令。当使用该指令跳转时,当前地址(PC)会自动送入LR寄存器。
B:无条件跳转。
PUSH和POP:可以看到,所有的子程序都是由PUSH和POP包起来的。借用一张图解释下这两个指令。
据上可知,PUSH {R0,R1, LR}的意思即把R0,R1,LR中的值放入堆栈中。由于主程式中使用BL跳转指令,所以LR中的值实际上就是当前PC的值。而POP {R0,R1,PC}的意思即是将栈中之前存的R0,R1,LR的值返还给R0,R1,PC。这样就完成了子程序的返回。
LDR和STR:寄存器的装载和存储指令。
LDR是把地址装载到寄存器中(比如R0)。
STR是把值存储到寄存器所指的地址中。
举个例子:
MOV R0,#1 ;将立即数1送入R0.
LDR R1,=LED0;将PA8 bit-bond的地址送入R1.
STR R0,[R1];将R0的值,也就是1,送给R1中的值所指向的地址中,也就是PA8的bit-bond地址。
上面三句话的意思即是将PA8置1。
ORR和BIC:
ORR 按位或操作。ORR R0,R0,#0x04意思即将R0中的数或上0x04,再将结果送往R0中。实际意思就是将R0的第二位置1,其他位不变。
BIC 先把立即数取反,再按位与。
CMP和BCC:CMP是比较两个数,相等或大于则将标志位C置位,否则将C清零。BCC是个组合指令,实际为B+CC,意思是如果C=0则跳转。
CMP R2,#15; 计算R2-15的值,若是R2<15,则C=0;若是R2>=15,则C=1。
BCC DelayLoop0;若是C=0,则跳到DelayLoop0,若是c=1,则不跳转。
以上就是代码段相关指令的介绍,相信了解了这些指令的含义,要理解代码并不困难。
整个代码的结构和上篇用C语言写的基本是一样的。可参照理解
////////////////////////////////////////////////////
第五步,编译,下载。
编译后,会有一个警告 No section matches pattern……可不用管。下载后,LED灯正常闪烁。
简单的STM32 汇编程序—闪烁LED的更多相关文章
- 最简单的STM32入门教程----闪烁LED
本文讲述的是如何从零开始,使用keil建立一个简单的STM32的工程,并闪烁LED灯,给小白看. 第零步,当然首先你得有一个STM32的板子,其IO口上接了一个LED... 第一步,建立一个文件夹0. ...
- ARM汇编程序闪烁灯与其反汇编代码比较
/* *LED闪烁 *led.s */ #define GPJ0CON 0xE0200240 #define GPJ0DAT 0xE0200244 .global _start //把 _start ...
- STM32点亮闪烁LED灯
详解请看其他博客: http://www.cnblogs.com/whik/p/6672730.html http://www.51hei.com/bbs/dpj-38605-1.html /*本程序 ...
- AVR单片机教程——闪烁LED
上次我们把LED点亮了.你可能已经试过把 LED_RED 换成其他灯,也可能已经用 led_on() 把所有LED一起点亮了.但是LED点亮以后,程序就退出了,之后LED一直没有暗,直到没有供电.这一 ...
- iOS简单动画效果:闪烁、移动、旋转、路径、组合
#define kDegreesToRadian(x) (M_PI * (x) / 180.0) #define kRadianToDegrees(radian) (radian*180.0)/(M_ ...
- stm32点亮LED 测试代码及目录结构
. main.c - 使用PB12, PB13, PB14, PB15, PB5, PB6, PB7 这七个PB口点亮LED. 注意PB3和PB4是特殊口, 直接调用无效. #include &quo ...
- CC2640R2F&TI-RTOS 拿到 TI CC2640R2F 开发板 第三件事就是使用 TI-RTOS 创建 一个任务 和 使用 信号量 超时来闪烁 LED灯
/* * data_process.c * * Created on: 2018年7月5日 * Author: admin */ #include <ti/sysbios/knl/Task.h& ...
- 【Linux 驱动】简单字符设备驱动架构(LED驱动)
本文基于icool210开发板,内核版本:linux2.6.35: 驱动代码: (1)头文件:led.h #ifndef __LED_H__ #define __LED_H__ #define LED ...
- 使用CCS10新建TMS320F28335工程并闪烁LED(流水灯)程序
学习TMS320F28335使用Code Composer Studio 10.4.0下载和安装本文不再叙述. 1. 新建工程 1.1选择目录新建工作区 1.2打开软件界面如下图所示: 1.3选择新建 ...
随机推荐
- Windows7开机登录界面背景图修改
首先,准备一张文件大小不超过250K的.jpg格式图片,文件名为:BackgroundDefault,图片分辨率建议与屏幕分辨率一致,因为这张背景无法像壁纸一样拉伸或者填充的. 打开这个路径,[C:\ ...
- [django]Django站点admin支持中文显示和输入设置
正文: Django站点admin支持中文输入设置,操作如下: 1 需要确定的你的数据库的client客户端和服务端的编码设置为utf-8,如果不是,请将其设置成utf-8编码,我采用mysql,详情 ...
- JustWeTools - 自定义控件集
JustWeTools - Some useful tools 项目地址 JustWe 现在有哪些模块? View自定义控件 PaintView画图工具(包含重构压感新版) CodeView代码编辑 ...
- Eclipse导入MyEclipse创建的web项目报错的解决方法
将myeclipse中开发的动态web项目直接引入到eclipse中继续开发,Eclipse中会报项目有错,如下图
- 怎样用ZBrush对模型进行渲染(二)
继上节课Fisker老师对ZBrush中对渲染和灯光起到重要作用的Light和LightCap进行了具体讲解之后,本节课继续研究Render(渲染)和Light及LightCap相结合会产生什么样的效 ...
- Bootstrap 按钮
本章将通过实例讲解如何使用 Bootstrap 按钮.任何带有 class .btn 的元素都会继承圆角灰色按钮的默认外观.但是 Bootstrap 提供了一些选项来定义按钮的样式,具体如下表所示: ...
- 【转】【C#】C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 在之前的C#基础知识系列文章中只介绍了从C#1.0到C#4.0中主要的特性,然而.NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两 ...
- tensorflow学习笔记三:实例数据下载与读取
一.mnist数据 深度学习的入门实例,一般就是mnist手写数字分类识别,因此我们应该先下载这个数据集. tensorflow提供一个input_data.py文件,专门用于下载mnist数据,我们 ...
- 分享一个自制的 .net线程池
扯淡 由于项目需求,需要开发一些程序去爬取一些网站的信息,算是小爬虫程序吧.爬网页这东西是要经过网络传输,如果程序运行起来串行执行请求爬取,会很慢,我想没人会这样做.为了提高爬取效率,必须使用多线程并 ...
- 跟我从零基础学习Unity3D开发--NGUI入门基础
英雄联盟(撸啊撸) QQ飞车 魔兽世界等等相信大家都玩过游戏吧,玩过那UI知道是什么吧?UI可能说得有点专业的话那么游戏中那些属性面板例如: 现在对UI有一定认识了吧!回想一下您玩过的游戏就一定知道什 ...