前提提一句,i.MX RT1052与imx6ul的很多片内外设的架构长的都是一样的。
总结一句话就是,蓝色部分通过配置好的红色部分来使用橙色部分进行IO
现在先配置成普通IO使用。学习好普通IO的框架后,如果要用作其他功能,直接通过MXC配置复用给对应的外设,然后,就全权交给外设来管理了。
/* 开启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);
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0U);
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代表引脚设置的复用功能
其实,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格式代码或者设备树配置文件。
熟悉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.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 */
···
}
GPIO_PinWrite(GPIO1, 9, 0U);