linux 应用层使用gpio

  • 使用这个代码之前 首先确认开发版的 “/sys/class/” 目录下有gpio这个文件夹,如果没有就需要配置linux内核
  • /**
     * @author emlsyx
     * @email [email protected]
     * @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;
    }

原文地址:https://www.cnblogs.com/emlsyx/p/12332857.html

时间: 2024-10-11 23:04:56

linux 应用层使用gpio的相关文章

Linux应用层直接操作GPIO

Linux应用层直接操作GPIO 在一个老手的指导下,应用层可以直接操作GPIO,具体指设置GPIO的输入输出以及输出电平高或者低.这个大大地提高了灵活性,官方的文档有GPIO Sysfs Interface for Userspace,GPIO Sysfs. 这里我记录一下使用过例子: # RK30_PIN0_PD4 # A0-7 -> 0-7 / B0-7 -> 8-15 / C0-7 -> 16-23 / D0-7 -> 24-31 echo 28 > /sys/cla

Linux 下操作GPIO(两种方法,驱动和mmap)(转载)

目前我所知道的在Linux下操作GPIO有两种方法: 1.编写驱动,这当然要熟悉Linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据ioctl命令进行GPIO寄存器的读写,并把结果回送到应用层.这里提供一点程序片断供大家参考: int  init_module(void){ printk(KERN_ALERT "ioctl load.\r\n"); register_chrdev(254,"ioreg"

Linux中的gpio口使用方法

Linux中的IO使用方法 应该是新版本内核才有的方法.请参考:./Documentation/gpio.txt文件 提供的API:驱动需要包含 #include <linux/gpio.h> 判断一个IO是否合法:int gpio_is_valid(int number); 设置GPIO的方向,如果是输出同时设置电平:/* set as input or output, returning 0 or negative errno */int gpio_direction_input(unsi

linux下操作gpio寄存器的方法

一. 在驱动中: 1. 用的时候映射端口:ioremap; #define GPIO_OFT(x) ((x) - 0x56000000) #define GPFCON (*(volatile unsigned long *)(gpio_va + GPIO_OFT(0x56000050))) gpio_va = ioremap(0x56000000, 0x100000); // 物理地址0x56000000, 映射区分配的大小0x100000字节 这样映射过后,就可以直接操作寄存器了: 配置3引脚

Android应用层操作GPIO

Android应用层操作GPIO的方法: http://my.oschina.net/u/1176566/blog/177554 在使用某个GPIO之前首先的保证此GPIO没有正在被使用,否则是无法操作的: 如NAND模块的NCE3/PC18,此io口正被使用,在导入echo 74 > /sys/class/gpio/export时没问题,但是设置方向是无权操作,如图: 下面是我写的DEMO,单独操作GPIO和控制LED操作的代码.之前想用C部分来操作,然后通过JNI把方法暴露给上层,但是貌似C

浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程【转】

本文转载自:http://www.cnblogs.com/qingchen1984/p/7007631.html 本篇文章主要介绍了"浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程",主要涉及到浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程方面的内容,对于浅析 Linux 中的时间编程和实现原理一—— Linux 应用层的时间编程感兴趣的同学可以参考一下. 简介: 本文试图完整地描述 Linux 系统中 C 语言编程中的时间问

基于Linux应用层的6LOWPAN物联网网关及实现方法

本发明涉及一种基于Linux应用层的6LOWPAN物联网网关及实现方法,所述物联网网关包括开发平台以及无线射频模块,其实现方法是:所述6LOWPAN物联网网关的以太网网口收到访问6LOWPAN无线传感器网络中节点的数据包,Linux应用层将以太网数据包格式转化成6LOWPAN物联网的格式,然后通过无线射频模块发送出去:同理,Linux应用层同时监听无线射频模块,收到6LOWPAN无线传感器网络中的数据包,所述Linux应用层将数据包转化成以太网数据包格式,再通过以太网网口把该数据包发送出去.本发

Linux应用层系统时间写入RTC时钟的方法

Linux内核版本:linux-3.0.35 开发板:i.MX6S MY-IMX6-EK200 系统:Ubuntu12 前言:之前写过一篇关于如何通过应用层程序读取系统时间的blog,今天再写一篇如何写入并保存RTC时钟的blog吧. 一.写入时间 1.预备知识: a.mktime 头文件:#include <time.h> 函数:time_t mktime(struct tm *timeptr) 函数说明:mktime()用来将timeptr所指的tm结构体数据换成从公元1970年1月1日0

Linux下控制GPIO实现LED流水灯(DM8168)

首先加载驱动模块,应用程序通过调用API实现GPIO控制功能. 驱动程序: 1 /* 2 * fileName: led_gpio.c 3 * just for LED GPIO test 4 * GP1_14 -> HDD 5 * GP1_15 -> REC 6 * GP1_27 -> NC 7 * GP1_28 -> IR 8 */ 9 10 #include <linux/device.h> 11 #include <linux/fs.h> 12 #i