一 打开电路原理图(LED 指示电路)的进行系统分析

1. 电路功能概述
该电路通过一个限流电阻驱动红色发光二极管(LED),用于指示系统中某一信号(标注为 LED0)的状态。其主要作用是提供可视化状态提示,如电源指示、运行指示或其他逻辑信号反馈。
2. 元器件逐项分析
2.1 电源端(DCDC_3V3)
-
功能:为 LED 指示电路提供 3.3V 的直流电源。
-
说明:3.3V 是 MCU、模块或低功耗系统常用的电压,适合驱动普通红光 LED。
2.2 R9 电阻(510R)
-
类型:510 Ω 限流电阻
-
主要作用:
-
限制流经 LED 的电流,防止 LED 过流损坏。
-
使 LED 工作在安全且亮度适宜的区间。
-
-
计算示例(用于设计分析):
-
红色 LED 正向压降(Vf)典型值:1.8V
-
电源电压:3.3V
-
电阻值:510Ω
电流约为:
I ≈ (3.3V - 1.8V) / 510Ω ≈ 2.94mA
该电流处于常规红色 LED 的安全工作范围内,亮度适中,适合作为指示灯。
-
2.3 DS0(RED LED)
-
类型:红色发光二极管(标注为 RED)
-
功能:
- 在有电流流过时发光,用于视觉指示电路是否处于激活状态。
-
连接方式:
-
阳极连接至限流电阻 R9;
-
阴极通过 LED0 节点接入后级电路(通常为 MCU 的 GPIO、逻辑控制信号端或接地路径)。
-
-
工作模式推断 :
LED 方向显示出阴极接向 LED0,因此常用配置是:
-
当 LED0 信号为低电平(如逻辑 0 / GND)时,电流自 3.3V → R9 → LED → LED0 流动,LED 点亮。
-
当 LED0 为高电平或高阻态时,LED 熄灭。
这种方式称为 低电平点亮(Active Low)。
-
3. 电路总体工作原理
-
正常点亮条件 :
LED0 被拉低(接地或输出低电平)。
此时电流路径为:
3.3V → R9(限流) → 红色 LED(DS0) → LED0 → 地
LED 点亮。
-
熄灭条件 :
LED0 被拉高(接近 3.3V)或处于高阻态。
电流无法形成足够的压差驱动 LED,LED 熄灭。
-
驱动特性总结:
-
该 LED 由 3.3V 供电;
-
LED0 为控制端,逻辑低电平时 LED 点亮;
-
LED 电流由 R9 限制,约 3mA。
-
4. 设计合理性分析
-
510Ω 限流电阻用于 3.3V 系统驱动红光 LED 非常常见,可确保 LED 长期可靠运行。
-
低电平点亮逻辑符合大多数 MCU GPIO 下拉驱动能力强于上拉的实际条件。
-
电路简单,可靠性高,适用于状态指示等非关键负载。
5. 小结
该 LED 电路由 3.3V 电源、510Ω 限流电阻和一个红色 LED 构成,采用低电平点亮的驱动方式。通过限流电阻确保 LED 在安全电流范围内工作。当控制端 LED0 输出低电平时,LED 点亮;当其为高电平或高阻态时,LED 熄灭。本电路结构简洁、成本低廉,并广泛用于系统状态指示。
二 追踪与连接关系


-
外设板上的红色指示灯 DS0 的阴极节点标记为 LED0(前一次图示)。
-
在 CORE 原理图(CPU 引脚页)中,存在一根标注为 GPIO_3 / LED0 的信号线(与 CPU 某个引脚相连),即 LED0 被直接连到 CPU 的一个可配置 IO(这里标称为 GPIO3)。
-
限流电阻 R9(510Ω) 在 LED 的阳极侧、接到 3.3V 电源,因而电流路径为:3.3V → R9 → LED(DS0)→ LED0 → CPU_IO(GPIO3)→ GND(当 GPIO 输出低)。
三 查找参考手册 并初始化GPIO
1. 使能 GPIO 模块时钟(Enable GPIO Clock)
多数处理器上 GPIO 模块在使用前必须开启时钟,否则引脚无法读写。
典型操作如:
-
STM32:
__HAL_RCC_GPIOx_CLK_ENABLE() -
i.MX 系列:CCM (Clock Control Module) 中配置 IOMUXC 和 GPIO 模块时钟
-
Linux 设备树:自动由驱动控制,只需在 DTS 写 pinctrl

一、从截图直接得出的"关键信息"
1️⃣ 寄存器
-
寄存器名称 :
CCM_CCGR2 -
地址 :
0x20C_4070
这是 GPIO3 时钟门控所在的寄存器。
2️⃣ GPIO3 对应的 CG 位(截图已明确给出)
在 CCM_CCGR2 field descriptions 表中:
27--26 CG13 gpio3 clock (gpio3_clk_enable)
结论非常明确:
| 模块 | CCGR | CG | 位段 |
|---|---|---|---|
| GPIO3 | CCM_CCGR2 | CG13 | bits[27:26] |
二、CG13 两位的取值含义(必须理解)
根据参考手册中 CGR value 表:

| CG13 值 | 含义 |
|---|---|
00 |
GPIO3 时钟关闭 |
01 |
仅 RUN 模式有时钟 |
11 |
RUN / WAIT 模式都有时钟(推荐) |
GPIO 标准配置结论
GPIO3:CG13 =
0b11
这是 GPIO 使用中的工程推荐配置。
三、这一"第一步"到底在干什么
写 CG13 = 11 的实际效果
-
给 GPIO3 模块 提供 IPG 时钟
-
允许访问:
-
GPIO3_DR -
GPIO3_GDIR -
GPIO3_PSR
-
-
后续 IOMUX / GPIO 操作才会生效
如果不做这一步
-
GPIO3 寄存器写了 ≈ 没写
-
引脚不翻转、不响应
-
调试时最容易踩坑
四、代码级实现(严格对应截图)
1️⃣ 宏定义
cpp
#define CCM_CCGR2 (*(volatile uint32_t *)0x20C4070)
2️⃣ 使能 GPIO3 时钟(推荐写法)
cpp
/* Enable GPIO3 clock: CG13 (bits[27:26]) = 0b11 */
CCM_CCGR2 = (CCM_CCGR2 & ~(0x3 << 26)) | (0x3 << 26);
3️⃣ 简化写法(确认不影响其他位时)
cpp
CCM_CCGR2 |= (0x3 << 26);
五、结合复位值再理解一次(截图中的 Reset 行)
截图显示:
- CG13 复位值是
1 1(即11)
说明:
-
上电后 GPIO3 时钟默认是开的
-
但在以下情况中可能被关闭:
-
Bootloader / Linux 关闭不用的外设
-
低功耗流程
-
用户代码误操作
-
初始化阶段显式再开一次,是规范做法
2. 配置引脚复用(Pin Multiplexing / IOMUX)
GPIO 引脚通常具备多种功能(如 UART、I2C、PWM)。使用 GPIO 前必须将引脚切换到 GPIO 模式。
流程包括:
-
选择该引脚对应的 MUX 模式为 GPIO
-
设置 SION(input select)或 MUX_MODE(不同平台名称不同)
示例(i.MX6ULL):
- IOMUXC_SW_MUX_CTL_PAD_xxx 寄存器 →
MUX_MODE = 5(GPIO 模式示例)

1、这一步在 GPIO 初始化中的位置
典型 GPIO 初始化流程(以 i.MX 系列为例):
-
IOMUX:配置引脚复用(MUX) ← 你当前问的就是这一步
-
IOMUX:配置 PAD 属性(上下拉、驱动能力、速度等)
-
GPIO 模块配置(方向、输出值、中断等)
第 2 步的目标只有一个:
告诉芯片:这个 PAD 到底是给谁用(GPIO 还是某个外设)
2、寄存器总体说明
寄存器名称
cpp
IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03
寄存器地址
cpp
0x20E_0068
关键可配置位
只有两个字段是你真正需要关心的:
| 位 | 字段名 | 作用 |
|---|---|---|
| [4] | SION | Software Input On |
| [3:0] | MUX_MODE | 选择引脚功能 |
其余 31--5 位全部是 Reserved,不能改。
3、MUX_MODE:选择"这个脚到底干什么"
1️⃣ MUX_MODE 字段说明(位 [3:0])
这是最关键的字段。
截图中给出了 GPIO1_IO03 支持的复用功能:
| MUX_MODE | 功能 | 说明 |
|---|---|---|
| 0000 | ALT0 | I2C1_SDA |
| 0001 | ALT1 | GPT1_COMPARE3 |
| 0010 | ALT2 | USB_OTG2_OC |
| 0100 | ALT4 | USDHC1_CD_B |
| 0101 | ALT5 | GPIO1_IO03(GPIO 功能) |
| 0110 | ALT6 | CCM_DIO_EXT_CLK |
| 0111 | ALT7 | SRC_TESTER_ACK |
| 1000 | ALT8 | UART1_RX |
如果你是要把这个脚当 GPIO 用,必须选 ALT5。
2️⃣ GPIO 初始化时的标准配置
cpp
MUX_MODE = 0101b (ALT5)
这一步的含义是:
将 PAD GPIO1_IO03 连接到 GPIO1 控制器的 IO03 引脚
如果不做这一步:
-
GPIO 模块即使配置了方向、输出值
-
PAD 仍然连在其他外设上
-
GPIO 操作不会生效
4、SION:是否强制打开输入通路
SION(位 4)
| 值 | 含义 |
|---|---|
| 0 | 正常模式(推荐) |
| 1 | 强制打开输入路径 |
官方描述:
Force the selected mux mode input path no matter of MUX_MODE functionality.
实际使用建议
-
普通 GPIO(输入或输出):
cppSION = 0 -
特殊场景 (如 GPIO 复用为外设输入、但硬件路径不默认打开):
才考虑设为 1
99% 的 GPIO 使用场景,SION 都应为 0
5、寄存器最终配置值示例
目标
-
GPIO 功能
-
不强制输入
位设置
cpp
SION = 0
MUX_MODE = 0101
寄存器低 5 位
cpp
0b0_0101 = 0x05
代码示例(裸机 / 寄存器方式)
cpp
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 (*(volatile uint32_t *)0x20E0068)
IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x05;
或(更安全,保留保留位):
cpp
IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 =
(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 & ~0x1F) | 0x05;
3. 配置引脚电气特性(Pad Control)
包括:
-
上拉/下拉(Pull-up/Pull-down)
-
开漏(Open-drain / Push-pull)
-
驱动能力(Drive Strength)
-
滞回(Hysteresis)
-
速度(Slew Rate)
这部分在 SoC 中非常关键,如 i.MX 通过 IOMUXC_SW_PAD_CTL_PAD_xxx 完成。


一、这一"第三步"在 GPIO 初始化中的作用
完成前两步后:
-
GPIO3 模块时钟已使能
-
PAD 已通过 MUX 连接到 GPIO(ALT5)
但此时引脚只是在"逻辑上连对了" ,并不意味着电气上是安全、稳定、可用的。
Pad Control 决定的是:
上拉 / 下拉
是否悬空
驱动能力(电流)
翻转速度
输入抗抖动(迟滞)
二、寄存器基本信息(根据截图)
寄存器名称
cpp
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03
地址
cpp
0x20E_02F4
三、字段解读(必须关心的位)
按实际工程使用频率从高到低说明。
1️⃣ HYS(bit 16)------ 输入迟滞(抗抖动)
| 值 | 含义 |
|---|---|
| 0 | 不使能迟滞 |
| 1 | 使能迟滞(推荐用于输入) |
使用建议
-
GPIO 输入 :
HYS = 1 -
GPIO 输出:可设 0(无影响)
迟滞可以抑制慢边沿 / 噪声导致的输入抖动
2️⃣ PKE / PUE / PUS ------ 上拉 / 下拉 / Keeper(成组理解)
这三个位必须一起理解
(1) PKE(bit 12)------ 是否使能上下拉 / Keeper
| 值 | 含义 |
|---|---|
| 0 | 上下拉 / Keeper 全部关闭 |
| 1 | 使能(必须设 1 才生效) |
(2) PUE(bit 13)------ 选择 Pull 还是 Keeper
| 值 | 含义 |
|---|---|
| 0 | Keeper(保持上一次状态) |
| 1 | Pull(上拉 / 下拉) |
(3) PUS(bits 15--14)------ 上拉 / 下拉方向与阻值
| PUS | 含义 |
|---|---|
| 00 | 100K 下拉 |
| 01 | 47K 上拉 |
| 10 | 100K 上拉(最常用) |
| 11 | 22K 上拉 |
GPIO 常见组合(工程推荐)
GPIO 输入(默认不悬空)
cpp
PKE = 1
PUE = 1
PUS = 10 (100K Pull-Up)
GPIO 输出
cpp
PKE = 0 (可关)
3️⃣ ODE(bit 11)------ 开漏输出
| 值 | 含义 |
|---|---|
| 0 | 关闭(普通 GPIO) |
| 1 | 开漏输出(I2C 等) |
GPIO 使用建议
-
普通 GPIO:
ODE = 0 -
只有 I2C / Wired-OR 才设 1
4️⃣ SPEED(bits 7--6)------ 翻转速度(不是频率)
| 值 | 含义 |
|---|---|
| 00 | 低速(50MHz) |
| 01 | 中速(100MHz) |
| 10 | 中速(100MHz) |
| 11 | 高速(200MHz) |
GPIO 使用建议
-
普通 GPIO:
01或10 -
LED / 按键:
00即可 -
高速信号:才用
11
5️⃣ DSE(bits 5--3)------ 驱动能力(非常关键)
| DSE | 含义 |
|---|---|
| 000 | 驱动关闭 |
| 001 | 弱驱动 |
| 100 | R0/4(GPIO 常用) |
| 110 | R0/6 |
| 111 | R0/7(最强) |
GPIO 推荐
-
普通 GPIO 输出 :
DSE = 100 -
LED / 长线:可适当增强
6️⃣ SRE(bit 0)------ 边沿速率
| 值 | 含义 |
|---|---|
| 0 | 慢边沿(推荐) |
| 1 | 快边沿 |
GPIO 使用建议
-
普通 GPIO:
0 -
高速接口:
1
四、一个"标准 GPIO" Pad 配置示例
场景
-
GPIO 输入
-
默认上拉
-
抗抖动
-
普通驱动
推荐配置
| 字段 | 值 |
|---|---|
| HYS | 1 |
| PKE | 1 |
| PUE | 1 |
| PUS | 10 |
| ODE | 0 |
| SPEED | 01 |
| DSE | 100 |
| SRE | 0 |
对应寄存器值(示例)
cpp
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 (*(volatile uint32_t *)0x20E02F4)
IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 =
(1 << 16) | /* HYS */
(1 << 12) | /* PKE */
(1 << 13) | /* PUE */
(2 << 14) | /* PUS = 100K pull-up */
(1 << 6) | /* SPEED = medium */
(4 << 3); /* DSE = R0/4 */
(未列出的位均为 0)
五、这一"第三步"做到什么程度才算正确
✔ 引脚不上电即悬空
✔ 输入稳定、不乱跳
✔ 输出不过冲、不抖动
✔ EMI 可控
常见错误
-
只配 MUX,不配 PAD
-
PKE=0 却期望有上拉
-
DSE 设太大,导致干扰
六、小结
GPIO 初始化第三步的本质:
用
IOMUXC_SW_PAD_CTL_PAD_xxx为 GPIO 引脚定义"电气性格"------
拉不拉、拉多大、推多狠、翻多快。
4. 设置 GPIO 方向(Direction Setting)
GPIO 可配置为:
-
输入模式(Input):用于按键、传感器、状态读取
-
输出模式(Output):用于 LED、控制引脚、驱动外部器件
-
双向(Bidirectional):某些平台允许
初始化必须明确方向。


1️⃣、核心寄存器:GPIOx_GDIR(GPIO 方向寄存器)
-
寄存器基础信息
- 地址:不同 GPIO 组的 GDIR 地址不同(如截图中
GPIO3_GDIR地址为20A_4004,GPIO1_GDIR为209_C004,GPIO2_GDIR为20A_0004等); - 位宽:32 位(每 1 位对应 1 个 GPIO 引脚);
- 访问权限:RW(可读可写);
- 复位值:
0x00000000(复位后所有引脚默认配置为输入)。
- 地址:不同 GPIO 组的 GDIR 地址不同(如截图中
-
位定义规则 GDIR 寄存器的每 1 位对应 1 个 GPIO 引脚的方向,规则如下:
位值 方向配置 说明 0 输入(INPUT) 该位对应的 GPIO 引脚配置为输入模式,引脚仅能读取外部电平,无法主动输出电平; 1 输出(OUTPUT) 该位对应的 GPIO 引脚配置为输出模式,引脚可通过 GPIOx_DR寄存器主动输出高低电平;例:若要将
GPIO1_3配置为输出,需将GPIO1_GDIR寄存器的第 3 位写 1;若配置为输入,第 3 位写 0。
2️⃣ 、方向设置的操作逻辑
-
步骤 1:确定目标 GPIO 的 "组 + 引脚号" 例:需配置
GPIO1_3为输出 → 确定操作GPIO3_GDIR寄存器的第 3 位。 -
步骤 2:计算 GDIR 寄存器的写入值
- 配置单个引脚:通过 "位掩码" 方式操作(避免影响其他引脚)。例:配置
GPIO3_20为输出 → 写入值 =1 << 3;配置GPIO1_3为输入 → 写入值 =0 << 3(或先读寄存器、清除第3位后写回)。 - 配置多个引脚:合并位掩码。例:配置
GPIO1_3(输出)+GPIO1_8(输入) → 先读GPIO1_GDIR原值,保留第 8 位为 0、第 3 位设 1,其余位不变,再写回寄存器。
- 配置单个引脚:通过 "位掩码" 方式操作(避免影响其他引脚)。例:配置
-
步骤 3:写入 GDIR 寄存器通过内存映射方式,向对应 GPIO 组的 GDIR 物理地址写入计算好的值,完成方向配置。
5. 配置默认输出电平(Initial Output Level)
如果 GPIO 是输出模式,需要先配置默认电平,再设置方向,避免初始化瞬间的错误电平跳变。
推荐顺序:
-
在方向设置为输出之前,先写入初始电平(如高电平/低电平)
-
然后设置方向为输出
-
再启用后续操作
例如:控制 LED(低电平点亮)时:
-
上电时把引脚先写成高电平
-
再设置为输出,确保 LED 不会误亮:

-
- 若 GDIR 配置为输出(1):
GPIOx_DR寄存器对应位可控制引脚输出电平; - 若 GDIR 配置为输入(0):
GPIOx_DR寄存器对应位仅能读取引脚外部电平(写 DR 无效)。
- 若 GDIR 配置为输出(1):
6. 配置中断(如需)
输入模式下可能需要配置中断,例如按键、检测信号。
步骤包括:
-
中断触发边沿(上升沿/下降沿/双沿/电平触发)
-
清除中断标志
-
使能中断
-
注册中断回调
不同 MCU/SoC 结构可能包含:
-
EXTI(STM32 等)
-
GPIO_INT(NXP i.MX)
-
GIC(ARM 架构中断控制器)
7. 上层驱动初始化或注册(可选)
对于复杂 SoC(如 i.MX 系列)或 Linux 系统,需要在中间层完成注册:
-
Linux Device Tree(DTS)中声明 pinctrl、GPIO 属性
-
注册 input device(如按键)
-
初始化 LED 子系统(如 LED class)
8. GPIO 测试和验证
汇编汇总
cpp
/**************************************************************
Copyright © Co., Ltd. 2000-2025. All rights reserved.
文件名 : mian.c
作者 :
版本 : V1.0
描述 : 裸机实验1 汇编点灯
使用汇编来点亮开发板上的LED灯,学习和掌握如何用汇编语言来
完成对I.MX6U处理器的GPIO初始化和控制。
其他 : 无
日志 : 初版V1.0 2025/12/23 denglz创建
**************************************************************/
.global _start /* 全局标号 */
/*
描述: _start函数,程序传此函数开始执行.
此函数完成时钟使能 GPIO初始化 最终控制GPIO输出低电平点亮LED灯.
*/
_start:
/* 1. 使能所有时钟 */
ldr r0, = 0x020C4068 /* CCGR0 */
ldr r1, = 0xFFFFFFFF
str r1, [r0]
ldr r0, = 0x020C406C /* CCGR1 */
str r1, [r0]
ldr r0, = 0x020C4070 /* CCGR2 */
str r1, [r0]
ldr r0, = 0x020C4074 /* CCGR3 */
str r1, [r0]
ldr r0, = 0x020C4078 /* CCGR4 */
str r1, [r0]
ldr r0, = 0x020C407C /* CCGR5 */
str r1, [r0]
ldr r0, = 0x020C4080 /* CCGR6 */
str r1, [r0]
/* 2. 设置GPIO1_IO03复用为GPIO1_IO03 */
ldr r0, = 0x020E0068 /* 将寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03加载到r0中 */
ldr r1, = 0x5;
str r1, [r0] /* 设置寄存器IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03的MUX_MODE为0101 ALT5 */
/* 3.配置GPIO1_IO03的电气属性
*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 /* 将寄存器IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03加载到r0中 */
ldr r1, = 0x10B0
str r1, [r0]
/* 4. 设置GPIO1_IO03方向为输出 */
ldr r0, = 0x0209C004 /* 寄存器GPIO1_GRIR */
ldr r1, = 0x00000008 /* 将GPI01_GRIR寄存器的第3为写1(输出) */
str r1, [r0]
/* 5. 配置GPIO1_IO03默认输出电平(点亮) */
ldr r0, = 0x0209C000 /* 寄存器GPIO1_DR */
ldr r1, = 0
str r1, [r0]
/*
* 描述: loop无限循环
*/
loop:
b loop
初始化之后必须进行基本验证:
-
输出模式:
-
切换高/低电平
-
测试 LED、继电器、电平转换器动作是否正确
-
-
输入模式:
-
读取状态
-
按键/信号测试
-
测试中断触发是否正常
-
三. 编译下载验证
1**、arm-linux-gnueabihf-gcc编译文件**
我们是要编译出在 ARM 开发板上运行的可执行文件,所以要使用我们在 4.3 小节安装的
交叉编译器 arm-linux-gnueabihf-gcc 来编译。因为本试验就一个 led.s 源文件,所以编译比较简
单。先将 led.s 编译为对应的.o 文件,在终端中输入如下命令:
bash
arm-linux-gnueabihf-gcc -g -c led.s -o led.o
2**、arm-linux-gnueabihf-ld链接文件**
arm-linux-gnueabihf-ld 用来将众多的.o 文件链接到一个指定的链接位置。
确定了链接地址以后就可以使用 arm-linux-gnueabihf-ld 来将前面编译出来的 led.o 文件链
接到 0X87800000 这个地址,使用如下命令:
bash
arm-linux-gnueabihf-ld -Ttext 0X87800000 led.o -o led.elf
3**、arm-linux-gnueabihf-objcopy格式转换**
arm-linux-gnueabihf-objcopy 更像一个格式转换工具,我们需要用它将 led.elf 文件转换为
led.bin 文件,命令如下:
bash
arm-linux-gnueabihf-objcopy -O binary -S -g led.elf led.bin
