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

news2024/9/27 7:16:58

系列文章目录

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
在这里插入图片描述

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

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

相关文章

flutter 的webview中touchstart和touchend 执行异常问题解决

效果 背景 使用flutter 调用webview内网页&#xff0c;网页内容是监听touchstart和 touchend&#xff0c;触发不同是事件&#xff0c;但是发现每次长按都 手指抬起后 才会执行 touchstart和touchend&#xff0c;满足不了我的需求&#xff0c;我的需求是当手指按下 立即执行touc…

aws emr启动standalone的flink集群

关键组件 Client&#xff0c;代码由客户端获取并做转换&#xff0c;之后提交给JobMangerJobManager&#xff0c;对作业进行中央调度管理&#xff0c;获取到要执行的作业后&#xff0c;会进一步处理转换&#xff0c;然后分发任务给众多的TaskManager。TaskManager&#xff0c;数…

解决mybatis/mybatis plus报错:Invalid bound statement (not found) 的方法汇总

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)问题&#xff0c;即在mybatis中dao接口与mapper配置文件在做映射绑定的时候接口与xml不匹配&#xff0c;要么是找不到&#xff0c;要么是找到了却匹配不到。 我的问题是项目没有把最新的方法x…

操作系统实验--终极逃课方法

找到图片里的这个路径下的文件 &#xff0c;结合当前题目名称&#xff0c;把文件内容全部删除&#xff0c;改为print print的内容为下图左下角的预期输出的内容

Databend 开源周报第 146 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持 Expressio…

Rocky Linux 9.4 正式版发布 - RHEL 100% 1:1 兼容免费发行版

Rocky Linux 9.4 正式版发布 - RHEL 100% 1:1 兼容免费发行版 Rocky Linux 由 CentOS 项目的创始人 Gregory Kurtzer 领导 请访问原文链接&#xff1a;Rocky Linux 9.4 正式版发布 - RHEL 100% 1:1 兼容免费发行版&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处…

20212313 2023-2024-2 《移动平台开发与实践》第5次作业

20212313 2023-2024-2 《移动平台开发与实践》第5次作业 1.实验内容 设计并开发一个地图应用系统。 该实验需提前申请百度API Key&#xff0c;调用接口实现百度地图的定位功能、地图添加覆盖物和显示文本信息。 2.实验过程 2.1 获取SHA1 &#xff08;1&#xff09;打开控制台…

【Python编程】给电脑安装最新的 Python3.12.3

笔者最近更换了新的Win11系统&#xff0c;安装最新的Python版本&#xff08;3.12.3&#xff09;尝尝鲜。据说这个版本存在一些漏洞&#xff0c;笔者将后续更新编程过程中的相关问题&#xff08;如果有&#xff09;。Python3.12.3的安装过程比较简单&#xff0c;在此进行说明。 …

mac下载安装好软件后提示已损坏

mac下载安装好软件后提示已损坏 解决方法&#xff1a; 首先确保系统安全设置已经改为任何来源。 打开任何来源后&#xff0c;到应用程序目录中尝试运行软件&#xff0c;如果仍提示损坏&#xff0c;请在应用图标上&#xff0c;鼠标右键&#xff0c;在弹出菜单中点打开。 如果…

【Pandas】深入解析`pd.read_pickle()`函数

【Pandas】深入解析pd.read_pickle()函数 &#x1f308; 欢迎莅临我的个人主页&#x1f448;这里是我深耕Python编程、机器学习和自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;并乐于分享知识与经验的小天地&#xff01;&#x1f387; &#x1f393; 博主简介&…

WordPress子比主题美化-首页动态的图片展示

WordPress子比主题首页动态的图片展示 WordPress子比主题首页添加动态的图片展示&#xff0c;其他程序也可以用&#xff0c;复制代码到相应位置即可&#xff0c;也可作为指定分类&#xff0c;重点内容等&#xff0c;可以适合各个场景&#xff0c;需要的自取。 图片展示: 教程…

如何搭建个人观测云平台

如何搭建个人观测云平台 安装DataKit什么是DataKit&#xff1f; 仪表板指标管理监控 开通阿里云观测云服务后&#xff0c;在观测云平台页面进行下面的操作。 安装DataKit 什么是DataKit&#xff1f; DataKit 是观测云官方发布的数据采集应用&#xff0c;支持上百种数据的采集…

恢复视频3个攻略:从不同情况下的恢复方法到实践!

随着科技的进步&#xff0c;我们的生活被各种各样的数字内容所包围&#xff0c;其中&#xff0c;视频因其独特的记录性质&#xff0c;承载着许多重要的资料。但不管是自媒体人还是普通人日常生活随手一拍&#xff0c;都会遇到误删视频的情况。为了帮助您找回手机视频&#xff0…

数据挖掘与机器学习——分类算法

目录 机器学习算法最普通分类&#xff1a; 分类算法的定义&#xff1a; 分类算法的应用&#xff1a; 分类器实现分类&#xff1a; 分类器的构建标准&#xff1a; 概率模型&#xff1a; 贝叶斯公式&#xff1a; 朴素贝叶斯算法&#xff08;朴素贝叶斯分类器&#xff09;…

【吊打面试官系列】Java高并发篇 - Java 死锁以及如何避免?

大家好&#xff0c;我是锋哥。今天分享关于 【Java 死锁以及如何避免&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; Java 死锁以及如何避免&#xff1f; Java 中的死锁是一种编程情况&#xff0c;其中两个或多个线程被永久阻塞&#xff0c;Java 死锁情况出现至…

正版软件 | Internet Download Manager 下载管理器

前言 IDM 是一个下载加速器&#xff0c;可将下载速度提高多达 8 倍&#xff0c;恢复、组织和安排下载。 30 天免费试用&#xff01;https://www.internetdownloadmanager.cc/ 新版本 Internet Download Manager v 6.40&#xff1a;添加了 Windows 11 兼容性。改进了媒体采集…

Stable Diffusion AI绘画:从提示词到模型出图的全景指南

&#x1f482; 个人网站:【 摸鱼游戏】【神级代码资源网站】【工具大全】&#x1f91f; 一站式轻松构建小程序、Web网站、移动应用&#xff1a;&#x1f449;注册地址&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交…

微信公众号关注页获取方式

Demo Location 查找步骤 仔细看下链接验证&#xff0c;排查有特点的参数__biz 分析如何获取__biz 查看某个文章线下零食届「拼多多」席卷&#xff0c;「赵一鸣们」如何高效拓店&#xff1f;&#xff0c;查看源代码 ,查找关键词 替换链接并执行

30V MOS管 60VMOS管 100VMOS管 150VMOS管推荐

MOS管&#xff0c;即金属氧化物半导体场效应管&#xff0c;其工作原理是&#xff1a;在P型半导体与N型半导体之间形成PN结&#xff0c;当加在MOS管栅极上的电压改变时&#xff0c;PN结之间的沟道内载流子的数量会随之改变&#xff0c;沟道电阻也会发生改变&#xff0c;进而改变…

Linux如何设置共享文件夹

打开虚拟机->菜单->虚拟机设置->选项->共享文件夹->总是启用。点击添加按钮->弹出添加向导->点击浏览按钮&#xff0c;从windows中选择一个文件夹&#xff0c;确定即可。