Linux用户空间操作gpio

1.sysfs的方式

​ 以nvidia NX的核心板为例:

  • 1.1.内核源码GPIO相关

    #define TEGRA194_MAIN_GPIO_PORT_A 0
    #define TEGRA194_MAIN_GPIO_PORT_B 1
    #define TEGRA194_MAIN_GPIO_PORT_C 2
    #define TEGRA194_MAIN_GPIO_PORT_D 3
    #define TEGRA194_MAIN_GPIO_PORT_E 4
    #define TEGRA194_MAIN_GPIO_PORT_F 5
    #define TEGRA194_MAIN_GPIO_PORT_G 6
    #define TEGRA194_MAIN_GPIO_PORT_H 7
    #define TEGRA194_MAIN_GPIO_PORT_I 8
    #define TEGRA194_MAIN_GPIO_PORT_J 9
    #define TEGRA194_MAIN_GPIO_PORT_K 10
    #define TEGRA194_MAIN_GPIO_PORT_L 11
    #define TEGRA194_MAIN_GPIO_PORT_M 12
    #define TEGRA194_MAIN_GPIO_PORT_N 13
    #define TEGRA194_MAIN_GPIO_PORT_O 14
    #define TEGRA194_MAIN_GPIO_PORT_P 15
    #define TEGRA194_MAIN_GPIO_PORT_Q 16
    #define TEGRA194_MAIN_GPIO_PORT_R 17
    #define TEGRA194_MAIN_GPIO_PORT_S 18
    #define TEGRA194_MAIN_GPIO_PORT_T 19
    #define TEGRA194_MAIN_GPIO_PORT_U 20
    #define TEGRA194_MAIN_GPIO_PORT_V 21
    #define TEGRA194_MAIN_GPIO_PORT_W 22
    #define TEGRA194_MAIN_GPIO_PORT_X 23
    #define TEGRA194_MAIN_GPIO_PORT_Y 24
    #define TEGRA194_MAIN_GPIO_PORT_Z 25
    #define TEGRA194_MAIN_GPIO_PORT_FF 26
    #define TEGRA194_MAIN_GPIO_PORT_GG 27
    
    //设备树中使用下面宏定义的,GPIO_BASE编号为288(通过cat /sys/class/gpio/gpiochipX/base得到)
    #define TEGRA194_MAIN_GPIO(port, offset) \
    	((TEGRA194_MAIN_GPIO_PORT_##port * 8) + offset)
    
    //设备树中使用下面宏定义的,GPIO_BASE编号为248(通过cat /sys/class/gpio/gpiochipX/base得到)
    #define TEGRA194_AON_GPIO(port, offset) \
    	((TEGRA194_AON_GPIO_PORT_##port * 8) + offset)
    
  • 1.2.使用sysfs interface 接口控制gpio:

    #确定gpiochipx的base值,X为gpio所在的gpiochip后的编号
    cat /sys/class/gpio/gpiochipX/base
    
    #GPIO11使用的编号为 288+(16*8+6) = 422 ,将422号GPIO导出到/sys/gpio
    echo 422 > /sys/class/gpio/export
    #设置为输出
    echo out > /sys/class/gpio/gpio422/direction
    #输出高电平
    echo 1 > /sys/class/gpio/gpio422/value
    #输出低电平
    echo 0 > /sys/class/gpio/gpio422/value
    #设置为输入
    echo in > /sys/class/gpio/gpio422/direction
    #获取输入值
    cat /sys/class/gpio/gpio22/value
    #取消导出
    echo 422 > /sys/class/gpio/unexport
    

2.用libgpiod库读写IO

​ 内核版本>4.8。

  • 2.1.通过libgpiod提供的gpiosetgpiogetgpiomon可以快速的读写GPIO和检测输入事件

    • 1)安装gpiod命令行工具

      sudo apt install gpiod
      
    • 2)使用gpiod命令行工具

      #查看系统支持多少个gpiochip
      sudo gpiodetect
      #查看指定的chip有多少lines
      sudo gpioinfo 0
      #设置指定的gpiochip的某个line输出低电平,(134 = 16*8+6)和上面使用sysfs使操作的是同一个gpio)
      sudo gpioset -m wait 0 134=0
      #设置指定的gpiochip的某个line输出高电平
      sudo gpioset -m wait 0 134=1
      #设置指定的gpiochip的某个line为输入,并获取其电平状态
      sudo gpioget 0 134
      
  • 2.2.通过调用libgpiod库函数,对gpio进行用户空间的编程

    • 1).下载编译libgpiod库

      #下载地址,需要选择合适的版本
      https://mirrors.edge.kernel.org/pub/software/libs/libgpiod/
      
      #配置安装
      cd libgpiod
      ./configure
      make
      make install
      
      #安装命令行工具(或使用 sudo apt install gpiod )
      cd tools
      make
      sudo make install
      
      #配置动态库
      sudo export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
      sudo ldconfig
      
    • 2).编写测试程序调用libgpiod库

      #include <stdio.h>
      #include <unistd.h>
      #include <string.h>
      #include <gpiod.h>
      
      int main(int argc, char *argv[])
      {
      	struct gpiod_chip *output_chip;
      	struct gpiod_line *output_line;
      	struct gpiod_chip *input_chip;
      	struct gpiod_line *input_line;
      	struct gpiod_line_event event;
      
      	char *chip_out = "gpiochip0";
      	unsigned int offset_out = 134;
      	char *chip_in = "gpiochip0";
      	unsigned int offset_in = 148;
      
      	int line_value = 0;
      
      	/* Configure a GPIO as output */
      	output_chip = gpiod_chip_open_by_name(chip_out);
      	if(!output_chip) {
      		perror("gpiod_chip_open_by_name failed\n");
      		return EXIT_FAILURE;
      	}
      	output_line = gpiod_chip_get_line(output_chip, offset_out);
      	if(!output_line) {
      		perror("gpiod_chip_get_line failed\n");
      		return EXIT_FAILURE;
      	}
      	if(gpiod_line_request_output(output_line, "out1", GPIOD_LINE_ACTIVE_STATE_LOW) < 0){
      		perror("gpiod_line_request_output failed\n");
      		return EXIT_FAILURE;
      	}
      	gpiod_line_set_value(output_line, line_value);
      
      	/* Configure a GPIO as input */
      	input_chip = gpiod_chip_open_by_name(chip_in);
      	if(!input_chip) {
      		perror("gpiod_chip_open_by_name failed\n");
      		return EXIT_FAILURE;
      	}
      	input_line = gpiod_chip_get_line(input_chip, offset_in);
      	if(!input_line) {
      		perror("gpiod_chip_get_line failed\n");
      		return EXIT_FAILURE;
      	}
      	if (gpiod_line_request_rising_edge_events(input_line, "in1") < 0){
      		perror("gpiod_line_request_rising_edge_events failed\n");
      		return EXIT_FAILURE;
      	}
      
      	while (1)
      	{
      		gpiod_line_event_wait(input_line, NULL);
      		if (gpiod_line_event_read(input_line, &event) != 0)
      			continue;
      		/* this should always be a rising event in our example */
      		if (event.event_type != GPIOD_LINE_EVENT_RISING_EDGE)
      			continue;
      
      		if(gpiod_line_get_value(input_line)==1) {
      			line_value = !line_value;
      			gpiod_line_set_value(output_line, line_value);
      			printf("out1_value: %d\n", line_value);
      		}
      		usleep(5000);
      	}
      
      	gpiod_chip_close(output_chip);
          gpiod_chip_close(input_chip);
      
      	return EXIT_SUCCESS;
      }
      
      
    • 3).编译测试程序

      gcc -o gpiotest gpiotest.c -lgpiod -L/usr/local/lib -I/usr/local/include --static
      
    • 4).执行测试程序

      sudo ./gpiotest
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值