STM32汇编语言点亮led灯

首先,这篇blog的主要内容是在C语言中调用汇编语言写的函数。即在我们常用的标准库函数工程中,对外设(这里指led)使用汇编语言完成相关的寄存器配置和控制。

一、背景

课程的需要:微机原理课程设计中,需要使用汇编语言/部分汇编语言进行课程设计的开发。

网上资料的稀缺:汇编相对于高级语言,更加偏向底层,编写代码的效率很低,资料较少,stm32汇编语言与教科书上8086汇编有一些差别,资料更加少。以下引用的例子是网上比较常见的关于stm32使用汇编点亮led灯的教程。

STM32用汇编点亮LED灯

基于 MDK 创建 STM32 汇编程序:串口输出 Hello world

虽然上面两个例子给出了点亮led/串口输出的功能代码,但对其原理方面的描述不是很清晰。

二、预备知识

在keil5中,按F1便可调出ARM内核的工具书,里面包含了ARM内核汇编的指导,如下图所示:

stm32相关的汇编相关的汇编指令

三、STM32中汇编与C语言的调用

常用的两种函数相互调用方式是在C语言中调用汇编函数,在汇编语言中调用C函数。这里仅仅是函数的调用,调用指.c文件调用.s文件中的函数,.s文件调用.c文件中的函数,嵌入代码块与这两种不同。(附:C语言中嵌入汇编代码块)

两种调用方式的具体实现教程可以查阅下面的博客:

两种函数调用方式

四、STM32汇编语言点亮led灯

在C语言中,我们点亮led灯首先需要对led灯对应引脚进行配置,即void LED_INIT(void),对led进行开关,即void LED_ON(void)void LED_OFF(void)。然后我们就可以在main函数中调用这些函数,实现对led的控制。

现在我们的目标是,对void LED_INIT(void)void LED_ON(void)void LED_OFF(void)这三个函数用汇编语言编写,这三个函数位于led.s中,在main.c文件中被main函数调用。

实验平台:stm32f103c8t6、MDK5.28

led引脚:C14、C15

4.1汇编语言实现LED相关配置

  1. 查阅数据手册使能相关的外设时钟和端口C,由下图我们可以得到

端口C的基地址是0x4001 1000,再由上图我们可以知道AHB系统总线通过桥接1和桥接2连接到了APB2和APB1总线,而AHB总线包含RCC时钟控制,GPIOC是属于APB2的,因此我们可以找到时钟使能寄存器的地址即复位和时钟控制RCC的地址是从0x4002 1000开始。

通过查阅数据手册,如上图 所示我们可以知道APB2外设时钟使能寄存器的地址为RCC时钟的地址为+0x18,即RCC_APB2ENR= 0x40021018。找到APB2外设时钟使能寄存器的地址后,需要对其进行赋值,根据参考手册里面描述,第四位为端口C的时钟使能位。因此将第四位赋为1便可以使能端口C的时钟。即0001 0000,对于0x10

使能外设时钟的代码如下:

LDR R0,=RCC_APB2ENR;LDR是把地址装载到寄存器中(比如R0)。
ORR R0,R0,#0x10 ;按位或ORR R0,R1,R2; R0=R1 | R2
LDR R1,=RCC_APB2ENR;R1存了RCC_APB2ENR的地址
STR R0,[R1];使能端口C的时钟

2.接下来配置PC14、PC15为通用输出。

控制LED需要输出高电平或是低电平,所以需要配置为输出。由于STM32的每个IO都需要4个位来配置,所以一个32位的寄存器最大只能配置8个IO(32位的单片机的寄存器就是32位的)。STM32中,用端口配置低寄存器(GPIOx_CRL)来配置引脚Px0-Px7, 用端口配置高寄存器(GPIOx_CRH)来配置引脚Px8-Px15。

配置引脚PC14,PC15使用的寄存器是GPIOC_CRH。下面我们来寻找这个寄存器的地址。

从上图中,我们可以推得到端口C的配置高寄存器为端口C的基地址是0x40011000+0x040x40011004 ,即GPIOC_CRH=0x40011004。PC15、PC14对应位31:28,接下来对该寄存器赋值。

复位值是0x4444 4444,并不是0x0000 0000。所谓的复位值,就是指如果没有操作这个寄存器时,寄存器存放的默认值。复位值按位拆分0x4 = 0b0100,0x表示16进制,0b表示二进制,也就是默认CNF 01,MODE 00,是浮空输入。

我们需要的是输出高低电平,所以要设置为输出。输出模式设置为推挽输出,速度为50MHZ。那么PC15、PC14所对应的位31:28应赋值为:0011 0011

代码如下:

;设置pc14、pc15
LDR R0,=GPIOC_CRH
BIC R0,R0,#0xffffffff ;R0清零
ORR R0,#0x33000000
LDR R1,=GPIOC_CRH
STR R0,[R1]

0x33000000也代表是0011 0011 0000 0000 0000 0000 0000 0000

这里对GPIOC_CRH寄存器进行赋值时可能会改变其他位,进而修改到其他引脚的配置,因此尽可能只改变相应的位,不改变其他位。

2.接下来设置PC14、PC15的初始电平状态。(端口输出数据寄存器)

中文数据手册中偏移地址是0Ch,如上图所示,也可以写为0x0C。0Ch对于一些汇编程序(编译汇编源程序的程序)来说是可行的,因此这种情况下0x0C和0Ch等价,可以参考这个解答。所以引脚PC15的端口输出数据寄存器的地址就是GPIOC_ODR =0x4001 100C。对 位15 置 1 ,引脚PC15便可以输出高电平。如下代码所示:

LDR R1,=GPIOC_ODR
LDR R0,[R1] ;加载GPIOC_ODR寄存器的值
MOV R1,#~(1<<15)
AND R0,R0,R1
LDR R1,=GPIOC_ODR
STR R0,[R1]

因为修改GPIOC_ODR寄存器的值可能会修改到其他位,进而改变其他引脚的电平,因此尽可能只改变相应的位,不修改其他位。这里使用#~(1<<15)R0进行与操作,保证只对 位15 进行操作将 位15 置0,输出低电平。

对C14进行重复操作,这时候是#~(1<<14)

这样就完成了对C14、C15的初始化。即完成了LED_INIT函数

4.2 LED_ON、LED_OFF函数

以PC15为例:

LED3_ON;亮灯PUSH {R0,R1, LR}    LDR R1,=GPIOC_ODRLDR R0,[R1];加载GPIOC_ODR寄存器的值MOV R1,#~(1<<15)AND R0,R0,R1LDR R1,=GPIOC_ODRSTR R0,[R1]POP {R0,R1,PC}

具体是#~(1<<15)还是#(1<<15)需要查看电路的解法,是高电平亮还是低电平亮。

LED3_OFF;熄灯PUSH {R0,R1, LR}    LDR R1,=GPIOC_ODRLDR R0,[R1]MOV R1,#(1<<15)ORR R0,R0,R1LDR R1,=GPIOC_ODRSTR R0,[R1]POP {R0,R1,PC}

4.3 在C中调用汇编语言

在.c文件中声明函数

extern void LED_INIT(void);
extern void LED3_ON(void);
extern void LED3_OFF(void);

然后像正常函数那样调用就可以了。

五、总结

stm32汇编跟8086汇编有些不同,使用stm32汇编进行代码逻辑编写确实有些难度,可以使用stm32汇编进行底层代码的编写,底层涉及到的是寄存器,也就是这篇文章所讲的内容。

代码工程附在最下面。实现的功能是将PS2遥控手柄的数据通过串口发送给上位机。因此可以当做3个模块进行学习:汇编实现LED底层,PS2游戏手柄操控,汇编实现串口底层。

本教程的代码仓库:(路径:user/led.s)

STM32汇编语言点亮led灯

拓展资料:

纯汇编实现led、LCD、串口、按键的代码工程

有问题可以评论/发邮件,191347294@qq.com

STM32汇编语言点亮led灯相关推荐

  1. 野火STM32寄存器点亮LED灯详解

    ** 1.需要先打开RCC总控制信号APB2->GPIOB中IO端口B时钟使能 ** 程序代码为:*(ussigend int *)0x40021018|=(1<<3); ** 2. ...

  2. 【STM32】STM32CubeMX教程二--基本使用(新建工程点亮LED灯)

    前言 在配置好CubeMX之后,就是新建工程的开始了,那么首先我们需要一些准备,本片博客我们会很详细的介绍STM32CubeMx的基本使用和如何创建一个新的工程并且点亮LED灯  面向初学者   如果 ...

  3. 【STM32学习笔记-点亮LED灯】

    STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...

  4. 单片机stm32LED流水灯C语言,STM32单片机入门 篇二:单片机编程:从点亮LED灯开始(二)...

    STM32单片机入门 篇二:单片机编程:从点亮LED灯开始(二) 2019-04-26 13:21:48 19点赞 73收藏 19评论 写在前面的话:本篇是承接上一篇文章,属于小白向. 没看过的朋友点 ...

  5. stm32点亮led灯。

    新手学习stm32 学习32第一个程序就是点亮led灯.本人用的是野火的指南者开发板.先上电路图. 如图所示,为led模块电路图,由图可知,此模块为共阳极.只需将引脚变成低电平即可使led灯亮.此次代 ...

  6. 点亮stm32开发板的led灯

    点亮stm32开发板的led灯 简述 我使用的是STM公司stm32f103系列开发板,我们通过看原理图,对LED进行操作,以实现led灯的控制.(对于小白来说很有作用哈!废话不说,上料!) 1.查看 ...

  7. STM32笔记2-使用库函数点亮LED灯

    目录 一.硬件电路设计 二.软件设计 1.工程配置 2.程序编写 (1)led头文件 (2)Led_Init()函数编写 三.实验测试 四.使用宏定义 1.修改后的led.h中程序 2.修改后的Led ...

  8. STM32之初学点亮led灯

    板子使用的是洋桃电子的开发板,核心板上面的两个led灯连接的是PB0和PB1两个引脚,如下图所示 可以看到这个电路图,如果将PB0的引脚的信号设置为高电平,则电流会从LED灯的左边流向右边,即点亮LE ...

  9. stm32点亮LED灯

    stm32点亮LED灯 野火烧不尽,春风吹又生,我购买的是野火的指南针开发板,接下来我就以发表动态来跟大家一起学习,也可以让我学习这块开发板更有动力,增加印象. 每一块开发板,第一个例程无一例外就是通 ...

最新文章

  1. 【Qt】通过QtCreator源码学习Qt(八):插件生命周期及对应状态(代码走读)
  2. 模板—主席树(待修改)
  3. 并发容器之CopyOnWriteArrayList
  4. 基于jwt的用户鉴权:拦截器概述
  5. mysql explain用法和结果的含义
  6. input发送a.jax_Java EE 7 / JAX-RS 2.0:具有自定义HTTP标头的简单REST API身份验证和授权...
  7. 【牛客 - 1080C】tokitsukaze and Soldier(思维,偏序问题)
  8. eclipse中folder、source folder和package的区别
  9. python如何保存数组_如何在Python中保存2D数组(列表)?
  10. 【浅说】堆(heap)和栈(stack)区别
  11. 多租户数据架构以及hibernate支持(Multi-TenantDataArchitecture)
  12. Atitit 在线机器人 自动化技术一览 目录 1. 俩个要点 1 1.1. 识别控件(对话框 按钮 列表等) 1 1.2. Dom控件操作 1 1.3. 鼠标键盘操作 api 1 2. 可以使用
  13. ghost还原提示an internal
  14. 【C++】字体文件解析(FreeType)
  15. android mp4 画面裁剪,说说Android的视频裁剪(二)
  16. python乘积函数_Python中乘法
  17. python 宏定义函数_python 宏使用详解
  18. 音视频SDK封装截图
  19. 我在CSDN的2022:突破零粉丝,4个月涨粉4000+,2023年目标5万+
  20. 语文科计算机培训心得体会,语文培训心得体会(精选3篇)

热门文章

  1. mac 无法打开22端口 无法远程连接ssh 的解决办法
  2. 远程工具之一---rsync用法介绍
  3. HTML期末作业-我的大学生活
  4. 拉里·埃里森亲自支招,数据库自动化之后,DBA何去何从???
  5. informatica session中bulk和normal模式
  6. Class not found: “xxx.xxx.xxx“报错
  7. 【Java编程练习】司机肇事后逃跑,现场三人半瞎系列
  8. 数据压缩作业1之:使用音频分析软件(Audacity)分析浊音、清音爆破音的时域及频域特性。
  9. 2022年03月05日:宜未雨而绸缪,毋临渴而掘井
  10. Luogu-P2015 二叉苹果树