基于I.MX6U的通用GPIO驱动编写

控制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

成功运行代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值