Linux用户态GPIO

本文详细介绍了如何在Linux系统中通过SYSFS接口操作周立功MX2000开发板的GPIO,包括GPIO的导出、导出后的功能设置(如方向、电平、中断触发等),以及在C语言程序中的使用示例。
摘要由CSDN通过智能技术生成

一、简介

        开发板:周立功的MX2000-B-EV-Board

        官网资料:MX2000

        Linux提供了通过SYSFS的方式控制GPIO,刚好对应Linux下一切皆文件,通过对文件的读写操作就能实现对GPIO控制。

        使用 ls /sys/class/gpio 查看该目录,如果没有需要在内核驱动中选择并编译进来Device Drivers > GPIO Support  > /sys/class/gpio

        从上图可以看出有两个文件export、unexport和多个gpiochipX 类型文件夹,文件作用描述和使用方法如下:

export:用于将指定编号的引脚导出,作为GPIO使用

 使用export导出后的GPIO信息如下

active_low:设置value中的值是否翻转,0不翻转,1翻转
                     翻转 echo 1 > active_low
                     不翻转:echo 0 > active_low
device:    控制GPIO引脚的设备文件
direction:    设置输出还是输入模式
                   设置为输入:echo "in"  > direction
                   设置为输出:echo "out" > direction  
edge:        控制中断触发模式,引脚被配置为中断后可以使用poll()函数监听引脚 
                   非中断引脚: echo "none"    > edge
                   上升沿触发: echo "rising"  > edge
                   下降沿触发: echo "falling" > edge
                   边沿触发:   echo "both"    > edge
power:        设备供电方面的相关信息
subsystem:    符号链接,指向父目录
uevent:    内核与udev(自动设备发现程序)之间的通信接口 
value:        输出时,控制高低电平;输入时,获取高低电平
                   高电平:echo 1 > value
                   低电平:echo 0 > value

unexport:用于将导出的GPIO删除掉

gpiochipX:当前芯片中包含的GPIO控制器

base:设备所管理的GPIO初始编号
label:设备信息
ngpio:设备所管理的GPIO总数
power:设备供电方面的相关信息
subsystem:符号链接,指向父目录
uevent:内核与udev(自动设备发现程序)之间的通信接口

二、在程序中使用文件对GPIO进行操作(gpio.c gpio.h)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>

#include "gpio.h"
// #include "../../log/log.h"

static const char *TAG = "gpio";

#define fprintf_error(tag, fmt, arg...)     do{\
                                            sprintf(stderr,"%s: "fmt"\n", tag, ##arg);\
                                        }while(0)

static int gpio_export(int pin)
{
    char path[64] = {0};

    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    if (access(path, F_OK) != GPIO_OK)
    {
        FILE *fp = fopen("/sys/class/gpio/export", "w");
        if (fp == NULL)
        {
            fprintf_error(TAG, "failed to gpio export\n");
            return GPIO_FAIL;
        }
        
        fprintf(fp, "%d", pin);
        fclose(fp);
    }
    return GPIO_OK;
}

int gpio_unexport(int pin)
{
    char path[64] = {0};

    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    if (access(path, F_OK) == GPIO_OK)
    {
        FILE *fp = fopen("/sys/class/gpio/unexport", "w");
        if (fp == NULL)
        {
            fprintf_error(TAG, "failed to gpio unexport\n");
            return GPIO_FAIL;
        }
        
        fprintf(fp, "%d", pin);
        fclose(fp);
    }
    return GPIO_OK;
}

static int gpio_direction(int pin, const char *direction)
{
    char path[64] = {0};

    sprintf(path, "/sys/class/gpio/gpio%d/direction", pin);
    if (access(path, F_OK) != GPIO_OK)
    {
        FILE *fp =  fopen(path, "w");
        if (fp == NULL)
        {
            fprintf_error(TAG, "failed to gpio direction\n");
            return GPIO_FAIL;
        }

        fprintf(fp, "%s", direction);
        fclose(fp);
    }
    return GPIO_OK;
}

int set_gpio_bit(int pin, int level)
{
    char path[64] = {0};

    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    if (access(path, F_OK) == GPIO_OK)
    {
        FILE *fp = fopen(path, "w");
        if (fp == NULL)
        {
            fprintf_error(TAG, "failed to set gpio bit\n");
            return GPIO_FAIL;
        }
        
        fprintf(fp, "%d", level);
        fclose(fp);
    }

    return GPIO_OK;
}

int get_gpio_bit(int pin)
{
    char value = 0;
    char path[64] = {0};

    sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
    if (access(path, F_OK) == GPIO_OK)
    {
        FILE *fp = fopen(path, "r");
        if (fp == NULL)
        {
            fprintf_error(TAG, "failed to get gpio bit (fopen)\n");
            return GPIO_FAIL;
        }
        
        if(fread(&value, sizeof(value), 1, fp) < 0)
        {
            fprintf_error(TAG, "failed to get gpio bit (read)\n");
            fclose(fp);
            return GPIO_FAIL;
        }

        fclose(fp);
    }

    return (atoi(&value));
}

int gpio_output_config(int pin, int level)
{
    int ret = GPIO_OK;

    ret = gpio_export(pin);
    if (ret == GPIO_FAIL)
    {
        return GPIO_FAIL;
    }

    ret = gpio_direction(pin, "out");
    if (ret == GPIO_FAIL)
    {
        return GPIO_FAIL;
    }
    
    return set_gpio_bit(pin, level);
}

int gpio_input_config(const int pin)
{
    int ret = GPIO_OK;

    ret = gpio_export(pin);
    if (ret == GPIO_FAIL)
    {
        return GPIO_FAIL;
    }

    ret = gpio_direction(pin, "in");
    if (ret == GPIO_FAIL)
    {
        return GPIO_FAIL;
    }
    
    return GPIO_OK;
}

#ifndef _GPIO_H_
#define _GPIO_H_

enum gpio
{
    GPIO_OK = 0,
    GPIO_FAIL = -1
};

#define GPIOA_PIN(pin)       (pin)
#define GPIOB_PIN(pin)       (pin + 32)
#define GPIOC_PIN(pin)       (pin + 64)
#define GPIOD_PIN(pin)       (pin + 96)
#define GPIOE_PIN(pin)       (pin + 128)

int get_gpio_bit(int pin);
int set_gpio_bit(int pin, int level);
int gpio_input_config(int pin);
int gpio_output_config(int pin, int level);
#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值