使用libgpiod控制树莓派LED灯亮灭

目录

一、libgpiod简介

二、libgpiod相关结构体

①struct gpiod_chip

②struct gpiod_line

三、libgpiod常见的函数解析

四、libgpiod命令

五、C程序代码实现


一、libgpiod简介

官方的对libgpiod库介绍如下:

libgpiod - C library and tools for interacting with the linux GPIO
               character device (gpiod stands for GPIO device)

Since linux 4.8 the GPIO sysfs interface is deprecated. User space should use
the character device instead. This library encapsulates the ioctl calls and
data structures behind a straightforward API.

以上的意思表明:libgpiod是用于与linux GPIO交互的C库和工具

                            字符设备(gpiod代表GPIO设备)
由于linux 4.8,GPIO sysfs接口已被弃用。用户空间应该使用取而代之的是字符设备。

这个库封装了ioctl调用和简单API背后的数据结构。

GPIO(General Purpose Input/Output Port)通用输入输出接口


二、libgpiod相关结构体

①struct gpiod_chip

这个结构体代表支持的gpio芯片的相关信息

struct gpiod_chip {
    struct gpiod_line **lines; //每个 gpio 口 gpiod_line 数组 lines,每一个gpio口对应一个line
    unsigned int num_lines;  //数组的个数

    int fd;    //设备句柄

    char name[32];   //芯片的名称
    char label[32];    //芯片的标签
};

②struct gpiod_line

struct gpiod_line {
    unsigned int offset;  //gpio口的偏移量
    int direction;    //gpio的方向
    int active_state; //活动状态配置
    int output_value;   //最后写入 GPIO 的逻辑值
    __u32 info_flags;
    __u32 req_flags;
    int state;
    struct gpiod_chip *chip;
    struct line_fd_handle *fd_handle;
    char name[32];
    char consumer[32];
};


三、libgpiod常见的函数解析

struct gpiod_chip* gpiod_chip_open_by_name(const(char)*    name)

功能描述:按名称打开 gpiochip
参数解析:name:要打开的 gpiochip 的名称
返回值:成功返回GPIO 芯片句柄,失败则返回 NULL

struct gpiod_line* gpiod_chip_get_line(struct gpiod_chip*    chip,uint    offset)

功能描述:获取给定偏移量处 GPIO句柄:
参数解析:chip:GPIO 芯片句柄
offset:GPIO 偏移量
返回值:成功返回GPIO 句柄,失败则返回 NULL

int gpiod_line_request_output(struct gpiod_line*    line,const(char)*    consumer,int    default_val)

功能描述:保留单线,设置输出方向
参数解析:line:GPIO 句柄
consumer:使用者的名称
default_val:初始值
返回值:成功返回0,失败则返回-1

int gpiod_line_set_value(struct gpiod_line*    line,int    value)

功能描述:设置单个 GPIO 值
参数解析:line:GPIO 句柄
value:设定的值
返回值:成功返回0,失败则返回-1

void gpiod_chip_close(struct gpiod_chip*    chip)

功能描述:关闭 GPIO 芯片句柄并释放所有分配的资源
参数解析:chip: GPIO 芯片句柄

void gpiod_line_release(struct gpiod_line*    line)

功能描述:释放先前保留的line
参数解析:line:GPIO 句柄‎


四、libgpiod命令

注意:以下命令需要sudo权限

gpiodetect:列举所有的gpio芯片以及它们名字,标签和io数目
gpioinfo:列举所有gpio芯片以及它们的名字,制造商,方向,激活状态,附加标志等
gpioget<gpiochip_name + OFFSET>:获取特定gpio引脚的当前值
active-high是高电平 值为1 active-low是低电平 值为0
gpioset <gpiochip_name + gpio_line_number>:设置特定的当前值
gpiofind <gpio line number?>:获取gpiochip的name和offset
eg:gpiofind GPIO26  是加上line的名字
gpiomon <gpio line number + event ?>:监视特定io上的特定事件


五、C程序代码实现

注意运行此程序需要sudo权限。 


nbiot@Raspberrypi4B:~/lyt $ sudo ./led -c "green" -s "on"

#include <gpiod.h>
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>

#define CHIPNAME    "gpiochip0"
#define CUSTOMER    "customer"

void print_usage(char *progname);
int control_led(struct gpiod_line *line, int value);

int main(int argc, char **argv)
{
	int                     ret = -1;
	int           		ch = -1;
	struct gpiod_chip      *chip = NULL;
	struct gpiod_line      *line26 = NULL;
	struct gpiod_line      *line19 = NULL;
	struct gpiod_line      *line13 = NULL;
	char                   *color = NULL;
	char                   *state = NULL;   
	char                   *progname = NULL;
	unsigned int            offset26 = 26;
	unsigned int            offset19 = 19;
	unsigned int            offset13 = 13;

	struct option    opts[] = {
		{"color", required_argument, NULL, 'c'},
		{"state", required_argument, NULL, 's'},
		{"help", no_argument, NULL, 'h'},
		{0, 0, 0, 0}
	};

	progname = basename(argv[0]);

	while( (ch = getopt_long(argc, argv, "c:s:h", opts, NULL)) != -1 )
	{
		switch(ch)
		{
			case 'c':
				color = optarg;
				break;
				
			case 's':
				state = optarg;
				break;
				
			case 'h':
				print_usage(progname);
				break;
				
			default:
				break;
		}		
	} 
	
	if( !color || !state )
	{
		print_usage(progname);
		return -1;
	}
	
	chip = gpiod_chip_open_by_name(CHIPNAME);
	if( chip == NULL )
	{
		printf("open the gpiochip failure: %s\n", strerror(errno));
		return -2;
	}
	
	line26 = gpiod_chip_get_line(chip, offset26);   //green
	if( line26 == NULL )
	{
		printf("get the line26 failure: %s\n", strerror(errno));
		gpiod_chip_close(chip);
		return -3;
	}
		
	line19 = gpiod_chip_get_line(chip, offset19);    //red
	if( line19 == NULL )
	{
		printf("get the line26 failure: %s\n", strerror(errno));
		gpiod_line_release(line26);
		gpiod_chip_close(chip);
		return -4;
	}
	
	line13 = gpiod_chip_get_line(chip, offset13);    //blue
	if( line13 == NULL )
	{
		printf("get the line26 failure: %s\n", strerror(errno));
		gpiod_line_release(line26);
		gpiod_line_release(line19);
		gpiod_chip_close(chip);
		return -5;
	}
	
	ret = gpiod_line_request_output(line26, CUSTOMER, 0);
	if( ret == -1 )
	{
		printf("request line26 as output failure: %s\n", strerror(errno));
		goto cleanup;
	}
	
	ret = gpiod_line_request_output(line19, CUSTOMER, 0);
	if( ret == -1 )
	{
		printf("request line19 as output failure: %s\n", strerror(errno));
		goto cleanup;
	}

	ret = gpiod_line_request_output(line13, CUSTOMER, 0);
	if( ret == -1 )
	{
		printf("request line13 as output failure: %s\n", strerror(errno));
		goto cleanup;
	}
	
	if( strcmp(color, "green") == 0 )
	{
		if( strcmp(state, "on") == 0 )
		{
			ret = control_led(line26, 1);
			if( ret < 0 )
			{
				printf("turn on the green led failure.\n");
				goto cleanup;
			}
			printf("turn on the green led successfully.\n");
		}
		else if( strcmp(state, "off") == 0 )
		{
			ret = control_led(line26, 0);
			if( ret < 0 )
			{
				printf("turn off the green led failure.\n");
				goto cleanup;
			}
			printf("turn off the green led successfully.\n");			
		}
	}
		
	if( strcmp(color, "red") == 0 )
	{
		if( strcmp(state, "on") == 0 )
		{
			ret = control_led(line19, 1);
			if( ret < 0 )
			{
				printf("turn on the red led failure.\n");
				goto cleanup;
			}
			printf("turn on the red led successfully.\n");
		}
		else if( strcmp(state, "off") == 0 )
		{
			ret = control_led(line19, 0);
			if( ret < 0 )
			{
				printf("turn off the red led failure.\n");
				goto cleanup;
			}
			printf("turn off the red led successfully.\n");			
		}
	}
	
	if( strcmp(color, "blue") == 0 )
	{
		if( strcmp(state, "on") == 0 )
		{
			ret = control_led(line13, 1);
			if( ret < 0 )
			{
				printf("turn on the blue led failure.\n");
				goto cleanup;
			}
			printf("turn on the blue led successfully.\n");
		}
		else if( strcmp(state, "off") == 0 )
		{
			ret = control_led(line13, 0);
			if( ret < 0 )
			{
				printf("turn off the blue led failure.\n");
				goto cleanup;
			}
			printf("turn off the blue led successfully.\n");			
		}
	}
	
cleanup:
	gpiod_line_release(line26);
	gpiod_line_release(line19);
	gpiod_line_release(line19);
	gpiod_chip_close(chip);
	
	return 0;
}

void print_usage(char *progname)
{
	printf("%s usage\n", progname);
	printf("-c(--color) specify led color(red|green|blue).\n");
	printf("-s(--state) specify led state(on|off).\n");
	printf("-h(--help) print helpful information.\n");
	printf("input example: ./led -c \"red\" -s \"on\".\n");
}

int control_led(struct gpiod_line *line, int value)
{
	int    ret = -1;
	
	ret = gpiod_line_set_value(line, value);
	if( ret == -1 )
	{
		printf("set line value failure: %s\n", strerror(errno));
		return -1;
	}
	
	return 0;
}

结果如下:

PS:上面代码只能用于控制单个灯的亮灭,如需要控制两个灯亮,三个灯亮,以下附上源代码(此源码的项目是基于MQTT控制树莓派三色LED灯亮灭):

https://gitee.com/Lyttt_Iot/mqtt_led/blob/master/led.c

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值