RT-1052学习笔记(5 )- GPIO架构分析

前提提一句,i.MX RT1052与imx6ul的很多片内外设的架构长的都是一样的。


分析GPIO的外设框架

RT-1052学习笔记(5 )- GPIO架构分析_第1张图片

  1. 橙色部分:由IOMUX控制,负责控制IO口的输入输出使能,上下拉或者开漏,保持,驱动能力,压摆率,带宽,HYS滞后使能输入。这部分通过配置IOMUX控制。
  2. 红色部分:配置橙色部分的功能,以及选择这个IO到底被谁用,通过MUX寄存器选择。还包括一个在输出的同时还可以读取IO电平的使能端,使能这个功能则输出同步输入
  3. 蓝色部分:用这个IO的人,GPIO框就是GPIO的控制端,控制引脚的输出电平,或者读取引脚的电平。Bolck端就是复用给其他外设使用,比如PWM,SPI,等外设

总结一句话就是,蓝色部分通过配置好的红色部分来使用橙色部分进行IO

怎么把一个引脚用做GPIO?:

现在先配置成普通IO使用。学习好普通IO的框架后,如果要用作其他功能,直接通过MXC配置复用给对应的外设,然后,就全权交给外设来管理了。

配置步骤

  1. 打开GPIO1时钟:通过配置CCM->CCGR1[27:26]打开GPIO1的时钟
  2. 配置IOMUX-MUX寄存器:选择复用功能以及是否使用SION
  3. 配置IOMUX-PAD寄存器:配置PAD模块功能
  4. 配置GPIO->GDIR寄存器:设置GPIO控制器为输出控制逻辑还是输入控制逻辑

代码展示

/* 开启GPIO1端口的时钟 */
CCM_CCGR1 &= ~(unsigned int)(3<<26);
CCM_CCGR1|=(unsigned int)(1<<26);

/* 设置MUX寄存器为0x05,表示把引脚用于普通GPIO */
IOMUXC_MUX_GPIO_AD_B0_09=(unsigned int)0x05;

/* 设置PAD寄存器控制引脚的属性 
  属性配置说明:
    十六进制数0x000B0=二进制数0000 0000 0000 1011 0000 b
    bit0:SRE:0b压摆率: 慢压摆率
    bit1~bit2:-:00b寄存器保留项
    bit3~bit5:DSE:110b驱动强度:R0/6(仅作为输出时有效)
    bit6~bit7:SPEED:10b带宽:medium(100MHz)
    bit8~bit10:-:000 b寄存器保留项
    bit11:ODE:0 b开漏配置:关闭 
        (开漏高阻态常用于总线配置,如I2C)
    bit12:PKE:0b拉/保持器配置:关闭
    bit13:PUE:0b拉/保持器选择:关闭了上下拉及保持器,任意值无效
    bit14~bit15:PUS:00b拉/下拉选择:关闭了上下拉及保持器,任意值无效
    bit16:HYS:0b滞回器配置:关闭 
        (仅输入时有效,施密特触发器,使能后可以过滤输入噪声)
    bit17~bit31:-:0b寄存器保留项
*/
IOMUXC_PAD_GPIO_AD_B0_09=(unsigned int)0x000B0;

/*设置GPIO1_09引脚的方向,使用输出模式 */
GPIO1_GDIR|=(unsigned int)(1<<9);

/*控制引脚为低电平,点亮LED灯*/
GPIO1_DR&=~(unsigned int)(1<<9);

使用

  1. 输出:设置GPIO->DR的对应位设置对应IO的电平
  2. 输入:读取GPIO-DR或者GPIO->PSR寄存器得到对应IO的电平

库函数操作

1、初始化MUX

IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0U);
  • 这里插播一段关于i.MX 系列芯片的引脚命名方式
  • i.MX的每一个引脚,都有一个专用的名字,比如GPIO_AD_B0_09。

    每个外设的输入输出引脚,也有一个专用的名字,比如ADC2_IN0,GPIO1_IO00。

    他们通过一个IOMUX控制器来连接,每个外部引脚可以选择一种复用方式来连接需要的外设。

    当一个引脚被连接到一个确定的外设后,就可以用一个名字来确定这个引脚是哪一个,有什么功能了。

    所以,库函数就通过一个宏来配置一个引脚的复用

    IOMUXC_GPIO_AD_B0_09_GPIO1_IO09

    其中:

    IOMUXC代表IOMUXC控制器

    GPIO_AD_B0_09代表引脚名字

    GPIO1_IO09代表引脚设置的复用功能

  •  库函数利用一句话就搞定了mux的配置,还剩下PAD就完成了一个引脚的配置了。

2、初始化PAD

其实,PAD的配置也是一句话。直接上代码:配置一个引脚为UART1_TX

/* 这个是SDK的例子截出来的 */
IOMUXC_SetPinConfig(
      IOMUXC_GPIO_AD_B0_12_LPUART1_TX, /* GPIO_AD_B0_12 PAD functional properties : */
      0x10B0u); /* Slew Rate Field: Slow Slew Rate
                   Drive Strength Field: R0/6
                   Speed Field: medium(100MHz)
                   Open Drain Enable Field: Open Drain Disabled
                   Pull / Keep Enable Field: Pull/Keeper Enabled
                   Pull / Keep Select Field: Keeper
                   Pull Up / Down Config. Field: 100K Ohm Pull Down
                   Hyst. Enable Field: Hysteresis Disabled */

第一个宏就是和配MUX的宏一样的,这个很好理解,根据那个引脚复用成什么功能就可以确定了。关键是第二个参数,这根本就是在操作寄存器啊!!!这个值是被直接写对应引脚的PAD寄存器,对是直接写进去。这里推荐一个i.MX Pins Tool v4.0工具,可以通过图形化对i.MX系列芯片的IO口进行配置,输出C格式代码或者设备树配置文件。

 

RT-1052学习笔记(5 )- GPIO架构分析_第2张图片

3、初始化GPIO外设

熟悉ST标准库的人看到这段肯定很舒服了。这就配置完GPIO外设了。

//API
/*! @brief GPIO Init structure definition. */
typedef struct _gpio_pin_config
{
    gpio_pin_direction_t direction; /*!< Specifies the pin direction. */
    uint8_t outputLogic;            /*!< Set a default output logic, which has no use in input */
    gpio_interrupt_mode_t
    interruptMode;								  /*!< Specifies the pin interrupt mode, a value of @ref gpio_interrupt_mode_t. */
} gpio_pin_config_t;
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config);
//使用
{
  /* 定义gpio初始化配置结构体 */
  gpio_pin_config_t led_config;      
    
   /** 核心板的LED灯,GPIO配置 **/       
  led_config.direction = kGPIO_DigitalOutput; //输出模式
  led_config.outputLogic =  1;                //默认高电平
  led_config.interruptMode = kGPIO_NoIntmode; //不使用中断
  
  /* 初始化 LED GPIO. */
  GPIO_PinInit(GPIO1, 9, &led_config);
}

4、配置时钟

4.1、配置外设时钟

/* 从AHB_CLK_ROOT中4分频得到IPG_CLK_ROOT时钟,提供给内部大部分外设 */
CLOCK_SetDiv(kCLOCK_IpgDiv, 3);

4.2、使能GPIO时钟

这个时钟在库函数中自动配置,如果没有定义宏FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL,或者定义了宏但是宏FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL不等于0,则通过GPIO_PinInit函数自动配置对应GPIO时钟

void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config)
{
#if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
    /* Enable GPIO clock. */
    CLOCK_EnableClock(s_gpioClock[GPIO_GetInstance(base)]);
#endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
···
}

 

5、使用

GPIO_PinWrite(GPIO1, 9, 0U);

 

你可能感兴趣的:(i.MX,RT)