看完这篇文章你就彻底懂啦{保姆级讲解}-----(I.MX6U驱动LED灯《使用汇编语言编写》) 2023.4.17

news2025/2/28 15:39:56

目录

    • 前言
    • STM32 知识回顾
    • 完整汇编代码
    • 最终编译验证
    • 结束语

前言

首先我们在开发stm32的时候驱动LED灯会有两种方式,分别是寄存器库函数版本。因为在实际的开发过程中,我们更愿意更习惯用库函数版本来驱动各种外设,但是对于底层的寄存器调用和配置也是我们必须掌握的。由于本篇文章主要讲解在I.MX6U平台上的LED驱动,并且使用汇编语言编写,所以更需要借助寄存器底层来驱动。接下来,我会详细讲解怎么从0开始驱动LED灯。

STM32 知识回顾

我们以最常见的 STM32F103 为例来看一下 STM32 的 GPIO 初始化
在这里插入图片描述
由上图可知,该GPIO初始化代码时由库函数编写的,贴这段代码的主要目的是为了了解驱动GPIO需要进行哪几步操作。分别是:

  1. 使能GPIO对应端口的时钟
  2. 设置GPIO的复用功能
  3. 设置GPIO的输出/输入模式、上下拉、 速度等相关
  4. 通过设置电平高低来控制LED亮灭

那自然而然,在I.MX6U平台上驱动LED灯大致也是如上几个步骤。

完整汇编代码

/*全局标号*/
.global _start 

_start:

/*使能GPIO1——IO03时钟*/
ldr r0, =0x020C4070 
ldr r1, =0xFFFFFFFF 
str r1, [r0]       

/*设置GPIO1——IO03复用为GPIO1——IO03*/
ldr r0, =0x020E0068
ldr r1, =0x5
str r1,[r0]

/*配置GPIO1——IO03的IO属性*/
ldr r0, =0x020E02F4
ldr r1, =0x10B0
str r1,[r0]

/*设置GPIO1——IO03为输出*/
ldr r0, =0x0209C004
ldr r1, =0x0000008
str r1,[r0]

/*打开LED0*/
ldr r0, =0x0209C000
ldr r1, =0
str r1,[r0]

loop:
    b loop

好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写!

.global _start 

_start:

//汇编程序的默认入口标号是_start,可以理解为代码从该处开始运行。上面代码中的.global是声明_start是一个全局标号,此时可联想为_start这个变量是全局变量即可。

ldr r0, =0x020C4070 
ldr r1, =0xFFFFFFFF 
str r1, [r0]   

//接下来我们一行行进行分析,在分析之前,我想先引入几个Cortex-A7汇编指令,由于ARM不能直接访问存储器,比如RAM中的数据,所以我们需要借助汇编指令来访问存储器,从而访问并配置I.MX6UL的寄存器。

  1. 存储器访问指令
    在这里插入图片描述
ldr r0, =0x020C4070

//相当于将0x020C4070赋值给r0。那至于为什么是0x020C4070,这个我们就需要根据I.MX6UL的原理图和参考数据手册了。
其中关于LED灯的原理图如下:
在这里插入图片描述
由上图可知,LED0接到了GPIO_3上,也就是GPIO1_IO03。所以我们需要开启GPIO1_IO03对应的时钟,也就是使能时钟。
在这里插入图片描述

由上图可知,该寄存器的主要作用为CCM的时钟门控寄存器,其中该寄存器的第26~27位也就是CG13为gpio3的时钟使能位,由于有两位,所以实际上会产生4种模式配置,具体如下图所示。

在这里插入图片描述

ldr r1, =0xFFFFFFFF

//相当于将0xFFFFFFFF赋值给r1
//即我们开启gpio3的时钟使能,只需将第26~27位设置为11即可。

str r1, [r0]  

//相当于将r1的值赋值给地址为r0的寄存器,即将0xFFFFFFFF赋值给CCM_CCGR2寄存器,成功对gpio3进行时钟使能。

ldr r0, =0x020E0068
ldr r1, =0x5
str r1,[r0]

//这一部分主要是设置GPIO的复用功能为GPIO1_IO03。

ldr r0, =0x020E0068

//相当于将0x020E0068赋值给r0,至于为什么是0x020E0068,请看下图(数据参考手册)

在这里插入图片描述在这里插入图片描述

//由上图可知,该寄存器可配置位为5位,分别是0 ~ 4位,其中0 ~ 3位为MUX_MODE,其中0101为将GPIO1复用功能设置为GPIO1_IO03。

ldr r1, =0x5

//将0101赋值给r1

str r1,[r0]

//将r1的值赋值给内存地址为r0的寄存器中。

ldr r0, =0x020E02F4
ldr r1, =0x10B0
str r1,[r0]

//这一部分主要功能是配置GPIO1_IO03的IO属性

*bit 16:0 HYS 关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper 功能
*bit [12]: 1 pull/keeper 使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度 100Mhz
*bit [5:3]: 110 R0/6 驱动能力
*bit [0]: 0 低转换率

ldr r0, =0x020E02F4

//相当于将0x020E02F4赋值给r0,至于为什么是0x020E02F4,请看下图(数据参考手册)
在这里插入图片描述在这里插入图片描述在这里插入图片描述

ldr r1, =0x10B0

//配置IO属性,具体配置是什么,请对照上图进行辨认。

str r1,[r0]

//相当于将r1的值赋值给内存地址为r0的寄存器中。

ldr r0, =0x0209C004
ldr r1, =0x00000008
str r1,[r0]

//这一部分主要是设置GPIO1_IO03为输出

ldr r0, =0x0209C004

//相当于将0x0209C004赋值给r0,至于为什么是0x0209C004,请看下图(数据参考手册)
在这里插入图片描述

ldr r1, =0x00000008

//由上图可知,GDIR寄存器是32位的,每一位对应的一个IO,由于我们设置GPIO1_IO3,所以需要将第3为设置为1即可,即0~3位为0001。

str r1,[r0]

//相当于将r1的值赋值给内存地址为r0的寄存器中。

ldr r0, =0x0209C000
ldr r1, =0
str r1,[r0]
ldr r0, =0x0209C000

//相当于将0x0209C000赋值给r0,至于为什么是0x0209C000,请看下图(数据参考手册)
在这里插入图片描述//该寄存器是32位的,每一位对应一个IO,当GPIO设置成输出模式时,向指定的位写入数据那么相应的IO就会输出相应的高低电平。

ldr r1, =0

//相当于将GPIO1_IO3的电平设置成低电平,即对应硬件电路中使其电路导通,从而使得LED保持常亮。

str r1,[r0]

//相当于将r1的值赋值给内存地址为r0的寄存器中。

loop:
    b loop

//死循环,通过b指令,CPU重复不断的跳到loop函数执行,进入一个死循环。

最终编译验证

由于我们只是编写了一个led.s的汇编文件,为了编写方便,我们需要创建Makefile文件。具体Makefile文件内容如下:

led.bin:led.s
 arm-linux-gnueabihf-gcc -g -c led.s -o led.o
 arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
 arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
 arm-linux-gnueabihf-objdump -D led.elf > led.dis
clean:
 rm -rf *.o led.bin led.elf led.dis

然后使用make命令生成led.bin文件即最终烧到开发板中的文件,在本次实验中我们采取烧写到SD卡中(至于怎么烧写到SD卡可以参考正点原子文档),最终实验结果如下:
在这里插入图片描述

结束语

如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/426609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux宝塔安装msyql服务,默认密码,允许远程登录问题解决

一、首先我在宝塔安装mysql服务是5.7 1.1MySQL数据库5.6之前(不包括)默认密码为空,用户不用输入密码,直接回车登陆 mysql -uroot -p password:(空) 1.2.MySQL数据库5.6之后(包括)默认密码是MySQL数据库随机…

Mybatis手动配置ORM,不用自动ORM等操作

一、解决mapper.xml存放在resources以外路径中的读取问题 在pom.xml文件最后追加< build >标签&#xff0c;以便可以将xml文件复制到classes中&#xff0c;并在程序运行时正确读取。 <build><!-- 如果不添加此节点src/main/java目录下的所有配置文件都会被漏掉…

【Android Audio】TimeCheck机制

TimeCheck机制&#xff08;Android R/S&#xff09; TimeCheck.cpp TimeCheck.h frameworks/av/media/utils/TimeCheck.cpp TimeCheck守护线程的作用&#xff1a; 当audioserver中IAudioFlinger&#xff0c;IAudioPolicyService&#xff0c;IEffect中的每一个binder函数调用时…

Web 攻防之业务安全:Callback自定义测试(触发XSS漏洞)

Web 攻防之业务安全&#xff1a;Callback自定义测试 业务安全是指保护业务系统免受安全威胁的措施或手段。广义的业务安全应包括业务运行的软硬件平台&#xff08;操作系统、数据库&#xff0c;中间件等&#xff09;、业务系统自身&#xff08;软件或设备&#xff09;、业务所提…

学习C语言十天了,我实现了仿真自由落体小球『C/C++图形库EasyX』

文章目录&#x1f490;专栏导读文章导读准备工作一、显示一个静止的小球二、显示多个小球使用#define美化代码三、小球下落动画四、利用while循环实现小球下落五、利用if语句实现小球重复下落六、实现小球落地反弹七、实现小球加速下落&#x1f490;专栏导读 &#x1f338;作者…

剪枝与重参第七课:YOLOv8剪枝

目录YOLOv8剪枝前言1.Overview2.Pretrain(option)3.Constrained Training4.Prune4.1 检查BN层的bias4.2 设置阈值和剪枝率4.3 最小剪枝Conv单元的TopConv4.4 最小剪枝Conv单元的BottomConv4.5 Seq剪枝4.6 Detect-FPN剪枝4.7 完整示例代码5.YOLOv8剪枝总结总结YOLOv8剪枝 前言 …

【三十天精通Vue 3】第八天 Vue 3 生命周期钩子详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录引言一、Vue 3 生命周期钩子概述1.1 生命周期钩子的简介1.2 生命周…

mulesoft MCIA 破釜沉舟备考 2023.04.14.11

mulesoft MCIA 破釜沉舟备考 2023.04.14.111. To implement predictive maintenance on its machinery equipment, ACME Tractors has installed thousands of IoT sensors that will send data for each machinery asset as sequences of JMS messages, in near real-time, to…

惠普Probook455电脑开机突然卡住无法进入桌面

惠普Probook455电脑开机突然卡住无法进入桌面解决方法分享。最近有用户使用的惠普Probook455电脑在开机的时候&#xff0c;电脑一直卡在开机的界面上&#xff0c;无法进入到系统中。无论是重启还是安全模式都无法解决问题。那么遇到这个情况怎么去进行问题的解决&#xff0c;来…

C++---状态压缩dp---炮兵阵地(每日一道算法2023.4.16)

注意事项&#xff1a; 本题为"状态压缩dp—蒙德里安的梦想"和"状态压缩dp—小国王"和"状态压缩dp—玉米田"的近似题&#xff0c;建议先阅读这三篇文章并理解。 题目&#xff1a; 司令部的将军们打算在 NM 的网格地图上部署他们的炮兵部队。 一个…

GoogleTest+VS code编译和编写简单测试用例

目录前言一、安装gtest二、 编译gtest与运行单元测试第一种编译方式第二种编译方式前言 在B站看了非常多Gtest的教学视频&#xff0c;CSDN上gtest博客也特别多&#xff0c;但是都非常陈旧或者根本不是用vscode。本篇目的在于&#xff0c;说明如何在vscode上编写简单单元测试。…

day01_Java概述丶环境搭建

Java背景知识 Java概述 概述&#xff1a;计算机语言就是人与计算机之间进行信息交流沟通的一种特殊语言。所谓计算机编程语言&#xff0c;就是人们可以使用编程语言对计算机下达命令&#xff0c;让计算机完成人们需要的功能。 Java语言&#xff1a;是美国Sun公司&#xff08…

Siamese network

文章目录一、相似性度量1. 欧氏距离2. 马氏距离二、Siamese network1. Siamese network 基础架构2. 损失函数3. 不同的Siamese network3.1. 行人重识别3.2 其他应用场景一、相似性度量 相似性度量是机器学习中一个非常基础的概念&#xff0c;是评定两个事物之间相似程度的一种度…

E: 仓库 “http://mirrors.aliyun.com/ubuntu eoan Release” 没有 Release 文件 —— 解决方案

Ubuntu 20.04 更新的时候&#xff0c;遇到如下问题&#xff1a; 可以通过修改源&#xff0c;来进行修复&#xff1a; 1、登录如下网址&#xff1a;LUGs repo file generator 2、选择对应的 Ubuntu 版本&#xff0c;这里我是 Ubuntu 20.04 点击 Download&#xff0c;会下载一个 …

DUBBO注册中心

注册中心上保存四种类型的数据: providers: 服务提供者目录,记录着服务提供者的ip、端口等信息。 consumers: 服务消费者目录,记录服务消费者的元数据信息,服务提供者并不会用到服务消费者的信息,这里要记录消费者的信息,是给服务治理中心(dubbo-admin)使用的。 route…

五分钟排查Linux的健康状态

五分钟排查Linux的健康状态1. CPU1.1 top命令1.2 什么是负载1.3 vmstat2. 内存2.1 观测命令2.2 CPU缓存2.3 HugePage2.4 预先加载3. I/O3.1 观测命令3.2 零拷贝4. 网络参考&#xff1a;《Linux运维实战》、xjjdog 操作系统作为所有程序的载体&#xff0c;对应用的性能影响是非常…

论文阅读 | Interpolated Convolutional Networks for 3D Point Cloud Understanding

前言&#xff1a;ICCV2019点云特征提取点卷积InterpoConv Interpolated Convolutional Networks for 3D Point Cloud Understanding 引言 点云是不规则、无序、且稀疏的 处理这样的点云数据有两大类方法 第一&#xff1a;voxel化 directly rasterize irregular point clouds…

《Netty》从零开始学netty源码(三十八)之PoolSubPage

PoolSubPage 上一节中我们提到了PooledByteBufAllocator类&#xff0c;先看下netty中有关内存的类关系&#xff1a; 从图中可以看到PoolSubPage为最小单位&#xff0c;所以我们先从最小的开始分析&#xff0c;先看下它的属性值&#xff1a; 为了更好的理解这些属性的意义&…

表情包MD编辑器简单使用

&#x1f337;1 表情包 ⭐️&#xff08;1&#xff09;常规表情图标 &#x1f600; &#x1f601; &#x1f602; &#x1f603; &#x1f604; &#x1f605; &#x1f606; &#x1f609; &#x1f60a; &#x1f60b; &#x1f60e; &#x1f60d; &#x1f618; &#x1…

(Deep Learning)交叉验证(Cross Validation)

交叉验证&#xff08;Cross Validation&#xff09; 交叉验证&#xff08;Cross Validation&#xff09;是一种评估模型泛化性能的统计学方法&#xff0c;它比单次划分训练集和测试集的方法更加稳定、全面。 交叉验证不但可以解决数据集中数据量不够大的问题&#xff0c;也可以…