LINUX开发板 GPIO 完全详解(I.MX6U 为例)

张开发
2026/4/15 8:11:23 15 分钟阅读

分享文章

LINUX开发板 GPIO 完全详解(I.MX6U 为例)
初始化 STM32 的一个 IO 为输出功能代码是下面这样的/* * 函数LED_Init * 功能初始化LED对应的GPIO引脚PB5为推挽输出 */ void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; // 定义GPIO初始化结构体 // 1. 使能GPIOB端口时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 2. 配置GPIO参数 GPIO_InitStructure.GPIO_Pin GPIO_Pin_5; // 选择PB5引脚 GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; // 推挽输出模式 GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; // IO口速度50MHz // 3. 根据参数初始化GPIO GPIO_Init(GPIOB, GPIO_InitStructure); // 4. 默认输出高电平熄灭LED GPIO_SetBits(GPIOB, GPIO_Pin_5); }使用库函数来初始化 STM32 的一个 IO 为输出功能重点要做的事情有①、使能指定 GPIO 的时钟。②、初始化 GPIO比如输出功能、上拉、速度等等。③、 STM32 有的 IO 可以作为其它外设引脚也就是 IO 复用如果要将 IO 作为其它外设引脚使用的话就需要设置 IO 的复用功能。④、最后设置 GPIO 输出高电平或者低电平。那么在Linux开发板中是否也是这样的流程呢本文用I.MX6U结合正点原子教程进行教学。I.MX6U IO命名STM32 中的 IO 都是 PA0~15、 PB0~15 这样命名的 I.MX6U 的 IO 是怎么命名的呢我们看下参考手册可以看到I.MX6ULL 的 IO 分为两类SNVS 域的和通用的。I.MX6ULL 的 GPIO 并不像 STM32 一样以 PA0~15 这样命名他是根据某个 IO 所拥有的功能来命名的。IOMUXC_SW_MUC_CTL_PAD_XX_XX。后面的“XX_XX”就是 GPIO 命名比如GPIO1_IO01、 UART1_TX_DATA、 JTAG_MOD 等等。比如我们一看到 GPIO1_IO01 就知道这个肯定能做 GPIO看到 UART1_TX_DATA 肯定就知道这个 IO 肯定能做为 UART1 的发送引脚。同时I.MX6ULL 的很多IO 是可以复用为 GPIO 功能。I.MX6U IO复用以“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00” 这个 IO 为例学会看参考手册看手册怎么看寄存器名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 等。再看一个“IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA”这个 IO同样的可以看出UART1_TX_DATA 可以复用为 8 种不同功能的 IOALT0~ALT5 和 ALT8、 ATL9。其中 ALT5 表示 UART1_TX_DATA 可以复用为 GPIO1_IO16。由此可见 I.MX6U 的 GPIO 不止 GPIO1_IO00~GPIO1_IO09 这 10 个其它的 IO 都可以复用为 GPIO 来使用。至此我们解决了一个问题那就是 I.MX6U 的 IO 是有复用功能的和 STM32 一样如果某个 IO 要作为某个外设引脚使用的话是需要配置复用寄存器的。I.MX6U IO 配置我们能看到参考手册中每一个IO会出现2次IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00MUX和PAD有什么区别呢IOMUX_SW_MUX_CTL_PAD_GPIO1_IO00 我们前面已经说了是用来配置GPIO1_IO00复用功能的那么 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是做什么的呢我们可以看到IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 也是个寄存器寄存器地址为0X020E02E8这也是个 32 位寄存器但是只用到了其中的低17位。图中的每一个模块都对应你要写的寄存器某一位。你要把 IO 配置成输入 / 输出 / 上下拉 / 驱动能力就是往这些位写 0 或 1。框图里的模块都代表什么1. PAD引脚就是芯片外部的物理引脚。2. Output Driver输出驱动器IO 做输出时使用的硬件模块。要让引脚输出高 / 低电平就通过这里。3. Input Receiver输入接收器IO 做输入时使用的硬件模块。外部电平从这里进入芯片内部。4. PU/PD/Keeper Logic上下拉 / 保持器管 IO 的上拉 / 下拉和状态保持。这是 IO 配置里非常关键的部分。5. Driver Config Logic驱动配置逻辑控制输出速度、驱动能力、压摆率。这也是表格里的 SPEED、DSE、SRE。每一个位域bit怎么看图重点要记一个规则图里每一个三角框、逻辑框最终都对应寄存器中的某一位。1. HYS (bit16) —— 施密特触发图中对应HYS作用输入时是否使能施密特触发整形波形0禁止1使能2. PUS (bit15~14) —— 上下拉选择图中对应PUS4 种组合00 100K 下拉01 47K 上拉10 100K 上拉11 22K 上拉3. PUE (bit13) —— 上下拉 / 保持器选择图中没有明确画出但逻辑是0 使用状态保持器1 使用上下拉电阻顾名思义就是当外部电路断电以后此 IO 口可以保持住以前的状态。4. PKE (bit12) —— 上下拉 / 保持使能0禁止1使能5. ODE (bit11) —— 输出使能0禁止输出输入模式1使能输出输出模式6. SPEED (bit7~6) —— IO 输出速度00 低速 50M01 中速 100M10 中速 100M11 最大 200M7. DSE (bit5~3) —— 驱动能力驱动强度8 种驱动强度000 输出关闭001 R0150Ω/260Ω/240Ω 依电压(3.3V 下 R0 是 260Ω 1.8V 下 R0 是 150Ω接 DDR 的时候是 240Ω )010 R0/2011 R0/3100 R0/4101 R0/5110 R0/6111 R0/7R0 越小驱动能力越强。8. SRE (bit0) —— 压摆率Slew Rate0 低压摆率波形缓1 高压摆率波形陡通过上面的介绍可以看出寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是用来配置 GPIO1_IO00 的包括速度设置、驱动能力设置、压摆率设置等等。至此我们解决了另一个问题I.MX6U 的 IO 是可以设置速度的、而且比 STM32 的设置要更多。那么如何设置 IO 为输入还是输出 IO 的默认电平如何设置呢I.MX6U 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 用作哪个外设就复用为哪个外设功能即可。我们先看下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.DR1。当 GPIO被配置为输入模式以后此寄存器就保存着对应 IO 的电平值每个位对对应一个 GPIO例如当GPIO1_IO00 这个引脚接地的话那么 GPIO1.DR 的 bit0 就是 0。一句话 DR 就是 GPIO 的 “状态面板” —— 输出时你写它输入时你读它。DR 是 GPIO 数据寄存器输出模式时写 DR 控制引脚高低电平输入模式时读 DR 获取引脚外部电平。一个 DR 寄存器 32 位每一位对应一组 GPIO 里的一个引脚。GDIR 寄存器这是方向寄存器用来设置某个 GPIO 的工作方向的即输入/输出GDIR 寄存器也是 32 位的此寄存器用来设置某个 IO 的工作方向是输入还是输出。每个 IO 对应一个位如果要设置 GPIO 为输入的话就设置相应的位为 0如果要设置为输出的话就设置为 1。比如要设置 GPIO1_IO00 为输入那么 GPIO1.GDIR0PSR 寄存器这是 GPIO 状态寄存器PSR 寄存器也是一个 GPIO 对应一个位读取相应的位即可获取对应的 GPIO 的状态也就是 GPIO 的高低电平值。功能和输入状态下的 DR 寄存器一样。ICR1 和 ICR2 这两个寄存器都是中断控制寄存器ICR1 用于配置低 16 个 GPIO ICR2 用于配置高 16 个 GPIOICR1 寄存器如下ICR1 用于 IO0~15 的配置 ICR2 用于 IO16~31 的配置。 ICR1 寄存器中一个 GPIO 用两个位这两个位用来配置中断的触发方式和 STM32 的中断很类似可配置的选线以 GPIO1_IO15 为例如果要设置 GPIO1_IO15 为上升沿触发中断那么 GPIO1.ICR1230如果要设置 GPIO1 的 IO16~31 的话就需要设置 ICR2 寄存器了。一个 GPIO 组有32 个引脚IO00 ~ IO31一个寄存器只有32 位。但每个中断需要 2 位来配置所以ICR1管低 16 个引脚IO00 ~ IO15ICR2管高 16 个引脚IO16 ~ IO31每个引脚用 2 位 配置中断方式2 位可以表示 4 种中断触发方式00 低电平触发01 高电平触发10 上升沿触发11 下降沿触发这和 STM32 的中断配置几乎一样。怎么算位置最重要IO00 → 占 ICR1 的bit0 ~ bit1IO01 → 占 ICR1 的bit2 ~ bit3IO02 → 占 ICR1 的bit4 ~ bit5...IO15 → 占 ICR1 的bit30 ~ bit31规律引脚号 × 2 起始位ICR1 和 ICR2 是 GPIO 中断触发方式配置寄存器。ICR1 控制 IO0~15ICR2 控制 IO16~31。每个引脚占用 2 位用于设置上升沿、下降沿、高 / 低电平触发。配置时根据引脚号计算出对应位写入 00/01/10/11 即可。IMR 寄存器这是中断屏蔽寄存器IMR 寄存器也是一个 GPIO 对应一个位 IMR 寄存器用来控制 GPIO 的中断禁止和使能如果使能某个 GPIO 的中断那么设置相应的位为 1 即可反之如果要禁止中断那么就设置相应的位为 0 即可。例如要使能 GPIO1_IO00 的中断那么就可以设置 GPIO1.MIR1。寄存器 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_SEL1那么就表示 GPIO1_IO01 是双边沿触发中断无论 GFPIO1_CR1 的设置为多少都是双边沿触发。关于 GPIO 的寄存器就讲解到这里因为 GPIO 是最常用的功能我们详细的讲解了 GPIO的 8 个寄存器。于是我们解决了另一个问题I.MX6U 的 IO 是需要配置和输出的、是可以设置输出高低电平也可以读取 GPIO 对应的电平。I.MX6U GPIO 时钟使能最后一个疑问那就是 I.MX6U 的 GPIO 是否需要使能时钟STM32 的每个外设都有一个外设时钟 GPIO 也不例外要使用某个外设必须要先使能对应的时钟。 I.MX6U 其实也一样的每个外设的时钟都可以独立的使能或禁止这样可以关闭掉不使用的外设时钟起到省电的目的。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_CCGR03 30。反之如果要关闭 GPIO2 的外设时钟那就设置 CCM_CCGR0 的 bit31 和 bit30 都为 0 即可。 CCM_CCGR0~CCM_CCGR6 这 7 个寄存器操作都是类似的只是不同的寄存器对应不同的外设时钟而已。至此我们所有问题都解决了 I.MX6U 的每个外设的时钟都可以独立的禁止和使能这个和 STM32 是一样。总结总结一下要将 I.MX6U 的 IO 作为 GPIO 使用我们需要一下几步①、使能 GPIO 对应的时钟。②、设置寄存器 IOMUXC_SW_MUX_CTL_PAD_XX_XX设置 IO 的复用功能使其复用为 GPIO 功能。③、设置寄存器 IOMUXC_SW_PAD_CTL_PAD_XX_XX设置 IO 的上下拉、速度等等。④、第②步已经将 IO 复用为了 GPIO 功能所以需要配置 GPIO设置输入/输出、是否使用中断、默认输出电平等。

更多文章