I.MX6ULL Linux 点灯实验理论及汇编点灯

系列文章目录

I.MX6ULL Linux C语言开发


I.MX6ULL Linux 点灯实验理论

  • 系列文章目录
  • 一、I.MX6ULL GPIO
  • 二、I.MX6ULL IO 命名
  • 三、I.MX6ULL IO 复用
  • 四、I.MX6ULL IO 配置
  • 五、I.MX6ULL GPIO 配置
  • 六、I.MX6ULL GPIO 时钟使能
  • 七、硬件原理分析
  • 八、实验程序编写


一、I.MX6ULL GPIO

一般拿到一款全新的芯片,第一个要做的事情的就是驱动其 GPIO,控制其 GPIO 输
出高低电平

学习 I.MX6U 也一样的,先来学习一下 I.MX6U 的 GPIO,学习方法打开I.MX6NULL手册,然后就是“啃”手册。

总结一下,要将 I.MX6ULL 的 IO 作为 GPIO 使用,我们需要一下几步:
①、使能 GPIO 对应的时钟。
②、设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能。
③、设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度等。
④、第②步已经将 IO 复用为了 GPIO 功能,所以需要配置 GPIO,设置输入/输出、是否使用中断、默认输出电平等。


二、I.MX6ULL IO 命名

I.MX6ULL 参考手册的第 32 章“Chapter 32: IOMUX Controller(IOMUXC)”,第 32 章的书签如图所示:
在这里插入图片描述

从图可以看出,I.MX6ULL 的 IO 分为两类:SNVS 域的和通用的
这两类 IO 本质上都是一样的,我们就有下面的常用 IO 为例,讲解一下 I.MX6ULL 的 IO 命名方式。

图中的形如“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”的就是 GPIO 命名 (General-Purpose Input/Output(通用输入/输出)),命名形式就是“IOMUXC_SW_MUC_CTL_PAD_XX_XX”,后面的“XX_XX”就是 GPIO 命名,比如:GPIO1_IO01、UART1_TX_DATA、JTAG_MOD 等等。I.MX6ULL是根据某个 IO 所拥有的功能来命名的。比如我们一看到GPIO1_IO01 就知道这个肯定能做 GPIO,看到 UART1_TX_DATA 肯定就知道这个 IO 肯定能做为 UART1 的发送引脚。“Chapter 32: IOMUX Controller(IOMUXC)”这一章列出了 I.MX6ULL 的所有 IO,如果你找遍 32 章的书签,你会发现貌似 GPIO 只有 GPIO1_IO00~GPIO1_IO09,难道I.MX6ULL 的 GPIO 只有这 10 个?显然不是的, 我们知道 STM32 的很多 IO 是可以复用为其它功能的,那么 I.MX6ULL 的其它 IO 也 是 可 以 复 用 为 GPIO 功能。
同样的,GPIO1_IO00~GPIO_IO09 也是可以复用为其它外设引脚的,接下来就是 I.MX6ULL IO 复用。


三、I.MX6ULL IO 复用

以“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”这个 IO 为例,打开参考手册的 1568 页,如图所示:

在这里插入图片描述

从图中可以看到有个名为:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00 的寄存器,
寄存器地址为 0X020E005C,这个寄存器是 32 位的,但是只用到了最低 5 位,其中
bit0~bit3(MUX_MODE)就是设置 GPIO1_IO00 的复用功能的。GPIO1_IO00 一共可以复用为 9种功能 IO,分别对应 ALT0~ALT8,其中 ALT5 就是作为 GPIO1_IO00。GPIO1_IO00 还可以作为 I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID 等。这个就是 I.MX6U 的 IO 复用


再看一个“IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA”这个 IO,这个 IO 对应
的复用如图所示:

在这里插入图片描述
同样的,从图可以看出,UART1_TX_DATA 可以复用为 8 种不同功能的 IO,分为
ALT0~ALT5 和 ALT8、ATL9,其中 ALT5 表示 UART1_TX_DATA 可以复用为 GPIO1_IO16。
由此可见,I.MX6U 的 GPIO 不止 GPIO1_IO00~GPIO1_IO09 这 10 个,其它的 IO 都可以复用为 GPIO 来使用。I.MX6U 的 GPIO 一共有 5 组:GPIO1、GPIO2、GPIO3、GPIO4 和 GPIO5,其中 GPIO1 有 32 个 IO,GPIO2 有 22 个 IO,GPIO3 有 29 个 IO、GPIO4 有 29 个 IO,GPIO5最少,只有 12 个 IO,这样一共有 124 个 GPIO。如果只想看每个 IO 能复用什么外设的话可以直接查阅《IMX6ULL 参考手册》的第 4 章“Chapter 4 External Signals and Pin Multiplexing”。如果我们要编写代码,设置某个 IO 的复用功能的话就需要查阅第 32 章“Chapter 32: IOMUX Controller(IOMUXC)”,第 32 章详细的列出了所有 IO 对应的复用配置寄存器。
如果某个 IO 要作为某个外设引脚使用的话,是需要配置复用寄存器的。


四、I.MX6ULL IO 配置

在《I.MX6UL 参考手册》第 30 章“Chapter 30: IOMUXController(IOMUXC)”的书签中,每一个 IO 会出现两次,它们的名字差别很小,不仔细看就看不出来,比如 GPIO1_IO00 有如下两个书签
在这里插入图片描述
上面两个都是跟 GPIO_IO00 有关的寄存器,名字上的区别就是红色部分,一是“MUX”,
一个是“PAD”。IOMUX_SW_MUX_CTL_PAD_GPIO1_IO00 我们前面已经说了,是用来配置GPIO1_IO00 复用功能的,那么 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是做什么的呢?找到这个书签对应的 1787 页,如图所示:

在这里插入图片描述

从图中可以看出,IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 也是个寄存器,寄存器地址为 0X020E02E8。这也是个 32 位寄存器,但是只用到了其中的低 17 位,在看这写位的具体含义之前,先来看一下下图所示的 GPIO 功能图:

在这里插入图片描述
我们对照着图来详细看一下寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 的
各个位的含义:

HYS(bit16):对应图中 HYS,用来使能迟滞比较器,当 IO 作为输入功能的时候有效,用于设置输入接收器的施密特触发器是否使能。如果需要对输入波形进行整形的话可以使能此位。此位为 0 的时候禁止迟滞比较器,为 1 的时候使能迟滞比较器。

PUS(bit15:14):对应图中的 PUS,用来设置上下拉电阻的,一共有四种选项可以选
择,如表所示:
在这里插入图片描述
PUE(bit13):图没有给出来,当 IO 作为输入的时候,这个位用来设置 IO 使用上下拉还是状态保持器。当为 0 的时候使用状态保持器,当为 1 的时候使用上下拉。状态保持器在IO 作为输入的时候才有用,顾名思义,就是当外部电路断电以后此 IO 口可以保持住以前的状态。

PKE(bit12):对应图中的 PKE,此位用来使能或者禁止上下拉/状态保持器功能,为0 时禁止上下拉/状态保持器,为 1 时使能上下拉和状态保持器。
ODE(bit11):对应图中的 ODE,当 IO 作为输出的时候,此位用来禁止或者使能开路输出,此位为 0 的时候禁止开路输出,当此位为 1 的时候就使能开路输出功能。

SPEED(bit7:6):对应图中的 SPEED,当 IO 用作输出的时候,此位用来设置 IO 速度,设置如表所示:
在这里插入图片描述
DSE(bit5:3):对应图 8.1.4.2 中的 DSE,当 IO 用作输出的时候用来设置 IO 的驱动能力,总共有 8 个可选选项,如表所示:

在这里插入图片描述SRE(bit0):对应图 8.1.4.2 中的 SRE,设置压摆率,当此位为 0 的时候是低压摆率,当为 1的时候是高压摆率。这里的压摆率就是 IO 电平跳变所需要的时间,比如从 0 到 1 需要多少时间,时间越小波形就越陡,说明压摆率越高;反之,时间越多波形就越缓,压摆率就越低。如果你的产品要过 EMC 的话那就可以使用小的压摆率,因为波形缓和,如果你当前所使用的 IO做高速通信的话就可以使用高压摆率。

通过上面的介绍,可以看出寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是用来配置 GPIO1_IO00 的,包括速度设置、驱动能力设置、压摆率设置等等。I.MX6U 的 IO 是可以设置速度的


五、I.MX6ULL GPIO 配置

IOMUXC_SW_MUX_CTL_PAD_XX_XX 和 IOMUXC_SW_PAD_CTL_PAD_XX_XX 这两
种寄存器都是配置 IO 的,注意是 IO!不是 GPIO,GPIO 是一个 IO 众多复用功能中的一种。比如 GPIO1_IO00 这个 IO 可以复用为:I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID、ENET1_REF_CLK 、 MQS_RIGHT 、 GPIO1_IO00 、 ENET1_1588_EVENT0_IN 、SRC_SYSTEM_RESET 和 WDOG3_WDOG_B 这 9 个功能,GPIO1_IO00 是其中的一种,我们想要把 GPIO1_IO00 用作哪个外设就复用为哪个外设功能即可。如果我们要用 GPIO1_IO00 来点个灯、作为按键输入啥的就是使用其 GPIO(通用输入输出)的功能。将其复用为 GPIO 以后还需要对其 GPIO 的功能进行配置,关于 I.MX6U 的 GPIO 请参考《IMX6UL 参考手册》的第 26章“Chapter 26 General Purpose Input/Ouput(GPIO)”,GPIO 结构如图所示:

在这里插入图片描述
在图中的左下角 的 IOMUXC 框 图 里 面 就 有 SW_MUX_CTL_PAD_* 和
SW_PAD_CTL_PAD_*两种寄存器。这两种寄存器前面说了用来设置 IO 的复用功能和 IO 属性配置。左上角部分的 GPIO 框图就是,当 IO 用作 GPIO 的时候需要设置的寄存器,一共有八个:
DR、GDIR、PSR、ICR1、ICR2、EDGE_SEL、IMR 和 ISR。 前面我们说了 I.MX6U 一共有GPIO1~GPIO5 共五组 GPIO,每组 GPIO 都有这 8 个寄存器。我们来看一下这 8 个寄存器都是什么含义。


DR 寄存器此寄存器是数据寄存器,结构图如图所示:

在这里插入图片描述

此寄存器是 32 位的,一个 GPIO 组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应一个 GPIO。当 GPIO 被配置为输出功能以后,向指定的位写入数据那么相应的 IO 就会输出相应的高低电平,比如要设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1。当 GPIO被配置为输入模式以后,此寄存器就保存着对应 IO 的电平值,每个位对对应一个 GPIO,例如,当 GPIO1_IO00 这个引脚接地的话,那么 GPIO1.DR 的 bit0 就是 0。


GDIR 寄存器,这是方向寄存器,用来设置某个 GPIO 的工作方向的,即输入/输出
GDIR 寄存器结构如图所示:

在这里插入图片描述
GDIR 寄存器也是 32 位的,此寄存器用来设置某个 IO 的工作方向,是输入还是输出。同样的,每个 IO 对应一个位,如果要设置 GPIO 为输入的话就设置相应的位为 0,如果要设置为输出的话就设置为 1。比如要设置 GPIO1_IO00 为输入,那GPIO1.GDIR=0;


PSR 寄存器,这是 GPIO 状态寄存器
如图所示:

在这里插入图片描述
同样的 PSR 寄存器也是一个 GPIO 对应一个位,读取相应的位即可获取对应的 GPIO 的状态,也就是 GPIO 的高低电平值。功能和输入状态下的 DR 寄存器一样。


ICR1和ICR2这两个寄存器,都是中断控制寄存器,ICR1用于配置低16个GPIO,
ICR2 用于配置高 16 个 GPIO

ICR1 寄存器如图所示:

在这里插入图片描述

ICR1 用于 IO0~15 的配置, ICR2 用于 IO16~31 的配置。ICR1 寄存器中一个 GPIO 用两个
位,这两个位用来配置中断的触发方式,可配置的选线如表 所示:位设置

在这里插入图片描述
以GPIO1_IO15为例,如果要设置GPIO1_IO15为上升沿触发中断,那么GPIO1.ICR1=2<<30,
如果要设置 GPIO1 的 IO16~31 的话就需要设置 ICR2 寄存器了。


IMR 寄存器,这是中断屏蔽寄存器

如图所示:

在这里插入图片描述IMR 寄存器也是一个 GPIO 对应一个位,IMR 寄存器用来控制 GPIO 的中断禁止和使能,如果使能某个 GPIO 的中断,那么设置相应的位为 1 即可,反之,如果要禁止中断,那么就设置相应的位为 0 即可。例如,要使能 GPIO1_IO00 的中断,那么就可以设置 GPIO1.MIR=1 即可。


寄存器 ISR,ISR 是中断状态寄存器

寄存器如图所示:

在这里插入图片描述

ISR 寄存器也是 32 位寄存器,一个 GPIO 对应一个位,只要某个 GPIO 的中断发生,那么ISR 中相应的位就会被置 1。所以,我们可以通过读取 ISR 寄存器来判断 GPIO 中断是否发生,相当于 ISR 中的这些位就是中断标志位。当我们处理完中断以后,必须清除中断标志位,清除方法就是向 ISR 中相应的位写 1,也就是写 1 清零。


EDGE_SEL 寄存器,这是边沿选择寄存器

寄存器如图所示:

在这里插入图片描述
EDGE_SEL 寄存器用来设置边沿中断,这个寄存器会覆盖 ICR1 和 ICR2 的设置,同样是一个 GPIO 对应一个位。如果相应的位被置 1,那么就相当与设置了对应的 GPIO 是上升沿和下降沿(双边沿)触发。例如,我们设置 GPIO1.EDGE_SEL=1,那么就表示 GPIO1_IO01 是双边沿触发中断,无论 GFPIO1_CR1 的设置为多少,都是双边沿触发。
关于 GPIO 的寄存器就讲解到这里,因为 GPIO 是最常用的功能,我们详细的讲解了 GPIO的 8 个寄存器。I.MX6U 的 IO 是需要配置和输出的、是可以设置输出高低电平,也可以读取 GPIO 对应的电平。


六、I.MX6ULL GPIO 时钟使能

I.MX6ULL每个外设的时钟都可以独立的使能或禁止,这样可以关闭掉不使用的外设时钟,起到省电的目的。I.MX6U 的系统时钟参考《I.MX6UL 参考手册》的第 18 章“Chapter 18: Clock Controller Module(CCM)”,这一章主要讲解 I.MX6U 的时钟系统,很复杂。我们先不研究 I.MX6U的时钟系统,我们只看一下 CCM 里 面 的 外 设 时 钟 使 能 寄 存 器 。 CMM 有CCM_CCGR0~CCM_CCGR6 这 7 个寄存器,这 7 个寄存器控制着 I.MX6U 的所有外设时钟开关,我们以 CCM_CCGR0 为例来看一下如何禁止或使能一个外设的时钟,CCM_CCGR0 结构体如图所示:
在这里插入图片描述CCM_CCGR0 是个 32 位寄存器,其中每 2 位控制一个外设的时钟,比如 bit31:30 控制着GPIO2 的外设时钟,两个位就有 4 种操作方式,如表所示:

在这里插入图片描述根据表中的位设置,如果我们要打开 GPIO2 的外设时钟,那么只需要设置
CCM_CCGR0 的 bit31 和 bit30 都为 1 即可,也就是 CCM_CCGR0=3 << 30。反之,如果要关闭GPIO2 的 外 设 时 钟 , 那 就 设 置 CCM_CCGR0 的 bit31 和 bit30 都 为 0 即可。
CCM_CCGR0~CCM_CCGR6 这 7 个寄存器操作都是类似的,只是不同的寄存器对应不同的外设时钟而已,为了方便开发,本教程后面所有的例程将 I.MX6U 的所有外设时钟都打开了。


总结一下,要将 I.MX6ULL 的 IO 作为 GPIO 使用,我们需要一下几步:
①、使能 GPIO 对应的时钟。
②、设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX,设置 IO 的复用功能,使其复用为 GPIO 功能。
③、设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX,设置 IO 的上下拉、速度等。
④、第②步已经将 IO 复用为了 GPIO 功能,所以需要配置 GPIO,设置输入/输出、是否使用中断、默认输出电平等。


七、硬件原理分析

打开 I.MX6U-ALPHA 开发板底板原理图,I.MX6UALPHA 开发板上有一个 LED 灯,原理图如下所示:
在这里插入图片描述
从图可以看出,LED0 接到了 GPIO_3 上,GPIO_3 就是 GPIO1_IO03,当 GPIO1_IO03
输出低电平(0)的时候发光二极管 LED0 就会导通点亮,当 GPIO1_IO03 输出高电平(1)的时候发光二极管 LED0 不会导通,因此 LED0 也就不会点亮。所以 LED0 的亮灭取决于 GPIO1_IO03的输出电平,输出 0 就亮,输出 1 就灭。


八、实验程序编写

我们需要对 GPIO1_IO03 做如下设置:
1、使能 GPIO1 时钟GPIO1 的时钟由 CCM_CCGR1 的 bit27 和 bit26 这两个位控制,将这两个位都设置位 11 即可。将 I.MX6U 的所有外设时钟都已经打开了,因此这一步可以不用做。
2、设置 GPIO1_IO03 的复用功能找到 GPIO1_IO03 的复用寄存器“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03”的地址为0X020E0068,然后设置此寄存器,将 GPIO1_IO03 这个 IO 复用为 GPIO 功能,也就是 ALT5。
3、配置 GPIO1_IO03
找到 GPIO1_IO03 的配置寄存器“IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03”的地址为0X020E02F4,根据实际使用情况,配置此寄存器。
4、设置 GPIO
将 GPIO1_IO03 复用为了 GPIO 功能,所以我们需要配置 GPIO。找到 GPIO3 对
应的 GPIO 组寄存器地址,在《IMX6ULL 参考手册》的 1357 页,如图所示:
在这里插入图片描述本实验中 GPIO1_IO03 是作为输出功能的,因此 GPIO1_GDIR 的 bit3 要设置为 1,表示输出

5、控制 GPIO 的输出电平
经过前面几步,GPIO1_IO03 已经配置好了,只需要向 GPIO1_DR 寄存器的 bit3 写入 0 即可控制 GPIO1_IO03 输出低电平,打开 LED,向 bit3 写入 1 可控制 GPIO1_IO03 输出高电平,关闭 LED。

所有的裸机实验我们都在 Ubuntu 下完成,使用 VSCode 编辑器!
既然是实验,肯定要自己动手创建工程,新建一个名为“1_leds”的文件夹,然后在“1_leds”这个目录下新建一个名为“led.s”的汇编文件和一个名为“.vscode”的目录,创建好以后“1_leds”文件夹
.vscode 文件夹里面存放 VSCode 的工程文件,led.s 就是我们新建的汇编文件,
在 led.s 这个文件中编写汇编程序。使用 VSCode 打开 1_leds 这个文件夹,打开以后
如图所示:
在这里插入图片描述
在 led.s 中输入如下代码:

1
2 .global _start /* 全局标号 */
3 
4 /*
5 * 描述: _start 函数,程序从此函数开始执行此函数完成时钟使能、
6 * GPIO 初始化、最终控制 GPIO 输出低电平来点亮 LED 灯。
7 */
8 _start:
9 /* 例程代码 */
10 /* 1、使能所有时钟 */
11 ldr r0, =0X020C4068 /* 寄存器 CCGR0 */
12 ldr r1, =0XFFFFFFFF 
13 str r1, [r0] 
14 
15 ldr r0, =0X020C406C /* 寄存器 CCGR1 */
16 str r1, [r0]
17
18 ldr r0, =0X020C4070 /* 寄存器 CCGR2 */
19 str r1, [r0]
20 
21 ldr r0, =0X020C4074 /* 寄存器 CCGR3 */
22 str r1, [r0]
23 
24 ldr r0, =0X020C4078 /* 寄存器 CCGR4 */
25 str r1, [r0]
26 
27 ldr r0, =0X020C407C /* 寄存器 CCGR5 */
28 str r1, [r0]
29 
30 ldr r0, =0X020C4080 /* 寄存器 CCGR6 */
31 str r1, [r0]
32 
33
34 /* 2、设置 GPIO1_IO03 复用为 GPIO1_IO03 */
35 ldr r0, =0X020E0068 /* 将寄存器 SW_MUX_GPIO1_IO03_BASE 加载到 r0 中 */
36 ldr r1, =0X5 /* 设置寄存器 SW_MUX_GPIO1_IO03_BASE 的 MUX_MODE 为 5 */
37 str r1,[r0]
38
39 /* 3、配置 GPIO1_IO03 的 IO 属性 
40 *bit 16:0 HYS 关闭
41 *bit [15:14]: 00 默认下拉
42 *bit [13]: 0 kepper 功能
43 *bit [12]: 1 pull/keeper 使能
44 *bit [11]: 0 关闭开路输出
45 *bit [7:6]: 10 速度 100Mhz
46 *bit [5:3]: 110 R0/6 驱动能力
47 *bit [0]: 0 低转换率
48 */
49 ldr r0, =0X020E02F4 /*寄存器 SW_PAD_GPIO1_IO03_BASE */
50 ldr r1, =0X10B0
51 str r1,[r0]
52
53 /* 4、设置 GPIO1_IO03 为输出 */
54 ldr r0, =0X0209C004 /*寄存器 GPIO1_GDIR */
55 ldr r1, =0X0000008 
56 str r1,[r0]
57
58 /* 5、打开 LED0
59 * 设置 GPIO1_IO03 输出低电平
60 */
61 ldr r0, =0X0209C000 /*寄存器 GPIO1_DR */
62 ldr r1, =0 
63 str r1,[r0]
64
65 /*
66 * 描述: loop 死循环
67 */
68 loop:
69 b loop

第 2 行定义了一个全局标号_start,代码就是从_start 这个标号开始顺序往下执行的。
第 11 行使用 ldr 指令向寄存器 r0 写入 0X020C4068,也就是 r0=0X020C4068,这个是
CCM_CCGR0 寄存器的地址。
第 12 行使用 ldr 指令向寄存器 r1 写入 0XFFFFFFFF,也就是 r1=0XFFFFFFFF。因为要开启所有的外设时钟,因此 CCM_CCGR0~CCM_CCGR6 所有寄存器的 32 位都要置 1,也就是写入 0XFFFFFFFF。
第 13 行使用 str 将 r1 中的值写入到 r0 所保存的地址中去,也就是给 0X020C4068 这个地址写入 0XFFFFFFFF,相当于 CCM_CCGR0=0XFFFFFFFF,就是打开CCM_CCGR0 寄存器所控制的所有外设时钟。
第 15~31 行都是向 CCM_CCGRX(X=1~6)寄存器写入 0XFFFFFFFF。这样我就通过汇编代
码使能了 I.MX6U 的所有外设时钟。
第35~37行是设置GPIO1_IO03的复用功能,GPIO1_IO03的复用寄存器地址为0X020E0068,寄存器 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 的 MUX_MODE 设置为 5 就是将GPIO1_IO03 设置为 GPIO。
第 49~51 行 是 设 置 GPIO1_IO03 的 配 置 寄 存 器 , 也 就 是 寄 存 器
IOMUX_SW_PAD_CTL_PAD_GPIO1_IO03 的值,此寄存器地址为 0X020E02F4,代码里面已经给出了这个寄存器详细的位设置。
第 54~63 行是设置 GPIO 功能,经过上面几步操作,GPIO1_IO03 这个 IO 已经被配置为了GPIO 功能,所以还需要设置跟 GPIO 有关的寄存器。第 54~56 行是设置 GPIO1->GDIR 寄存器,
将 GPIO1_IO03 设置为输出模式,也就是寄存器的 GPIO1_GDIR 的 bit3 置 1。
第 61~63 行设置 GPIO1->DR 寄存器,也就是设置 GPIO1_IO03 的输出,我们要点亮开发板上的 LED0,那么 GPIO1_IO03 就必须输出低电平,所以这里设置 GPIO1_DR 寄存器为 0。
第 68~69 行是死循环,通过 b 指令,CPU 重复不断的跳到 loop 函数执行,进入一个死循环。


END
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式进阶——外部中断(EXTI)

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 STC8H中断外部中断外部中断编写配置外部中断调用中断触发函数 外部中断测试测试外部中断0测试外部中断2、3或者4 PCB中断设计 STC8…

Unity 生成模版代码

1、创建模版代码文本 using System.Collections; using System.Collections.Generic; using UnityEngine;public class ClassNameScritpItem : MonoBehaviour {public GameObject go;// Start is called before the first frame updatevoid Start(){go new GameObject();}// …

驱动开发学习之新旧字符设备接口,自动创建设备的点灯

1.前言 本章将介绍新旧字符设备接口,以及自动创建设备节点的点灯实验。 2.实验原理介绍 2.1.寄存器知识 学习过单片机的兄弟都知道&#xff0c;点灯有以下步骤&#xff1a; &#xff08;1&#xff09;开启相应的GPIO时钟 &#xff08;2&#xff09;如果需要配置复用&…

聊聊如何感知项目引入哪些功能特性

前言 使用过springcloud全家桶朋友&#xff0c;应该知道springcloud涉及的组件很多&#xff0c;为了让开发者快速了解项目引入了springcloud哪些组件&#xff0c;springcloud引入了HasFeatures&#xff0c;配合Actuator&#xff0c;可以让开发者感知到项目引入的组件功能类型、…

C++ std::reference_wrapper:让引用更强大

std::reference_wrapper 的通俗易懂解释 一、简介二、std::reference_wrapper 的初衷三、常用示例3.1、与 make_pair 和 make_tuple 一起使用3.2、引用容器3.3、通过 std::thread 按引用传递参数给启动函数3.4、引用作为类成员3.5、按引用传递函数对象3.6、与绑定表达式一起使用…

苹果手机备忘录共享到微信,为何显示不支持的类型

作为一名苹果手机用户&#xff0c;我深知其系统的流畅与便捷。然而&#xff0c;在日常使用中&#xff0c;我发现了一个令人不解的问题&#xff1a;为何苹果手机的原生备忘录无法直接分享到微信&#xff1f;每次当我尝试将备忘录里的内容共享给微信好友时&#xff0c;总会遇到“…

代码随想录算法训练营第四十二天|62.不同路径、63. 不同路径 II

62.不同路径 文档讲解&#xff1a;代码随想录 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 记录每个格子的状态 二维矩阵-->二维dp数组 dp数组 题目是要求到达最后一个格子有多少种路径 所以dp[i,j]: 到达第(i,j)个格子有多少种路径 递推公式 到达一…

WPS文件没有保存怎么恢复?5个解决方案轻松恢复!

“我在WPS上编辑了一个文件&#xff0c;但是还没来得及将它保存&#xff0c;我不小心就退出软件了&#xff0c;现在不知道有什么方法可以恢复WPS文件呢&#xff1f;大家可以帮帮我吗” WPS作为一款功能强大且用户友好的软件&#xff0c;给我们的工作带来了很多的便利。但我们在…

记录一次内存取证

1.情景复现 我姐姐的电脑坏了。我们非常幸运地恢复了这个内存转储。你的工作是从系统中获取她所有的重要文件。根据我们的记忆&#xff0c;我们突然看到一个黑色的窗口弹出&#xff0c;上面有一些正在执行的东西。崩溃发生时&#xff0c;她正试图画一些东西。这就是我们从崩溃…

# WIN10/WIN11 找不到【应用商店 Microsoft.WindowsStore】怎么办?

WIN10/WIN11 找不到【应用商店 Microsoft.WindowsStore】怎么办&#xff1f; 解决方法&#xff1a; 1、右键【开始】菜单&#xff0c;点击【Windows PowerShell (管理员)】&#xff0c;输入&#xff1a; Get-AppxPackage -allusers | Select Name, PackageFullName 2、查询…

期望薪资30k字节java2面,A给B转账的同时B给A转账怎么并发量最高

一面 1、自我介绍 2、详细介绍一下自己的做的项目&#xff1f;根据项目提了一些问题 3、hashmap原理 4、B树原理&#xff1f; 5、final禁止重排序原理&#xff1f; 6、设计一个榨汁机类&#xff0c;面向对象怎么设计&#xff1f; 7、get、post区别&#xff0c;使用场景&…

AI大模型探索之路-实战篇9:探究Agent智能数据分析平台的架构与功能

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5&#xff1a;探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6&#xff1a;掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…

kettle学习之子映射组件

映射组件就跟java中的函数方法一样&#xff0c;类似一个子流程。 练习开始 根据数据库表中的id查询出想要的字段&#xff0c;并把字段存到excel表中 一、表输入 二、子映射 映射输入规范&#xff0c;类似java方法中的形参 name vsxcd是方法返回的参数 三、excel输出 运行结果…

前端基于word模板导出word文档

项目环境 vue2 js vue-cli等 依赖包都可以在npm官网找到对应文档 npm官网(英文) 1、依赖 安装依赖 docxtemplater npm i docxtemplaterfile-saver npm i file-saverjszip-utils npm i jszip-utilsjszip npm i jszip在对应页面或模块中引入依赖 import Docxtemplater …

关于(苍穹外卖)Cache问题的一点困惑与思路

因为本人&#xff0c;em---昨天看的&#xff0c;今天早上就有点迷惑了&#xff0c;在这里记录一下&#xff0c;并捋一下思路&#xff0c; 首先要明确的一点就是&#xff0c;我们是在uesr端进行缓存的&#xff0c;并且&#xff0c;菜品缓存是中的key是 String key "dish…

ora-00392 ora-00312错误处理

检查当前日志组状态 对日志组进行clear操作 重新开库无报错

CSS 一些常见的大坝设备仪器标识绘制

文章目录 需求分析1. 坝基测压管2. 坝体测压管3. 竖向位移兼水平位移测点4. 竖向位移测点5. 三角量水堰6. 水平位移观测工作基点7. 竖向位移观测水准基点8. 其他 需求 绘制一些常见的设备仪器标识符 分析 1. 坝基测压管 <!DOCTYPE html> <html lang"en"…

中国1KM分辨率年平均气温数据集

该数据为中国逐年平均温度数据&#xff0c;空间分辨率为0.0083333&#xff08;约1km&#xff09;&#xff0c;时间为1901年-2022年。该数据集是根据全国2472个气象观测点数据进行插值获取&#xff0c;验证结果可信。本数据集包含的地理空间范围是全国主要陆地&#xff08;包含港…

【ARM+Codesys案例】基于全志T3+Codesys的快递物流单件分离器控制系统

物流涉及国计民生&#xff0c;是在社会发展中不可或缺的一环。随着社会的改革开放&#xff0c;工业发展迅猛&#xff0c;此时也伴随着物流业的快速发展。电商、快递等行业业务量爆发以及人工成本的不断上涨&#xff0c;自动化输送分拣设备市场呈现井喷式发展。物流行业从传统方…

探索智能零售的未来商机与运营策略

探索智能零售的未来商机与运营策略 在智能零售的广阔图景中&#xff0c;无人售货机加盟赫然矗立为一股不可小觑的力量&#xff0c;预示着零售业态未来的转型与机遇。其核心优势多维展开&#xff0c;具体阐述如下&#xff1a; 1. **全天候服务**&#xff1a;无人售货机的运行跨…