在线时间717 小时
UID3469866
注册时间2018-4-19
NXP金币3763

TA的每日心情 | 慵懒 2025-5-7 08:45 |
---|
签到天数: 279 天 连续签到: 1 天 [LV.8]以坛为家I
版主
  
- 积分
- 11056

- 最后登录
- 2025-8-17
|
今天看了看RT1052的GPIO,感觉这玩意比STM32复杂多了,今天我们来尝试了解一下它先从LED点灯开始。
可以看出飞凌底板上的LED是连接的GPIO1_IO02脚。 首先放出例程的配置方式(删除了注释)
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0x10B0u);
其中
#define IOMUXC_GPIO_AD_B0_09_GPIO1_IO09 0x401F80E0U, 0x5U, 0, 0, 0x401F82D0U
这红色的字体就是这次配置的关键了。首先看IOMUXC_SetPinMux函数
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
{
*((volatile uint32_t *)muxRegister) =
IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield);
if (inputRegister)
{
*((volatile uint32_t *)inputRegister) = inputDaisy;
}
}
#define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_MASK (0x7U)
#define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_SHIFT (0U)
#define IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(x) (((uint32_t)(((uint32_t)(x)) << IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_SHIFT)) & IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_MASK)
#define IOMUXC_SW_MUX_CTL_PAD_SION_MASK (0x10U)
#define IOMUXC_SW_MUX_CTL_PAD_SION_SHIFT (4U)
#define IOMUXC_SW_MUX_CTL_PAD_SION(x) (((uint32_t)(((uint32_t)(x)) << IOMUXC_SW_MUX_CTL_PAD_SION_SHIFT)) & IOMUXC_SW_MUX_CTL_PAD_SION_MASK)
可以看出,我们配置了0x401F80E0U的第0—2位为0x5U,第4位为0
我们来看一下这个0x401F80E0U到底是个什么地址
可以看出来,第4位为0时可以设置功能复用,而0—2位设置的是功能复用,这里设置为GPIO1功能
然后是IOMUXC_SetPinConfig函数
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
{
if (configRegister)
{
*((volatile uint32_t *)configRegister) = configValue;
}
}
可以看出是配置0x401F82D0U为0x10B0u。
我们来看一下0x401F82D0U是什么
可以看出来这里是对引脚功能的设置,这里的0x10B0u就是设置为 转化速率慢,驱动强度为R0/6,速度100MHz,关闭开漏,开启拉/保持器,选择为保持,100K下拉(无用),关闭滞回。
感觉写这么一个数不好理解,我改写了一下这个函数
//转换速率 0 慢 1 快
//驱动强度 0 无 1 R0 2 R0/2 3 R0/3 4 R0/4 5 R0/5 6 R0/6 7 R0/7
//输出速度 0 50MHz 1 100MHz 2 100MHz 3 200MHz
//开漏输出 0 关闭 1 开启
//拉/保持器 0 关闭 1 开启
//拉/保持器设置 0 保持 1 拉
//上下拉电阻 0 100K下拉 1 47K上拉 2 100K上拉 3 22K上拉
//滞回器设置 0 关闭 1开启
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_02_GPIO1_IO02, IOMUXC_SW_PAD_CTL_PAD_SRE(0) //转换速率慢
|IOMUXC_SW_PAD_CTL_PAD_DSE(6) //驱动强度R0/6
|IOMUXC_SW_PAD_CTL_PAD_SPEED(2) //速度100MHz
|IOMUXC_SW_PAD_CTL_PAD_ODE(0) //关闭开漏
|IOMUXC_SW_PAD_CTL_PAD_PKE(1) //拉/保持器开启
|IOMUXC_SW_PAD_CTL_PAD_PUE(0) //选择为保持
|IOMUXC_SW_PAD_CTL_PAD_PUS(0) //100K下拉(没用到)
|IOMUXC_SW_PAD_CTL_PAD_HYS(0)); //关闭滞回
感觉这样更容易理解,更容易操作一点。
接下来就是配置GPIO了,下面只放出关键程序
gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; //设为输出 默认输出0 无中断
GPIO_PinInit(GPIO1, 2, &led_config);
这两句很好理解,首先设置led_config
typedef struct _gpio_pin_config
{
gpio_pin_direction_t direction; //设置输出方向
uint8_t outputLogic; //设置初始电平
gpio_interrupt_mode_t interruptMode; //设置中断模式
} gpio_pin_config_t;
里面有这三个成员 取值如下
typedef enum _gpio_pin_direction
{
kGPIO_DigitalInput = 0U, //输入
kGPIO_DigitalOutput = 1U, //输出
} gpio_pin_direction_t;
typedef enum _gpio_interrupt_mode
{
kGPIO_NoIntmode = 0U, //无中断
kGPIO_IntLowLevel = 1U, //低电平中断
kGPIO_IntHighLevel = 2U, //高电平中断
kGPIO_IntRisingEdge = 3U, //上升沿中断
kGPIO_IntFallingEdge = 4U, //下降沿中断
kGPIO_IntRisingOrFallingEdge = 5U, //上升下降沿中断
} gpio_interrupt_mode_t;
就是把GPIO1_2配置为输出模式,默认输出1,无中断。(这里的寄存器也没啥好分析的,接下来就不讨论了寄存器了)
GPIO_PinWrite(GPIO1, 2, 0U);//点亮LED
delay(10);
GPIO_PinWrite(GPIO1, 2, 1U);//熄灭LED
delay(10);
相当简单的程序 运行结果就是灯一闪一闪的,效果见视频附件
接下来是GPIO输入 参考原理图
嗯,这GPIO5_0就是我们要的。对他进行配置
IOMUXC_SetPinMux(IOMUXC_SNVS_WAKEUP_GPIO5_IO00, 0U); //复用为GPIO
IOMUXC_SetPinConfig(IOMUXC_SNVS_WAKEUP_GPIO5_IO00, IOMUXC_SW_PAD_CTL_PAD_SRE(0) //转换速率慢
|IOMUXC_SW_PAD_CTL_PAD_DSE(0) //无驱动强度(没用到)
|IOMUXC_SW_PAD_CTL_PAD_SPEED(2) //速度100MHz(没用到)
|IOMUXC_SW_PAD_CTL_PAD_ODE(0) //关闭开漏(没用到)
|IOMUXC_SW_PAD_CTL_PAD_PKE(1) //拉/保持器开启
|IOMUXC_SW_PAD_CTL_PAD_PUE(1) //选择为拉
|IOMUXC_SW_PAD_CTL_PAD_PUS(3) //22K上拉
|IOMUXC_SW_PAD_CTL_PAD_HYS(0)); //关闭滞回
这里我们把它设为了22K上拉(这里只能配置为,拉/保持器开启,选择为拉。具体原因应该是RT1052把使能上下拉设为了输入专用了。而输出使用的是配置开漏,和配置驱动能力)。下面是main里程序(省略很多)
gpio_pin_config_t key_config = {kGPIO_DigitalInput, 0, kGPIO_NoIntmode}; //设为输入 默认输出0 无中断
GPIO_PinInit(GPIO5, 0, &key_interrupt_config);
while(1)
{
GPIO_PinWrite(GPIO1, 2, GPIO_PinReadPadStatus(GPIO5,0));
}
补充一句,如果设置为输入模式那么默认输出电平就不起作用
这里的GPIO_PinReadPadStatus是一个读取引脚电平的函数,运行结果是按住按键灯亮,松开灭。
接下来是配置外部中断。参考MIMXRT1052.h
可以发现包含GPIO5_0的中断是GPIO5_Combined_0_15_IRQn,中断回调函数是GPIO5_Combined_0_15_IRQHandler(MIMXRT1052.s有定义)
还是和刚才一样配置引脚模式,下面是main里程序(省略很多)
gpio_pin_config_t key_interrupt_config = {kGPIO_DigitalInput, 1, kGPIO_IntFallingEdge}; //设为输入 默认输出0 下降沿中断
EnableIRQ(GPIO5_Combined_0_15_IRQn);//使能中断
GPIO_PinInit(GPIO5, 0, &key_interrupt_config);
GPIO_PortEnableInterrupts(GPIO5, 1U << 0); //使能特定引脚中断
中断回调函数
void GPIO5_Combined_0_15_IRQHandler(void)
{
delay(1); //消除抖动
if(GPIO_PinReadPadStatus(GPIO5, 0) == 0) //二次判断
GPIO_PortToggle(GPIO1,1<<2); //灯取反
GPIO_PortClearInterruptFlags(GPIO5, 1 << 0); //清除中断标志位
__DSB();
}
这里的代码和普通的代码差不多,就不分析了。
比较有意思的是这个__DSB();它的作用是只有CPU把这句话之前的代码全部执行完毕后才能继续向下执行。
最后的效果是按下按键后灯转换状态补充一点如果不需要go to什么的,可以把output里的两个输出去掉,大大加快了编译速度
最后不得不吐槽一句底板的绿灯有点太亮了。。。。。晚上拍的视频看着特别显眼。
最后附上程序和视频
MDK版本:5.24
pack:NXP.MIMXRT1052_DFP.10.0.1.pack
下载算法:飞凌嵌入式提供的 MIMXRT_QSPIFLASH.FLM
启动方式:spi flash启动
下载方式:STlink
|
|