linux 应用层使用gpio

Posted _安静的生活

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux 应用层使用gpio相关的知识,希望对你有一定的参考价值。

  • 使用这个代码之前 首先确认开发版的 “/sys/class/” 目录下有gpio这个文件夹,如果没有就需要配置linux内核
  •  

     

    /**
     * @author emlsyx
     * @email yangx_1118@163.com
     * @create date 2020-02-19 19:11:53
     * @modify date 2020-02-19 19:11:53
     * @desc [description]
     */
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <linux/poll.h>
    
    #define err_out(fmt, ...)                                                      \\
        do                                                                         \\
        {                                                                          \\
            printf(fmt, ##__VA_ARGS__);                                            \\
            printf("<%s>  \\"%s()\\" %d error\\n", __FILE__, __FUNCTION__, __LINE__); \\
        } while (0)
    
    #define open_gpio_file(path, flag, fd)              \\
        do                                              \\
        {                                               \\
            fd = open(path, flag);                      \\
            if (fd < 0)                                 \\
            {                                           \\
                err_out("\\"%s\\" open failed \\n", path); \\
                return (-1);                            \\
            }                                           \\
        } while (0);
    
    /**
     * @brief : gpio 导出
     * @param : pin
     * @retval: 0 成功; -1失败
     */
    static int gpio_export(const int pin)
    {
        int fd, len;
        char buffer[64];
        char path[64];
    
        sprintf(&path[0], "/sys/class/gpio/gpio%d", pin);
        /* 文件不存在时,导出gpio*/
        if (access(path, F_OK) != 0)
        {
            memset(path, 0, 64);
            sprintf(&path[0], "/sys/class/gpio/export");
            open_gpio_file(path, O_WRONLY, fd);
            len = snprintf(buffer, sizeof(buffer), "%d", pin);
    
            if (write(fd, buffer, len) < 0)
            {
                err_out("write failed to export gpio!\\n");
                return -1;
            }
            close(fd);
        }
        return 0;
    }
    /**
     * @brief : gpio 卸载
     * @param : pin
     * @retval: 0 成功; -1失败
     */
    static int gpio_unexport(const int pin)
    {
        int fd, len;
        char buffer[64];
        char path[64];
    
        sprintf(&path[0], "/sys/class/gpio/gpio%d", pin);
        /* 文件存在时,卸载gpio*/
        if (access(path, F_OK) == 0)
        {
            memset(path, 0, 64);
            sprintf(&path[0], "/sys/class/gpio/unexport");
            open_gpio_file(path, O_WRONLY, fd);
            len = snprintf(buffer, sizeof(buffer), "%d", pin);
            if (write(fd, buffer, len) < 0)
            {
                err_out("write failed to unexport gpio!\\n");
                return -1;
            }
            close(fd);
        }
        return 0;
    }
    
    /**
     * @brief : gpio 方向控制
     * @param : dir 方向(in/out)
     * @retval: 0 成功; -1失败
     */
    static int gpio_direction(const int pin, const char *dir)
    {
        int fd;
        char path[64];
        int w_len = ((dir[0] == \'i\') && (dir[1] == \'n\')) ? 2 : 3;
    
        snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/direction", pin);
        open_gpio_file(path, O_WRONLY, fd);
        if (write(fd, dir, w_len) < 0)
        {
            err_out("Failed to set direction!\\n");
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    /**
     * @brief : gpio 写
     * @param : 0 / 1
     * @retval: 0 成功; -1失败
     */
    static int gpio_write(const int pin, const int value)
    {
        int fd;
        char path[64];
        const char *val[] = {"0", "1"};
    
        snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
        open_gpio_file(path, O_WRONLY, fd);
    
        if (write(fd, val[value], 1) < 0)
        {
            err_out("Failed to write value!\\n");
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    /**
     * @brief : gpio 读
     * @param : 读取的引脚值
     * @retval: 返回引脚的值 0 / 1
     */
    static int gpio_read(const int pin)
    {
        int fd;
        char path[64];
        char value_str[3];
    
        snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/value", pin);
        open_gpio_file(path, O_RDONLY, fd);
        if (read(fd, value_str, 3) < 0)
        {
            err_out("Failed to read value!\\n");
            return -1;
        }
    
        close(fd);
        return (atoi(value_str));
    }
    
    /**
     * @brief : gpio 中断控制
     * @param : 0 none 表示引脚为输入,不是中断引脚
     *   @arg : 1 rising 表示引脚为中断输入,上升沿触发
     *   @arg : 2 falling 表示引脚为中断输入,下降沿触发
     *   @arg : 3 both 表示引脚为中断输入,边沿触发
     * @retval:
     */
    static int gpio_edge(const int pin, int edge)
    {
        int fd;
        char path[64];
        const char *dir_str[] = {"none", "rising", "falling", "both"};
    
        if (edge > 3)
        {
            err_out("Failed edge parameter error\\n");
            return -1;
        }
    
        snprintf(path, sizeof(path), "/sys/class/gpio/gpio%d/edge", pin);
        open_gpio_file(path, O_WRONLY, fd);
    
        if (write(fd, dir_str[edge], strlen(dir_str[edge])) < 0)
        {
            err_out("Failed to set edge!\\n");
            return -1;
        }
    
        close(fd);
        return 0;
    }
    
    int main()
    {
        char buff[10], res;
        int led_fd, key_fd;
        struct pollfd fds;
    
        /* 按键led指示灯*/
        gpio_export(55);
        gpio_direction(55, "out");
        gpio_write(55, 0);
    
        /* 按键引脚初始化*/
        gpio_export(70);
        gpio_direction(70, "in");
        gpio_edge(70, 2);
        open_gpio_file("/sys/class/gpio/gpio70/value", O_RDONLY, key_fd);
    
        /* poll 操作的文件符号*/
        fds.fd = key_fd;
    
        /* 经测试io中断产生后,正常会发送POLLPRI 这个中断,循环中必须等待这个事件*/
        fds.events = POLLPRI | POLLERR;
    
        /* 真实发生的事件*/
        fds.revents = 0;
        while (1)
        {
            int ret = poll(&fds, 1, -1);
            if (!ret)
            {
                err_out("poll time out\\n");
            }
            else
            {
                if (fds.revents & POLLPRI)
                {
                    gpio_write(55, gpio_read(55) ? 0 : 1);
    
                    res = lseek(fds.fd, 0, SEEK_SET); /* 读取按键值*/
                    if (res == -1)
                    {
                        printf("lseek failed!\\n");
                        return -1;
                    }
                    res = read(fds.fd, buff, sizeof(buff));
                    if (res == -1)
                    {
                        perror("read failed!\\n");
                        return -1;
                    }
                    printf("fds.revents %d key value %s \\n", fds.revents, buff);
                }
            }
        }
    
        return 0;
    }

     

以上是关于linux 应用层使用gpio的主要内容,如果未能解决你的问题,请参考以下文章

Linux应用层直接操作GPIO

Linux——Linux驱动之设备树中pinctrl和gpio子系统应用实践(如何使用其在设备树中配置GPIO,驱动中如何调用?)

linux使用gpiolib中设置输出读取value始终为0,修改哪里可以读取gpio管教值?

Linux系统GPIO应用编程

Linux——Linux驱动之设备树中pinctrl和gpio子系统应用实践(如何使用其在设备树中配置GPIO,驱动中如何调用?)

linux应用程序中如何操作gpio口