RT-1052学习笔记 - GPIO架构分析
一、RT1052之GPIO与IOMUX
二、GPIO架构分析
原文链接:https://blog.csdn.net/weixin_42264572/article/details/84972405
前提提一句,i.MX RT1052与imx6ul的很多片内外设的架构长的都是一样的。
分析GPIO的外设框架
橙色部分:由IOMUX控制,负责控制IO口的输入输出使能,上下拉或者开漏,保持,驱动能力,压摆率,带宽,HYS滞后使能输入。这部分通过配置IOMUX控制。
红色部分:配置橙色部分的功能,以及选择这个IO到底被谁用,通过MUX寄存器选择。还包括一个在输出的同时还可以读取IO电平的使能端,使能这个功能则输出同步输入
蓝色部分:用这个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);
使用
输出:设置GPIO->DR的对应位设置对应IO的电平
输入:读取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格式代码或者设备树配置文件。
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引脚状态
GPIO_PinWrite(GPIO1, 9, 0U);
三、驱动74hc595,级联模式
1.驱动头文件74hct595.h
/*
* Copyright 2017-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _74HCT595_H_
#define _74HCT595_H_
#include "clock_config.h"
#include "fsl_common.h"
#include "fsl_gpio.h"
#include "fsl_clock.h"
#include "fsl_iomuxc.h"
#include "pin_mux.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#define BOARD_595_OE_GPIO_PIN (25U)
#define BOARD_595_OE_GPIO GPIO1
#define BOARD_595_OE_PIN_MUX IOMUXC_GPIO_AD_B1_09_GPIO1_IO25
#define BOARD_595_MR_GPIO_PIN (31U)
#define BOARD_595_MR_GPIO GPIO1
#define BOARD_595_MR_PIN_MUX IOMUXC_GPIO_AD_B1_15_GPIO1_IO31
#define BOARD_595_SH_CP_GPIO_PIN (30U)
#define BOARD_595_SH_CP_GPIO GPIO1
#define BOARD_595_SH_CP_PIN_MUX IOMUXC_GPIO_AD_B1_14_GPIO1_IO30
#define BOARD_595_STCP_GPIO_PIN (29U)
#define BOARD_595_STCP_GPIO GPIO1
#define BOARD_595_STCP_PIN_MUX IOMUXC_GPIO_AD_B1_13_GPIO1_IO29
#define BOARD_595_SDI_GPIO_PIN (28U)
#define BOARD_595_SDI_GPIO GPIO1
#define BOARD_595_SDI_PIN_MUX IOMUXC_GPIO_AD_B1_12_GPIO1_IO28
#define LED_RUN_GPIO_PIN (9U)
#define LED_RUN_GPIO GPIO1
#define LED_RUN_PIN_MUX IOMUXC_GPIO_AD_B0_09_GPIO1_IO09
#define LED_RUN_ON GPIO_PinWrite(LED_RUN_GPIO, LED_RUN_GPIO_PIN, 1U)
#define LED_RUN_OFF GPIO_PinWrite(LED_RUN_GPIO, LED_RUN_GPIO_PIN, 0U)
#define LED_ALARM_GPIO_PIN (10U)
#define LED_ALARM_GPIO GPIO1
#define LED_ALARM_PIN_MUX IOMUXC_GPIO_AD_B0_10_GPIO1_IO10
#define LED_ALARM_ON GPIO_PinWrite(LED_ALARM_GPIO, LED_ALARM_GPIO_PIN, 1U)
#define LED_ALARM_OFF GPIO_PinWrite(LED_ALARM_GPIO, LED_ALARM_GPIO_PIN, 0U)
#define LED_COMM_GPIO_PIN (11U)
#define LED_COMM_GPIO GPIO1
#define LED_COMM_PIN_MUX IOMUXC_GPIO_AD_B0_11_GPIO1_IO11
#define LED_COMM_ON GPIO_PinWrite(LED_COMM_GPIO, LED_COMM_GPIO_PIN, 1U)
#define LED_COMM_OFF GPIO_PinWrite(LED_COMM_GPIO, LED_COMM_GPIO_PIN, 0U)
extern void hct595_Init(void);
extern void hct595_SetValue(uint16_t value);
extern void delay(uint32_t count);
#endif /* _74HCT595_H_ */
2.驱动源文件74hct595.c
/*
* Copyright 2017-2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "74hct595.h"
void hct595_Init(void);
static void GPIO_Mode_Config(void);
void hct595_SetValue(uint16_t value)
{
for(int i = 0; i < 16; i++)
{
GPIO_PinWrite(BOARD_595_SH_CP_GPIO, BOARD_595_SH_CP_GPIO_PIN, 0U); //SH=0
if(value & 0x8000)
GPIO_PinWrite(BOARD_595_SDI_GPIO, BOARD_595_SDI_GPIO_PIN, 1U);
else
GPIO_PinWrite(BOARD_595_SDI_GPIO, BOARD_595_SDI_GPIO_PIN, 0U);
delay(700000);
GPIO_PinWrite(BOARD_595_SH_CP_GPIO, BOARD_595_SH_CP_GPIO_PIN, 1U); //SH=1
delay(700000);
value = value << 1;
}
GPIO_PinWrite(BOARD_595_STCP_GPIO, BOARD_595_STCP_GPIO_PIN, 0U); //ST=0
delay(700000);
GPIO_PinWrite(BOARD_595_STCP_GPIO, BOARD_595_STCP_GPIO_PIN, 1U); //ST=1
delay(700000);
}
void hct595_Init(void)
{
IOMUXC_SetPinMux(BOARD_595_OE_PIN_MUX, 0U);
IOMUXC_SetPinConfig(BOARD_595_OE_PIN_MUX, 0x10B0u);
IOMUXC_SetPinMux(BOARD_595_MR_PIN_MUX, 0U);
IOMUXC_SetPinConfig(BOARD_595_MR_PIN_MUX, 0x10B0u);
IOMUXC_SetPinMux(BOARD_595_SH_CP_PIN_MUX, 0U);
IOMUXC_SetPinConfig(BOARD_595_SH_CP_PIN_MUX, 0x10B0u);
IOMUXC_SetPinMux(BOARD_595_STCP_PIN_MUX, 0U);
IOMUXC_SetPinConfig(BOARD_595_STCP_PIN_MUX, 0x10B0u);
IOMUXC_SetPinMux(BOARD_595_SDI_PIN_MUX, 0U);
IOMUXC_SetPinConfig(BOARD_595_SDI_PIN_MUX, 0x10B0u);
//led
IOMUXC_SetPinMux(LED_RUN_PIN_MUX, 0U);
IOMUXC_SetPinConfig(LED_RUN_PIN_MUX, 0x10B0u);
IOMUXC_SetPinMux(LED_ALARM_PIN_MUX, 0U);
IOMUXC_SetPinConfig(LED_ALARM_PIN_MUX, 0x10B0u);
IOMUXC_SetPinMux(LED_COMM_PIN_MUX, 0U);
IOMUXC_SetPinConfig(LED_COMM_PIN_MUX, 0x10B0u);
//GPIO输入输出属性配置
GPIO_Mode_Config();
//MR = 1
GPIO_PinWrite(BOARD_595_MR_GPIO, BOARD_595_MR_GPIO_PIN, 0U);
delay(700000);
GPIO_PinWrite(BOARD_595_MR_GPIO, BOARD_595_MR_GPIO_PIN, 1U);
GPIO_PinWrite(BOARD_595_OE_GPIO, BOARD_595_OE_GPIO_PIN, 0U);
}
static void GPIO_Mode_Config(void)
{
/* 定义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(LED_RUN_GPIO, LED_RUN_GPIO_PIN, &led_config);
GPIO_PinInit(LED_ALARM_GPIO, LED_ALARM_GPIO_PIN, &led_config);
GPIO_PinInit(LED_COMM_GPIO, LED_COMM_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_595_OE_GPIO, BOARD_595_OE_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_595_MR_GPIO, BOARD_595_MR_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_595_SDI_GPIO, BOARD_595_SDI_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_595_SH_CP_GPIO, BOARD_595_SH_CP_GPIO_PIN, &led_config);
GPIO_PinInit(BOARD_595_STCP_GPIO, BOARD_595_STCP_GPIO_PIN, &led_config);
}