STM32汇编语言点亮led灯
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相关配置
- 查阅数据手册使能相关的外设时钟和端口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+0x04
即0x40011004
,即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灯相关推荐
- 野火STM32寄存器点亮LED灯详解
** 1.需要先打开RCC总控制信号APB2->GPIOB中IO端口B时钟使能 ** 程序代码为:*(ussigend int *)0x40021018|=(1<<3); ** 2. ...
- 【STM32】STM32CubeMX教程二--基本使用(新建工程点亮LED灯)
前言 在配置好CubeMX之后,就是新建工程的开始了,那么首先我们需要一些准备,本片博客我们会很详细的介绍STM32CubeMx的基本使用和如何创建一个新的工程并且点亮LED灯 面向初学者 如果 ...
- 【STM32学习笔记-点亮LED灯】
STM32学习笔记-点亮LED灯 文章目录 STM32学习笔记-点亮LED灯 一.原理图分析 二.代码分析 1.mian函数 2.led.c函数 3.led.h函数 4.函数文件整理 5.LED_In ...
- 单片机stm32LED流水灯C语言,STM32单片机入门 篇二:单片机编程:从点亮LED灯开始(二)...
STM32单片机入门 篇二:单片机编程:从点亮LED灯开始(二) 2019-04-26 13:21:48 19点赞 73收藏 19评论 写在前面的话:本篇是承接上一篇文章,属于小白向. 没看过的朋友点 ...
- stm32点亮led灯。
新手学习stm32 学习32第一个程序就是点亮led灯.本人用的是野火的指南者开发板.先上电路图. 如图所示,为led模块电路图,由图可知,此模块为共阳极.只需将引脚变成低电平即可使led灯亮.此次代 ...
- 点亮stm32开发板的led灯
点亮stm32开发板的led灯 简述 我使用的是STM公司stm32f103系列开发板,我们通过看原理图,对LED进行操作,以实现led灯的控制.(对于小白来说很有作用哈!废话不说,上料!) 1.查看 ...
- STM32笔记2-使用库函数点亮LED灯
目录 一.硬件电路设计 二.软件设计 1.工程配置 2.程序编写 (1)led头文件 (2)Led_Init()函数编写 三.实验测试 四.使用宏定义 1.修改后的led.h中程序 2.修改后的Led ...
- STM32之初学点亮led灯
板子使用的是洋桃电子的开发板,核心板上面的两个led灯连接的是PB0和PB1两个引脚,如下图所示 可以看到这个电路图,如果将PB0的引脚的信号设置为高电平,则电流会从LED灯的左边流向右边,即点亮LE ...
- stm32点亮LED灯
stm32点亮LED灯 野火烧不尽,春风吹又生,我购买的是野火的指南针开发板,接下来我就以发表动态来跟大家一起学习,也可以让我学习这块开发板更有动力,增加印象. 每一块开发板,第一个例程无一例外就是通 ...
最新文章
- jquery实现表格中点击相应行变色功能
- python 下载图片损坏_爬虫爬取出的图片下载出错,图片文件直接损坏
- dhcp是哪一层的协议_OSI各个分层分别负责哪些功能?有哪些主要协议?涉及到哪些设备?...
- SessionListener失败,退出
- 本地提交到yarn_Flink on Yarn三部曲之三:提交Flink任务
- Qi v1.2.4 -- WPC官方文档资源下载
- 判断系统误差的matlab,基于MATLAB的误差数据处理实验报告
- 小米官网服务器维修无法刷机,小米手机无法刷机的解决方法
- php 调用qq接口,PHP调用QQ互联接口实现QQ登录网站功能示例
- UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xfe in position 198369: illegal multibyte sequenc
- linux系统文件名颜色含义
- Android IntentService deprecated|笔记
- 蓝牙传输速率详细分析【针对蓝牙4.2]
- 为了中国---我国民用客机深度报道(第三部分下)
- mysql 代理 mycat_使用MyCAT代理MySQL数据库
- 如何系统地自学python100天_Github上发布了一个Python学习秘笈,从萌新到王者的100天Python学习之旅...
- JZOJ3426. 封印一击
- iBase4J是Java的分布式系统架构 使用Springboot整合开源框架
- 免费数据集 人工智能训练方面
- 微信小程序 云数据库使用(下)
热门文章
- reference other engineer's code to explain wheather linux terminal can display matplotlib' figure
- outlook修改服务器端口号,Outlook 设置教程
- 证件照换背景,excel2步搞定!
- Spring aop 循环依赖 Is there an unresolvable circular reference?
- 计算机桌面成英文怎样变成中文版,怎样把电脑语言设置成英文
- 华为手机刷微博体验更好?技术角度的分析和思考,Android基础72问
- vim normal 模式、插入模式、命令行模式
- 无线路由的四种加密方式
- Eclipse中使用search功能,搜索内容无法多窗口打开
- Linux防火墙设置黑白名单