初始rt1052GPIO之输入输出操作
前面几个帖子已经把环境大了起来,那么这个帖子即开始让rt1052跑起来吧,当然了 ,还行先从最基础的gpio搞起来,循序渐进嘛。。。
然后呢激励爱做实验用按键控制led的相关操作。
想来看下半只资源的硬件连接吧
led:(DS0 和 DS1)
DS0 接 P103(GPIO1_IO03), DS1 接 P303(GPIO3_IO03)。 如下图
<ignore_js_op>
key:(KEY0、 KEY1、 KEY2、和 KEY_UP)
按键
KEY0 连接在 P105(GPIO1_IO05)上、 KEY1 连接在 P501(GPIO5_IO01) 上、 KEY2 连接在P326(GPIO3_IO26)上、 KEY_UP 连接在 P500(GPIO5_IO00) 上 。
<ignore_js_op> 四个按键都是低电平有效的, 并且外部都没有(KEY0 除外)接上拉电阻,所以,需要在 RT1052 内部设置上拉电阻。另外, KEY0 和 BOOT_MODE1 共用,按住KEY0,则 BOOT_MODE1 接 GND,所以上电的时候,不要按住 KEY0,否则无法正常启动。
RT1052 的 IO 口总共分成 5 组: GPIO1~GPIO5,其中: GPIO1、 GPIO2 和 GPIO4 每组 32个 IO, GPIO3 只有 28 个 IO, GPIO5 最少,只有 3 个 IO,这样总共是 127 个 IO 口。
RT1052 的 IO 口可以有很多个 Block(控制块),每个 Block 其实就是一个复用功能, GPIO功能也属于这些 Block 里面的一个。其他的,比如串口、 SPI、 CAN、 CSI、 SEMC 等,这些都是控制 IO 口的 Block,最多一个 IO 口可以由 8 个 lock(ALT0~ALT7)控制 。
IO 口通过一个叫 IOMUXC 的 IO 复用选择器来选择具体的功能(具体连接到那个 Block 上面),我们先来看一下 RT1052 的 IO 复用功能框图 :
<ignore_js_op>
任意一个 IO 的 2 个控制寄存器,可以用如下通用名字表示:
1, IOxxxxx 复用功能选择寄存器: yyyyy_SW_MUX_CTL_PAD_xxxxx
2, IOxxxxx 属性设置寄存器: yyyyy_SW_PAD_CTL_PAD_xxxxx
其中 yyyyy 表示所属分组,可以为: IOMUXC 和 IOMUXC_SNVS。 xxxxx 则表示具体的 IO名字了(注意是以复用功能命名的),比如: GPIO_AD_B0_01、 GPIO_AD_B1_15、 GPIO_B0_03之类的,总共 127 个。
IO 复用功能选择器(IOMUXC)的寄存器非常多,主要可以分为四组:
① IOMUXC_GPR 寄存器组, 用于通用控制设置。
② IOMUXC_SNVS 组,主要用于 GPIO5 的控制。
③ IOMUXC_SNVS_GPR 寄存器组,暂时没用到。
④ IOMUXC 组, 用于指定 IO 的复用功能选择和 IO 属性设置。
FSL 库提供的 API 函数
1、 IOMUXC_SetPinMux 函数
此函数是用来设置 IO 的复用选择器的,用来选择 IO 的功能的,比如本实验的
GPIO_AD_B0_03 要设置为 GPIO1_IO03,本函数原型如下:
- <span class="fontstyle2">static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
- uint32_t muxMode,
- uint32_t inputRegister,
- uint32_t inputDaisy,
- uint32_t configRegister,
- uint32_t inputOnfield)</span>
2、 IOMUXC_SetPinConfig 函数
此函数用来配置 IO 的驱动能力、速度、 驱动能力等这些的,对于 GPIO_AD_B0_03 来说就是设置寄存器 IOMUX_SW_PAD_CTL_PAD_GPIO_AD_B0_03 的值, 此函数原型如下:
- static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
- uint32_t muxMode,
- uint32_t inputRegister,
- uint32_t inputDaisy,
- uint32_t configRegister,
- uint32_t configValue)
3、 GPIO_PinInit 函数
此函数用来设置指定 GPIO 引脚的功能的,比如 GPIO_AD_B0_03 设置为 GPIO_IO03 以后就需要初始化 GPIO1_IO03 了:输入还是输出?用不用中断?默认电平是什么? 此函数原型如下:
- void GPIO_PinInit(GPIO_Type *base, uint32_t pin, const gpio_pin_config_t *Config);
base:要设置的 GPIO 组, GPIO1_IO03 就是 GPIO1 组的。
pin:组内编号,比如 GPIO1_IO03 就是 GPIO1 组中的 3 号 IO。
Config:配置参数,使用结构体来设置指定 GPIO 的配置参数,此结构体如下:
- typedef struct _gpio_pin_config
- {
- gpio_pin_direction_t direction; //方向,输入还是输出?
- uint8_t outputLogic; //默认输出电平
- gpio_interrupt_mode_t interruptMode; //中断模式
- } gpio_pin_config_t;
4、 GPIO_PinWrite 函数
设置指定的 GPIO 的输出电平,函数原型如下:
- void GPIO_PinWrite(GPIO_Type *base, uint32_t pin, uint8_t output);
base:要设置的 GPIO 组, GPIO1_IO03 就是 GPIO1 组的。
pin:组内编号,比如 GPIO1_IO03 就是 GPIO1 组中的 3 号 IO。
output:输出电平, 1 为高电平, 0 为低电平。
5、 GPIO_PinRead 函数
此函数用于读取一个指定 IO 的电平,函数原型如下:
- static inline uint32_t GPIO_PinRead(GPIO_Type *base, uint32_t pin)
base:要设置的 GPIO 组, GPIO1_IO03 就是 GPIO1 组的。
pin:组内编号,比如 GPIO1_IO03 就是 GPIO1 组中的 3 号 IO。
返回值:读到的指定 IO 的电平值, 1 为高电平, 0 为低电平。
然后就是led的初始化代码了
<ignore_js_op>
<ignore_js_op>
LED作为gpio的输出功能已经配置好了,下面来研究下gpio的输入功能,按键需要用得到的
初始化
<ignore_js_op>
按键处理函数
<ignore_js_op>
至此,gpio已经初始化完毕,然后在主循环中检测按键,判断每个那件按下时需要执行的功能即可
- int main(void)
- {
- u8 key=0;
- u8 led0sta=1,led1sta=1; //LED0,LED1的当前状态
- MPU_Memory_Protection(); //初始化MPU
- RT1052_Clock_Init(); //配置系统时钟
- DELAY_Init(600); //延时函数初始化
- LPUART1_Init(115200); //初始化串口1
- LED_Init(); //初始化LED
- KEY_Init(); //初始化KEY
- LED0(0); //先点亮红灯
- while(1)
- {
- key=KEY_Scan(0); //得到键值
- if(key)
- {
- switch(key)
- {
- case WKUP_PRES: //控制LED0,LED1互斥点亮
- led1sta=!led1sta;
- led0sta=!led1sta;
- break;
- case KEY2_PRES: //控制LED0翻转
- led0sta=!led0sta;
- break;
- case KEY1_PRES: //控制LED1翻转
- led1sta=!led1sta;
- break;
- case KEY0_PRES: //同时控制LED0,LED1翻转
- led0sta=!led0sta;
- led1sta=!led1sta;
- break;
- }
- LED0(led0sta); //控制LED0状态
- LED1(led1sta); //控制LED1状态
- }else delay_ms(10);
- }
- }
最后来看下运行效果吧