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. jquery实现表格中点击相应行变色功能
  2. python 下载图片损坏_爬虫爬取出的图片下载出错,图片文件直接损坏
  3. dhcp是哪一层的协议_OSI各个分层分别负责哪些功能?有哪些主要协议?涉及到哪些设备?...
  4. SessionListener失败,退出
  5. 本地提交到yarn_Flink on Yarn三部曲之三:提交Flink任务
  6. Qi v1.2.4 -- WPC官方文档资源下载
  7. 判断系统误差的matlab,基于MATLAB的误差数据处理实验报告
  8. 小米官网服务器维修无法刷机,小米手机无法刷机的解决方法
  9. php 调用qq接口,PHP调用QQ互联接口实现QQ登录网站功能示例
  10. UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xfe in position 198369: illegal multibyte sequenc
  11. linux系统文件名颜色含义
  12. Android IntentService deprecated|笔记
  13. 蓝牙传输速率详细分析【针对蓝牙4.2]
  14. 为了中国---我国民用客机深度报道(第三部分下)
  15. mysql 代理 mycat_使用MyCAT代理MySQL数据库
  16. 如何系统地自学python100天_Github上发布了一个Python学习秘笈,从萌新到王者的100天Python学习之旅...
  17. JZOJ3426. 封印一击
  18. iBase4J是Java的分布式系统架构 使用Springboot整合开源框架
  19. 免费数据集 人工智能训练方面
  20. 微信小程序 云数据库使用(下)

热门文章

  1. reference other engineer's code to explain wheather linux terminal can display matplotlib' figure
  2. outlook修改服务器端口号,Outlook 设置教程
  3. 证件照换背景,excel2步搞定!
  4. Spring aop 循环依赖 Is there an unresolvable circular reference?
  5. 计算机桌面成英文怎样变成中文版,怎样把电脑语言设置成英文
  6. 华为手机刷微博体验更好?技术角度的分析和思考,Android基础72问
  7. vim normal 模式、插入模式、命令行模式
  8. 无线路由的四种加密方式
  9. Eclipse中使用search功能,搜索内容无法多窗口打开
  10. Linux防火墙设置黑白名单