GPIO配置基本过程
配置IO复用功能→配置IO属性→IO口配置
IO 复用功能选择器(IOMUXC)的寄存器非常多,主要可以分为四组:
① IOMUXC_GPR 寄存器组,用于通用控制设置。
② IOMUXC_SNVS 组,主要用于 GPIO5 的控制。 ③ IOMUXC_SNVS_GPR 寄存器组,暂时没用到。
④ IOMUXC 组,用于指定 IO 的复用功能选择和 IO 属性设置。
在 IO 设置的时候,实际上我们只用到了②和④,①和③没用到,所以①和③,我们这里不做介绍。
所以,我们可以把②和④一起介绍,任意一个 IO,都是由 2 个寄存器(SW_MUX_CTL_PAD / SW_PAD_CTL_PAD)控制的。
IOMUXC_SW_MUX_CTL_PAD_
IOMUXC_SW_PAD_CTL_PAD_
红色:用于定义IO所属分组
蓝色:SW_MUX_CTL_PAD——IO复用功能选择寄存器;SW_PAD_CTL_PAD——IO属性配置寄存器
具体模式查看:IOMUXC Memory Map/Register Definition;具体寄存器名:(IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_05)
SION位:强制输入位,一旦设置,无论MUX_MODE设置什么模式总可以从PSR中读取到该引脚的状态
在IOMUXC的分组下还有一类特殊的寄存器:IOMUXC_xxxxx_SELECT_INPUT
xxxxx代表为某一IO口的复用功能,但这个复用功能一般有多个IO口可以选择
OBE,输出缓冲使能,这个属性是内部自动设置的,我们无法直接通过软件修改,当 IO 配置成输出模式时,OBE 自动使能;当 IO 配置成输入模式时,OBE 自动失能;相当于间接设置,其他功能也自动失效
DSE,输出驱动能力,需软件设置,总共有 8 个等级:关闭和 R0/1~R0/7。由 R0 决定 IO 口的驱动能力,在 3.3V 条件下,R0 的值为 150Ω。最小的输出电阻(可以获得最大的驱动能力)为:R0/7=21.4Ω。
SRE,压摆率,需软件设置。共有 2 个等级:Fast 和 Slow。压摆率控制电平跳变的时间,压摆率越高,波形越陡,压摆率越低,波形越缓。这个设置,在过 EMC 测试的时候,比较有用。比如要过 EMC 可以设置压摆率低一些(slow),得到比较平缓的边沿,从而降低电磁辐射。
SPEED,输出速率(带宽),需软件设置,总共有 3 个等级:50M、100M 和 200M。
ODE,开漏输出使能,需软件设置,当设置 ODE=0 且 GPIO 设置成输出模式,为推挽输出;当设置 ODE=1 且 GPIO 设置成输出模式,为开漏输出,开漏输出时:IO 口只能输出低电平/三态输出,无法直接输出高电平,需要使用上拉电阻(内部/外部)才可以输出高电平。当GPIO 设置成输入模式时,ODE 设置直接被忽略。
输入部分
IBE,输入缓冲使能,这个属性是内部自动设置的,我们无法直接通过软件修改,当 IO 配置成输入模式时,IBE 自动使能;当 IO 配置成输出模式时,IBE 自动失能;相当于间接设置。当 IBE 失能时(GPIO 为输出模式时),HYS 等设置无效。
IND,输入信号,读取到的 IO 口状态,由这个口传入 MCU 内部的。
HYS,迟滞比较使能,需软件设置,用于设置是否使能输入接收器的施密特触发器(滞后模式),施密特触发可以对波形进行整形,可以在一定程度上滤除误触发。一般可以不设置。
上拉/下拉/保持控制逻辑
PUS:用于设置上/下拉电阻,可选设置有:100K 下拉、47K 上拉、100K 上拉和 22K 上拉。
PKE:用于使能/禁止上下拉电阻和状态保持器,当设置为 1 时,使能上下拉电阻/状态保持器;当设置为 0 时,关闭上下拉电阻/状态保持器
另外,还有一个 PUE 信号,在图 6.3.3 中没有标出,是用于控制选择使用上下拉电阻还是使用状态保持器,当设置为 0 的时候,选择使用状态保持器(上下拉关闭);当设置为 1 的时候,选择使用上下拉电阻(状态保持器关闭),因此上下拉和状态保持器只能二选一。
关于状态保持器(KEEPER)的说明
RT1052 的每个 IO 口,都有一个状态保持器,但是它在输入模式下,叫输入状态保持器,用于当外部电路断电时(此时 MCU 还是供电的),维持 IO 口的状态,有利于低功耗应用。而在输出模式下,它又叫输出状态保持器,用于当内核断电时,维持 IO 口的输出状态,同样有利于低功耗应用。
一般情况下,当我们使用 IO 口做输入模式的时候,设置上下拉模式(PUE=1);当我们使用 IO 口作为输出模式的时候,设置状态保持器模式(PUE=0);
GPIO_DR 数据寄存器在输出模式(GDIR=1)下,写入 DR 的数据将会输出到对应的 IO 引脚,用于控制 IO 的高低电平。
在输入模式(GDIR=0)下,通过读取 DR 寄存器对应位,可以读取对应 IO 引脚的状态值。
GPIO_GDIR 方向控制寄存器用于控制 IO 口的输入/输出方向,当 GDIR 对应位设置为 0时,对应 IO 为输入模式。当 GDIR 对应位设置为 1 时,对应 IO 为输出模式。
GPIO_GDIR 方向控制寄存器用于控制 IO 口的输入/输出方向,当 GDIR 对应位设置为 0时,对应 IO 为输入模式。当 GDIR 对应位设置为 1 时,对应 IO 为输出模式。
GPIO_PSR引脚状态寄存器用于读取IO口的状态,相当于输入模式下的GPIO_DR寄存器。
注意:当 IOMUXC 开启 IO 口的强制输入(SION=1)时,可以通过 GPIO_PSR
读取 IO 口的状态。
GPIO_ICR1 用于配置 IO0~IO15 的中断触发条件,总共有 4 种触发条件可选:00,低电平触发;01,高电平触发;10,上升沿触发;11,下降沿触发。
GPIO_IMR 中断屏蔽寄存器用于使能/禁止 IO 的中断功能,当 GPIO_IMR 对应位设置成 1的时候,使能对应 IO 口的中断功能,反之则禁止。
GPIO_EDGE_SEL 边沿选择寄存器用于设置上升沿&下降沿触发中断。
注意:该寄存器的设置,会覆盖 ICR1/ICR2 的设置。
RT1064的IO口不能容忍5V。
如果需要和 5V 设备连接,输出模式:请使用开漏输出模式配合上拉电阻(接 5V)实现,且灌电流越小越好,最大单个 IO 的灌电流不要超 过 1mA,整个芯片的灌电流不要超过 10mA。输入模式:请串联大电阻!
IOMUXC_SetPinMux 函数 (fsl_iomuxc.h)
用于设置IO的复用功能
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
muxRegister:IO复用功能选择寄存器的地址
muxMode:选择的复用的模式
inputRegister:选择的输入寄存器
inputDaisy:DAISY 位
configRegister:配置寄存器
inputOnfield:设置是否为强制输入
若这些参数要一个个找会很麻烦,在fsl_iomuxc.h中1188行之前
IOMUXC_SetPinConfig函数 (fsl_iomuxc.h)
此函数用来配置 IO 的驱动能力、速度、驱动能力等
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
前5个参数与上个函数一样
configValue:写入到IOMUXC_SW_PAD_CTL_PAD_
GPIO_PinInit 函数 (fsl_gpio.h)
设置指定 GPIO 引脚的功能
void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config)
base:要设置的GPIO的组
pin:组内编号
Config:配置参数
typedef struct _gpio_pin_config
{
gpio_pin_direction_t direction; //方向,输入还是输出?
uint8_t outputLogic; //默认输出电平
gpio_interrupt_mode_t interruptMode; //中断模式
} gpio_pin_config_t;
direction:
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, /*!< Set current pin as digital input.*/
kGPIO_DigitalOutput = 1U, /*!< Set current pin as digital output.*/
} gpio_pin_direction_t;
outputLogic:0 or 1
interruptMode:六种设置
typedef enum _gpio_interrupt_mode
{
kGPIO_NoIntmode = 0U, /*!< Set current pin general IO functionality.*/
kGPIO_IntLowLevel = 1U, /*!< Set current pin interrupt is low-level sensitive.*/
kGPIO_IntHighLevel = 2U, /*!< Set current pin interrupt is high-level sensitive.*/
kGPIO_IntRisingEdge = 3U, /*!< Set current pin interrupt is rising-edge sensitive.*/
kGPIO_IntFallingEdge = 4U, /*!< Set current pin interrupt is falling-edge sensitive.*/
kGPIO_IntRisingOrFallingEdge = 5U, /*!< Enable the edge select bit to override the ICR register's configuration.*/
} gpio_interrupt_mode_t;
GPIO_PinWrite 函数 (fsl_gpio.h)
设置指定的 GPIO 的输出电平
void GPIO_PinWrite(GPIO_Type *base, uint32_t pin, uint8_t output);
base:要设置的GPIO的组
pin:组内编号
output:输出电平,1为高电平,0为低电平
此函数用于读取一个指定 IO 的电平
static inline uint32_t GPIO_PinRead(GPIO_Type *base, uint32_t pin)
base:要设置的 GPIO 组
pin:组内编号
返回值:读到的指定 IO 的电平值,1 为高电平,0 为低电平
配置为输出模式时,输入部分的参数配置自动失效;
配置为输入模式时,输出部分的参数配置自动失效
详见SW_PAD_CTL_PAD——IO属性配置寄存器
应该主要看的是DSE
void LED_Init(void)
{
gpio_pin_config_t led_config;
//设置 B3 的复用功能选择寄存器,设置B3为普通GPIO模式
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_03_GPIO1_IO03,0);
//配置 B3 的功能
//0 0001 0000 1011 0000
//关闭 Hyst,下拉 100K Ohm,选择Keeper,使能pull/keeper,关闭开漏,100MHz_SPEED1,驱动能力R0/6,低转换速度
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_03_GPIO1_IO03,0x10B0);
led_config.direction=kGPIO_DigitalOutput;
led_config.interruptMode=kGPIO_NoIntmode;
led_config.outputLogic=1;
GPIO_PinInit(GPIO1,3,&led_config);//此函数中自动打开时钟
}
void KEY_Init(void)
{
gpio_pin_config_t key_config;
//设置 B3 的复用功能选择寄存器,设置B3为普通GPIO模式
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_03_GPIO1_IO03,0);
//配置 B3 的功能
//0 1111 0000 1000 0000
//关闭 Hyst,上拉 22K Ohm,选择Pull,使能pull/keeper,关闭开漏,100MHz_SPEED2,关闭输出驱动,低转换速度
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_03_GPIO1_IO03,0xF080);
led_config.direction=kGPIO_DigitalInput; //输入
led_config.interruptMode=kGPIO_NoIntmode; //无中断
led_config.outputLogic=1; //此值设置为输出时才有效
GPIO_PinInit(GPIO1,3,&led_config);//此函数中自动打开时钟
}
本文参照正点原子RT1052 开发指南。