MX6ULL 的 GPIO 操作方法(保姆级教程)

目录

[一、点亮 LED 的三步法](#一、点亮 LED 的三步法)

[二、看原理图:LED 怎么连到芯片的?](#二、看原理图:LED 怎么连到芯片的?)

[2.1 LED 在原理图中的抽象](#2.1 LED 在原理图中的抽象)

[2.2 两种最基本的驱动方式](#2.2 两种最基本的驱动方式)

[2.3 引脚驱动能力不足怎么办?------ 三极管驱动](#2.3 引脚驱动能力不足怎么办?—— 三极管驱动)

[三、GPIO 通用操作方法](#三、GPIO 通用操作方法)

[3.1 GPIO 模块的五大要素](#3.1 GPIO 模块的五大要素)

[3.2 寄存器操作的两种方式](#3.2 寄存器操作的两种方式)

方式A:读-改-写(Read-Modify-Write)

[方式B:set-and-clear 协议(硬件原子操作)](#方式B:set-and-clear 协议(硬件原子操作))

[四、实战:i.MX6ULL 的 GPIO 操作](#四、实战:i.MX6ULL 的 GPIO 操作)

[4.1 总体流程](#4.1 总体流程)

[4.2 步骤详解 + 如何查手册](#4.2 步骤详解 + 如何查手册)

[步骤1:使能 GPIO1 时钟](#步骤1:使能 GPIO1 时钟)

[步骤2:将引脚复用为 GPIO 功能](#步骤2:将引脚复用为 GPIO 功能)

步骤3:设置方向为输出

步骤4:输出高/低电平

[4.3 完整代码示例(裸机风格)](#4.3 完整代码示例(裸机风格))

五、怎么查手册?我教你方法

[5.1 必备的两份文档](#5.1 必备的两份文档)

[5.2 查手册的典型路径](#5.2 查手册的典型路径)

[5.3 小技巧](#5.3 小技巧)

六、为了更好的阅读体验,建议你贴出这些图

七、总结


学习 C 语言时,第一个程序是 "Hello World"。

学习 ARM 裸机编程时,第一个程序就是 点亮 LED

这篇文章带你从看原理图开始,一步步掌握 i.MX6ULL 的 GPIO 操作,顺便学会怎么查芯片手册。


一、点亮 LED 的三步法

点亮一个 LED 只需要三步:

  1. 看原理图 -- 找到控制 LED 的引脚是哪个。

  2. 看芯片手册 -- 确定如何设置这个引脚(时钟、复用、方向、电平)。

  3. 写程序 -- 配置寄存器,点亮或熄灭 LED。

下面我们就按这三步展开。


二、看原理图:LED 怎么连到芯片的?

2.1 LED 在原理图中的抽象

实际 LED 长得五花八门(插脚、贴片),原理图中统一抽象成下图的样子:

text

复制代码
        +3.3V
         │
        ╭┴╮
        │ │ 电阻(限流,一般 470Ω ~ 1kΩ)
        ╰┬╯
         │
        ┌┴┐
        │▼│ LED(箭头指向GND表示正极接电源)
        └┬┘
         │
       GND

重点

  • LED 需要 正向电压 才能点亮(阳极 > 阴极)。

  • 必须串联电阻 限制电流,否则 LED 会烧坏。

2.2 两种最基本的驱动方式

方式 连接方法 芯片引脚动作
方式1 芯片引脚 → 电阻 → LED → GND 引脚输出 3.3V 点亮,输出 0V 熄灭
方式2 VCC(3.3V) → 电阻 → LED → 芯片引脚 引脚输出 0V 点亮,输出 3.3V 熄灭

方式1也叫 "高电平点亮" ,方式2是 "低电平点亮"

很多开发板喜欢用低电平点亮,因为芯片引脚的 灌电流 能力通常比拉电流强。

2.3 引脚驱动能力不足怎么办?------ 三极管驱动

有些芯片引脚输出电流很小(比如 <5mA),直接推 LED 可能很暗。这时可以加一颗 三极管MOSFET 来驱动:

  • 方式3:NPN 三极管,基极接芯片引脚,集电极接 LED 负极。引脚输出 1.2V 左右(高电平)→ 三极管导通 → LED 亮。

  • 方式4:PNP 三极管,基极接芯片引脚,发射极接电源。引脚输出 0V(低电平)→ 三极管导通 → LED 亮。

💡 在你的学习板原理图上,先看清 LED 是接到哪个 GPIO 引脚,以及是高电平点亮还是低电平点亮。这是编程的第一步。


三、GPIO 通用操作方法

GPIO = General Purpose Input/Output ,通用输入输出口。

任何芯片的 GPIO 操作都逃不出下面几个步骤:

3.1 GPIO 模块的五大要素

  1. 使能(时钟/电源) -- 先打开 GPIO 模块的时钟,否则寄存器无法读写。

  2. 模式(Mode) -- 引脚可能复用为 UART、I2C、SPI 等,需要先设为 GPIO 模式。

  3. 方向(Direction) -- 设为输入还是输出。

  4. 数值(Data) -- 输出时写高/低电平;输入时读电平状态。

  5. 其他 -- 中断、防抖、唤醒等(后续再学)。

3.2 寄存器操作的两种方式

方式A:读-改-写(Read-Modify-Write)

适用于普通的数据寄存器(写 1 置位,写 0 清零,不能只改某一位)。

cs 复制代码
c

// 设置 bit n 为 1
val = *reg;
val |= (1 << n);
*reg = val;

// 清除 bit n 为 0
val = *reg;
val &= ~(1 << n);
*reg = val;
方式B:set-and-clear 协议(硬件原子操作)

部分芯片提供 SETCLR 寄存器,向 SET 写 1 就置位,向 CLR 写 1 就清零,互不影响。

cs 复制代码
c

// 设置 bit n
*set_reg = (1 << n);

// 清除 bit n
*clr_reg = (1 << n);

i.MX6ULL 的 GPIO 数据寄存器 GPIOx_DR 不支持 set-and-clear,只能用读-改-写。但它的 IOMUXC 部分有类似设计,后面会见到。


四、实战:i.MX6ULL 的 GPIO 操作

我们以最常见的 i.MX6ULL 芯片为例,演示如何点亮一个 LED。

假设 LED 接在 GPIO1_IO00 引脚,且是 高电平点亮(方式1)。

4.1 总体流程

cs 复制代码
text

1. 使能 GPIO1 时钟          → 操作 CCM_CCGR1 寄存器
2. 将引脚复用为 GPIO1_IO00  → 操作 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00
3. 设置方向为输出           → 操作 GPIO1_GDIR
4. 输出高电平或低电平       → 操作 GPIO1_DR

4.2 步骤详解 + 如何查手册

步骤1:使能 GPIO1 时钟

为什么? 如果不打开时钟,GPIO 模块无法工作,寄存器读写无效(可能引起总线错误)。

查手册

打开 i.MX6ULL 参考手册,找到 Chapter 18 Clock Controller Module (CCM)

搜索 GPIO1_CLK_ENABLE,会看到如下信息:

时钟信号 控制位 所在寄存器
gpio1_clk_enable CG13 CCM_CCGR1
gpio2_clk_enable CG15 CCM_CCGR0
gpio3_clk_enable CG13 CCM_CCGR2
gpio4_clk_enable CG6 CCM_CCGR3
gpio5_clk_enable CG15 CCM_CCGR1

注意:每个 CG 位占 2 bits,编码含义:

  • 00:所有模式下关闭时钟

  • 01:Run 模式开,Wait/Stop 关

  • 11:所有模式(除 Stop)开

我们一般设为 11,让时钟一直开着。

实际操作

cs 复制代码
c

#define CCM_CCGR1  (*(volatile unsigned int *)0x020C406C)  // 地址见手册

// 使能 GPIO1 时钟:设置 CG13 两位为 11
CCM_CCGR1 |= (3 << 26);   // CG13 从 bit26 开始,占2位

💡 教你找地址

手册中搜索 "CCM_CCGR1" 即可看到它的基址和偏移。i.MX6ULL 的 CCM 基址是 0x020C4000,CCGR1 偏移 0x6C,所以地址 0x020C406C

步骤2:将引脚复用为 GPIO 功能

一个物理引脚可能有多个功能(UART、I2C、GPIO...)。我们需要选择 GPIO 功能。

查手册

找到 Chapter 30 IOMUX Controller (IOMUXC)

搜索引脚名称,比如 GPIO1_IO00,找到 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00 寄存器。

其中关键字段 MUX_MODE

MUX_MODE 值 功能
0101 (5) ALT5 -- GPIO1_IO00
0000 I2C2_SCL
0001 GPT1_CAPTURE1
... ...

要设置为 GPIO,就写入 5

实际操作

cs 复制代码
c

#define SW_MUX_GPIO1_IO00  (*(volatile unsigned int *)0x020E005C)

// 将 MUX_MODE 设置为 5 (ALT5, GPIO 功能)
SW_MUX_GPIO1_IO00 = 5;

💡 地址怎么来的?

IOMUXC 基址 0x020E0000GPIO1_IO00 的 SW_MUX 偏移 0x005C0x020E005C

另外这个寄存器里还有一个 SION 位(Software Input On),如果希望输入路径一直打开(比如读引脚状态),可以置1。输出操作一般不需要。

步骤3:设置方向为输出

每个 GPIO 端口有一组 GDIR 寄存器,每 bit 控制一个引脚的方向:

  • 0 = 输入

  • 1 = 输出

查手册
Chapter 28 General Purpose I/O (GPIO)

找到 GPIOx_GDIR 寄存器描述,bit n 对应 GPIO[n] 的方向。

实际操作

cs 复制代码
c

#define GPIO1_GDIR  (*(volatile unsigned int *)0x0209C004)

// 设置 bit0 为 1,表示 GPIO1_IO00 为输出
GPIO1_GDIR |= (1 << 0);
步骤4:输出高/低电平

输出电平通过 数据寄存器 GPIOx_DR 控制。

写 1 则引脚输出高电平(3.3V),写 0 输出低电平(0V)。

⚠️ 特别注意 :当方向为 输入 时,读取 GPIOx_DR 返回的不是你写入的值,而是 引脚实际电平 (等同于 GPIOx_PSR 状态寄存器)。

手册原文:While the GPIO direction is set to input, a read access to GPIO_DR returns the GPIO_PSR data.

实际操作

cs 复制代码
c

#define GPIO1_DR   (*(volatile unsigned int *)0x0209C000)

// 点亮 LED(高电平点亮)
GPIO1_DR |= (1 << 0);

// 熄灭 LED
GPIO1_DR &= ~(1 << 0);

4.3 完整代码示例(裸机风格)

cs 复制代码
c

// 定义寄存器地址
#define CCM_CCGR1      (*(volatile unsigned int *)0x020C406C)
#define SW_MUX_GPIO1_0 (*(volatile unsigned int *)0x020E005C)
#define GPIO1_GDIR     (*(volatile unsigned int *)0x0209C004)
#define GPIO1_DR       (*(volatile unsigned int *)0x0209C000)

void delay(volatile int t) { while(t--); }

int main(void)
{
    // 1. 使能 GPIO1 时钟 (CG13 = 11)
    CCM_CCGR1 |= (3 << 26);

    // 2. 复用为 GPIO1_IO00
    SW_MUX_GPIO1_0 = 5;   // ALT5

    // 3. 设置为输出
    GPIO1_GDIR |= (1 << 0);

    while (1) {
        // 点亮
        GPIO1_DR |= (1 << 0);
        delay(500000);
        // 熄灭
        GPIO1_DR &= ~(1 << 0);
        delay(500000);
    }
    return 0;
}

五、怎么查手册?我教你方法

很多初学者觉得手册几百页很恐怖,其实你只需要学会 有目的地搜索

5.1 必备的两份文档

  • i.MX6ULL 参考手册IMX6ULLRM.pdf) -- 详细寄存器描述。

  • 数据手册IMX6ULLCEC.pdf) -- 引脚定义、电气特性。

5.2 查手册的典型路径

任务 搜索关键词 去哪一章
找某个引脚的复用配置 GPIO1_IO00SW_MUX_CTL_PAD_ IOMUXC 章节
打开 GPIO 时钟 GPIO1_CLK_ENABLECCM_CCGR1 CCM 章节
GPIO 方向寄存器 GPIOx_GDIR GPIO 章节
GPIO 数据寄存器 GPIOx_DR GPIO 章节
引脚在哪个 GPIO 组? 查看原理图或数据手册的 Ball Map 数据手册

5.3 小技巧

  • 手册 PDF 的 书签 是最快导航。

  • 善用 Ctrl+F,但尽量搜准确的寄存器名或信号名。

  • 看到 ALT5 这样的复用值,就在附近找表格,里面列出了所有复用功能。


七、总结

步骤 寄存器类别 作用
1 CCM_CCGRx 使能 GPIO 模块时钟
2 IOMUXC_SW_MUX 把引脚切换为 GPIO 功能
3 GPIOx_GDIR 设置方向(输入/输出)
4 GPIOx_DR 输出高低电平 / 读取输入

掌握了这套 "时钟 → 复用 → 方向 → 数据" 的套路,任何 Cortex-A 芯片的 GPIO 你都能轻松驾驭。

下一步,你可以试试读取按键输入、控制蜂鸣器,甚至用 GPIO 模拟 I2C 协议。

动手是学会的唯一途径。现在就去打开你的开发板,把第一个 LED 点起来吧!

相关推荐
点灯小铭3 小时前
基于单片机的球类比赛专用计分与暂停管理系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
自小吃多4 小时前
TMC220X芯片 串口工具连接交互
笔记·嵌入式硬件
笨笨饿4 小时前
34_数据结构_栈
c语言·开发语言·数据结构·人工智能·嵌入式硬件·算法
Wave8454 小时前
基于 STM32 的模块化多功能手表系统:从架构设计到低功耗深度实践
stm32·嵌入式硬件·智能手表
清风6666665 小时前
基于单片机的安全带长度高度拉力监测与自动锁紧控制系统设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
笨笨饿5 小时前
32_复变函数在工程中实际应用区别于联系
linux·服务器·c语言·人工智能·单片机·算法·学习方法
悟渔6 小时前
用于STM32的C++编程的LED对象
c++·stm32·单片机
yongui478346 小时前
基于STM32+W5500的IAP远程升级程序设计
stm32·单片机·嵌入式硬件
LCG元6 小时前
STM32实战:基于STM32CubeMX的串口通信(UART)与DMA传输优化
stm32·单片机·嵌入式硬件