简介
相信大家在进行嵌入式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); } }