控制IO的输入和输出是非常常用的功能,一般在操作时都是直接操作GPIO的寄存器,其实我们完全可以对GPIO寄存器进行提炼,做一个针对GPIO的驱动,可以仿照STM32的标准外设库对IMX6U的GPIO进行一个二次的封装,其实就是对GPIO的寄存器的封装。后续再需要设置GPIO时只需要调用封装完成的函数就行了。
以上一个博客的按键蜂鸣器程序为例,在这个程序的基础上创建一个bsp_gpio文件夹,在这个文件夹中存放我们要封装的GPIO驱动程序。
对于通用GPIO首先都要有个初始化 ,仿照stm32创建一个表示IO信息的结构体 ,IO要么输入要么输出,所以我们创建一个枚举类型来表示这两种值,并且在IO的结构体中会包含这个枚举类型
bsp_gpio.h如下所示:在这个头文件中我定义了一个枚举类型表示IO的方向;定义了以及IO的结构体,其中包括IO的方向以及输出的高或低电平。用这些变量来代替写入寄存器的0和1.
#ifndef __BSP_GPIO_H
#define __BSP_GPIO_H
#include "imx6u.h"
typedef enum GPIO_Direction_t
{
//输入方向设置为0
KGPIO_DigitalInput = 0U,
//输出方向设置为1
KGPIO_DigitalOutput = 1U,
}GPIO_Direction;
typedef struct GPIO_Config_t
{
//GPIO的参数包括输出输入方向,
GPIO_Direction Direction;
//输出的高低电平
uint8_t OutputLogic;
//输入的高低电平是读取DR寄存器才能知道的,这里不需要设置,而且也没法设置,或者设置一个变量用来保存读取的DR寄存器的值,但这是不必要的
}GPIO_Config;
void GPIO_Init(GPIO_Type *Base,int Pin, GPIO_Config *Config);
void GPIO_WritePin(GPIO_Type *Base,int Pin, int Value);
int GPIO_ReadPin(GPIO_Type *Base,int Pin);
#endif // !1
bsp_gpio.c如下所示:
这个c文件主要是将GPIO的GDIR和DR寄存器进行了封装;在编写驱动时主要是对这两个寄存器进行读写操作,后续会在这个c文件的基础上继续封装GPIO的其他寄存器
#include "bsp_gpio.h"
//gpio初始化
void GPIO_Init(GPIO_Type *Base,int Pin, GPIO_Config *Config)
{
//GPIO引脚设置为Input,IMX6U设置输入是将GDIR相应位置0
if(Config->Direction == KGPIO_DigitalInput)
{
Base->GDIR &= ~(1<<Pin);
}
//如果是设置为输出就将GDIR相应位置1,并且还要设置输出的电平是高还是低
else
{
Base->GDIR |= (1<<Pin);
GPIO_WritePin(Base,Pin,Config->OutputLogic);
}
}
//设置输出电平,向DR寄存器中写1或0
void GPIO_WritePin(GPIO_Type *Base,int Pin, int Value)
{
//写高点平1
if(Value == 1)
{
Base->DR |= (Value<<Pin);
}
//写低电平0
if(Value == 0)
{
Base->DR &= ~(Value<<Pin);
}
}
//读DR寄存器,这里将GPIO的对应的引脚的DR寄存器的值右移到最低位再与上0x1就能得到
int GPIO_ReadPin(GPIO_Type *Base,int Pin)
{
/* 提取特定位:通过位与操作与0x1(即二进制的0000 0001)进行运算,可以提取出任何整数的最低位。
它用于提取Base->DR右移Pin位后的最低位,
这通常用于检查某个特定的Base引脚是高电平(1)还是低电平(0)。
简化处理:位与操作可以确保结果只包含0或1,这对于表示二进制状态(如开/关、高/低)非常有用。
*/
return (((Base->DR)>>Pin)&0x1);
}
将这两个文件包含到程序中,将原程序中操作GPIO寄存器的地方使用bsp_gpio文件中的函数进行替换。
替换前:bsp_key.c查看上一博客
替换后:bsp_key.c
#include "bsp_key.h"
#include "bsp_delay.h"
void Key_Init(void)
{
GPIO_Config Config;
Config.Direction = KGPIO_DigitalInput;
//根据原理图和手册,设置UART1_CTS复用为GPIO1_IO18
IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18,0);
IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0XF080);
// GPIO1->GDIR &= ~(1<<18);
GPIO_Init(GPIO1,18,&Config);
}
int Read_Key(void)
{
int ret =0;
ret = GPIO_ReadPin(GPIO1,18);
//ret = GPIO1->DR >> 18 & 0X1;
return ret;
}
int Get_Value(void)
{
//状态机
int ret = 0;
static int release = 1;//默认按键是释放
//如果在按键释放状态下检测到按键被按下
if(release == 1 && GPIO_ReadPin(GPIO1,18) == 0 )
{
//在延时后再判断按键是否被释放
//这里的标志位被按下是0
release = 0;
delay(10);
//如果按键还是被按下
if(GPIO_ReadPin(GPIO1,18) == 0)
{
ret = Key0_Value;//直接返回0表示按键被按下
}
}
else if(GPIO_ReadPin(GPIO1,18) == 1)//表示按键没有被按下
{
ret = 0;
release = 1;
}
return ret;
}
替换前:bsp_beep.c查看上一博客
替换后:bsp_beep.c
#include "bsp_beep.h"
void Beef_Init(void)
{
GPIO_Config Beep_Config;
Beep_Config.Direction=KGPIO_DigitalOutput;
Beep_Config.OutputLogic=1;
//复用为gpio5_io01
IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0);
//设置电气属性
IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0x10B0);
//gpio初始化
GPIO_Init(GPIO5,1,&Beep_Config);
//GPIO5->GDIR |= (1<<1);//设置为输出
//GPIO5->DR |= (1<<1);//默认关闭
}
void Beep_Switch(int status)
{
if(status == ON)
{
GPIO_WritePin(GPIO5,1,0);
// GPIO5->DR &= ~(1<<1);
}
else if(status == OFF)
{
GPIO_WritePin(GPIO5,1,1);
// GPIO5->DR &= (1<<1);
}
}
将创建的新文件bsp_gpio添加到.vscode和Makefile中进行编译,编译成功
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/ledc_stm32.o project/ledc_stm32.s
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/main.o project/main.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/bsk_clk.o bsp/clk/bsk_clk.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/bsp_delay.o bsp/delay/bsp_delay.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/bsp_led.o bsp/led/bsp_led.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/bsp_beep.o bsp/beep/bsp_beep.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/bsp_key.o bsp/key/bsp_key.c
arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -I imx6u -I bsp/clk -I bsp/delay -I bsp/led -I bsp/beep -I bsp/key -I bsp/gpio -o obj/bsp_gpio.o bsp/gpio/bsp_gpio.c
arm-linux-gnueabihf-ld -Timx6u.lds -o key.elf obj/ledc_stm32.o obj/main.o obj/bsk_clk.o obj/bsp_delay.o obj/bsp_led.o obj/bsp_beep.o obj/bsp_key.o obj/bsp_gpio.o
arm-linux-gnueabihf-objcopy -O binary -S key.elf key.bin
arm-linux-gnueabihf-objdump -D -m arm key.elf > key.dis
成功运行代码