简介

    相信大家在进行嵌入式linux设备开发时,会多或少都会涉及到对gpio的控制。以前通用的方式是在内核中增加一个gpio驱动,然后再在上端条用它从而实现对gpio的控制。

    今天我给大家介绍一个简单的方式(不用写代码)用以控制gpio。该方式主要基于内核提供的gpio控制接口文件。也就是通过读写/sys/class/gpio目录下的文件来控制对应的gpio接口。

    使用该方法去控制某个gpio接口主要分为三个步骤:

        1、导出相应的gpio接口。

        2、设置相应gpio接口的方向。(in or out)

        3、设置相应gpio的值。

导出GPIO

    echo $gpio_num > /sys/class/gpio/export

    eg: echo 1 > /sys/class/gpio/export

    执行完以上命令后,如果该gpio接口存在且未被占用则会出现如下目录:/sys/class/gpio/gpio1

设置方向

    gpio的方向分为两类:in和out

    in:表示该gpio用于输入。(如该gpio连接一个按钮)

    out:表示该gpio用于输出。(如该gpio连接一个led灯)

    指定为in模式的命令:echo in > /sys/class/gpio/gpio1/direction

    指定为out模式的命令如下:

        echo out > /sys/class/gpio/gpio1/direction //默认value为0

        echo low > /sys/class/gpio/gpio1/direction //指定方向为out且value为0

        echo high > /sys/class/gpio/gpio1/direction //指定方向为out且value为1

设置高低

    只用当方向为out模式时才能指定gpio接口的电压的高低。这个很容易理解,因为如果是in模式的话,它的电平高低取决于所连接外设的电平高低,我们只能读取它的值,不能更改它的值。

    echo 1 > /sys/class/gpio/gpio1/value //指定gpio1为高电平。

    echo 0 > /sys/class/gpio/gpio1/value //指定gpio1为低电平。

获取当前值

    cat /sys/class/gpio/gpio1/value //用以获取gpio1的当前值。

    cat /sys/kernel/debug/gpio //用以获取系统中所有正在使用的gpio的值。


linux C实现代码

gpio.h

#ifndef GPIO_H_
#define GPIO_H_

int gpio_is_requested(unsigned int gpio);
int gpio_request(unsigned int gpio);
int gpio_free(unsigned int gpio);
int gpio_direction_input(unsigned int gpio);
int gpio_direction_output(unsigned int gpio, int value);
int gpio_get_value(unsigned int gpio);
int gpio_set_value(unsigned int gpio, int value);

#endif

gpio.c

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

#include "gpio.h"

#define GPIO_ROOT "/sys/class/gpio"
#define GPIO_EXPORT    GPIO_ROOT "/export"
#define GPIO_UNEXPORT  GPIO_ROOT "/unexport"
#define GPIO_DIRECTION GPIO_ROOT "/gpio%d/direction"
#define GPIO_ACTIVELOW GPIO_ROOT "/gpio%d/active_low"
#define GPIO_VALUE     GPIO_ROOT "/gpio%d/value"

static int gpio_write_value(const char *pathname, const char *buf, size_t count)
{
    int fd;

    if ((fd = open(pathname, O_WRONLY)) == -1)
        return -1;

    if (write(fd, buf, count) != count) {
        close(fd);
        return -1;
    }

    return close(fd);
}

int gpio_is_requested(unsigned int gpio)
{
    int rv;
    char pathname[255];
    snprintf(pathname, sizeof(pathname), GPIO_VALUE, gpio);

    if ((rv = access(pathname, R_OK)) == -1)
        return -1;

    return (rv == 0);
}

int gpio_request(unsigned int gpio)
{
    char buffer[16];
    snprintf(buffer, sizeof(buffer), "%d\n", gpio);
    return gpio_write_value(GPIO_EXPORT, buffer, strlen(buffer));
}

int gpio_free(unsigned int gpio)
{
    char buffer[16];
    snprintf(buffer, sizeof(buffer), "%d\n", gpio);
    return gpio_write_value(GPIO_UNEXPORT, buffer, strlen(buffer));
}

int gpio_direction_input(unsigned int gpio)
{
    char pathname[255];
    snprintf(pathname, sizeof(pathname), GPIO_DIRECTION, gpio);
    return gpio_write_value(pathname, "in", 3);
}

int gpio_direction_output(unsigned int gpio, int value)
{
    char pathname[255];
    char *val;
    snprintf(pathname, sizeof(pathname), GPIO_DIRECTION, gpio);
    val = value ? "high" : "low";
    return gpio_write_value(pathname, val, strlen(val) + 1);
}

int gpio_get_value(unsigned int gpio)
{
    int fd;
    char pathname[255];
    char buffer;

    snprintf(pathname, sizeof(pathname), GPIO_VALUE, gpio);

    if ((fd = open(pathname, O_RDONLY)) == -1)
        return -1;

    if (read(fd, &buffer, sizeof(buffer)) != sizeof(buffer)) {
        close(fd);
        return -1;
    }

    if (close(fd) == -1)
        return -1;

    return buffer - '0';
}

int gpio_set_value(unsigned int gpio, int value)
{
    char pathname[255];
    snprintf(pathname, sizeof(pathname), GPIO_VALUE, gpio);
    return gpio_write_value(pathname, value ? "1" : "0", 2);
}

test.c

#include <stdio.h>
#include <string.h>

#include "gpio.h"

#define GPIO_MODEM_POWER 11
#define GPIO_MODEM_RESET 2
#define GPIO_SIM_EN      9
#define GPIO_SIM_SEL     8

int main(int argc, char **argv)
{
    if (gpio_is_requested(GPIO_SIM_EN) != 1) {
	gpio_request(GPIO_SIM_EN);
	gpio_direction_output(GPIO_SIM_EN,  1);
    }
    if (gpio_is_requested(GPIO_SIM_SEL) != 1) {
        gpio_request(GPIO_SIM_SEL);
        gpio_direction_output(GPIO_SIM_SEL, 0);
    }
    if (gpio_is_requested(GPIO_MODEM_RESET) != 1) {
        gpio_request(GPIO_MODEM_RESET);
        gpio_direction_output(GPIO_MODEM_RESET, 1);
    }
    if (gpio_is_requested(GPIO_MODEM_POWER) != 1) {
        gpio_request(GPIO_MODEM_POWER);
        gpio_direction_output(GPIO_MODEM_POWER, 1);
    }
}