使用文件IO操作GPIO引脚之花式点灯(/sys/class/gpio)

实验结果:在设备树未驱动该引脚的情况下,也可以通过此方法控制引脚电平。
在这里插入图片描述

寄存器点灯、函数点灯、驱动点灯都写过,但是还没有接触这种方式,因此想将其记录下来,首先编写gpio相关函数:
头文件就不写了,gpio.c内容如下:

#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>

#define CFG_GPIO_DIR "/sys/class/gpio"
#define CFG_GPIO_SYS_FILE_EXPORTED_TIME_IN_100MS 10

int gpio_is_exported(size_t gpio)
{
	int fd = 0;
	int i;
	char buf[64] = {0};
	size_t len = 0;

	len = snprintf(buf, sizeof(buf), CFG_GPIO_DIR "/gpio%lu/direction", gpio);
	fd = open(buf, O_WRONLY);
	if (fd >= 0) {
		close(fd);
		return 1;
	}

	return 0;
}


int gpio_export(size_t gpio)//112
{
	int fd = 0;
	int i;
	char buf[64] = {0};
	size_t len = 0;

	if( gpio_is_exported(gpio))
	{
		return 0; //No need to re-export
	}

	fd = open(CFG_GPIO_DIR "/export", O_WRONLY);		//export文件用于通知系统需要导出控制的GPIO引脚编号
	if( fd < 0 )
	{
		return -1;
	}

	len = snprintf(buf, sizeof(buf), "%lu", gpio);
	write(fd, buf, len);								//向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间
														//成功后生成/sys/class/gpio/gpio112目录,如果没有出现相应的目录,说明此引脚不可导出
	close(fd);

	/* wait until file is actually available in user space */
	for (i = 0; i < CFG_GPIO_SYS_FILE_EXPORTED_TIME_IN_100MS; i++)
	{
		if( gpio_is_exported(gpio))
		{
			return 0; //GPIO is present in user space
		}
		usleep(100 * 1000);
	}

	return -1;
}

int gpio_unexport(size_t gpio)
{
	int fd = 0;
	char buf[64] = {0};
	size_t len = 0;

	fd = open(CFG_GPIO_DIR "/unexport", O_WRONLY);		//unexport文件用于通知系统取消导出
	if( fd < 0 )
	{
		return -1;
	}

	len = snprintf(buf, sizeof(buf), "%lu", gpio);
	write(fd, buf, len);
	
	close(fd);
	return 0;
}

int gpio_set_direction(size_t gpio, int is_output)
{
	int fd = 0;
	char buf[64] = {0};
	size_t len = 0;

	len = snprintf(buf, sizeof(buf), CFG_GPIO_DIR "/gpio%lu/direction", gpio);	//GPIO的操作接口包括direction和value等,direction控制GPIO方向

	fd = open(buf, O_WRONLY);
	if( fd < 0 )
	{
		return -1;
	}

	if(is_output)
	{
		write(fd, "out", 3);
	}
	else
	{
		write(fd, "in", 2);
	}

	close(fd);
	return 0;
}

int gpio_set_edge(size_t gpio, int rising, int falling)
{
	int fd = 0;
	char buf[64] = {0};
	size_t len = 0;

	len = snprintf(buf, sizeof(buf), CFG_GPIO_DIR "/gpio%lu/edge", gpio);	// none表示引脚为输入,不是中断引脚;rising表示引脚为中断输入,上升沿触发;falling表示引脚为中断输入,下降沿触发;both表示引脚为中断输入,边沿触发;

	fd = open(buf, O_WRONLY);
	if( fd < 0 )
	{
		return -1;
	}

	if(rising && falling)
	{
		write(fd, "both", 4);
	}
	else if(rising)
	{
		write(fd, "rising", 6);
	}
	else
	{
		write(fd, "falling", 7);
	}

	close(fd);
	return 0;
}

int gpio_set_value(size_t gpio, int value)
{
	int fd = 0;
	char buf[64] = {0};
	size_t len = 0;
	
	len = snprintf(buf, sizeof(buf), CFG_GPIO_DIR "/gpio%lu/value", gpio);	//控制gpio的值,value文件中是端口的数值,为1或0

	fd = open(buf, O_WRONLY | O_NONBLOCK);
	if( fd < 0 )
	{
		return -1;
	}
	
	if (value != 0)
		write(fd, "1", 1);
	else
		write(fd, "0", 1);
		
	close(fd);
	return 0;	
}

int gpio_get_value(size_t gpio)
{
	int fd = 0;
	char buf[64] = {0};
	size_t len = 0;
	int ret, val;
	
	len = snprintf(buf, sizeof(buf), CFG_GPIO_DIR "/gpio%lu/value", gpio);

	fd = open(buf, O_RDONLY | O_NONBLOCK);
	if( fd < 0 )
	{
		return -1;
	}
	
	ret = read(fd, buf, 1);
	if (ret < 0)
	{
		close(fd);
		return -1;
	} 
	
	val = buf[0] - '0';	
	close(fd);
	return val;	
}

然后就是点灯文件了:

#include <fcntl.h>     
#include <stdio.h>      
#include <string.h>
#include <stdlib.h>
#include <termio.h>    
#include <sys/time.h>   
#include <unistd.h>     
#include <assert.h>
#include <errno.h>      
#include <sys/mman.h>
#include "gpio.h"

#define GPIO_TO_NUM(bank, gpio) (32 * ((bank) - 1) + (gpio))
#define LED_GPIO_NUM	GPIO_TO_NUM(4, 16)	//112

static int set_led(int is_on)
{
	int ret;

	ret = gpio_set_value(LED_GPIO_NUM, is_on);
	if (ret < 0)
	{
		fprintf(stderr, "gpio : %d set value(%d) failed!!!!\n", LED_GPIO_NUM, is_on);
		return -1;
	}
	else
		return 0;
}

int main(int argc, char *argv[])
{
	int ret;
	int i;

        ret = gpio_export(LED_GPIO_NUM);	//将gpio112从内核空间暴露到用户空间
        if (ret < 0)
        {
                fprintf(stderr, "export gpio : %d failed!!!!\n", LED_GPIO_NUM);
                return -1;
        }

        ret = gpio_set_direction(LED_GPIO_NUM, 1);	//将gpio112设置为输出引脚
        if (ret < 0)
        {
                fprintf(stderr, "gpio : %d set direction(output) failed!!!!\n", LED_GPIO_NUM);
                return -1;
        }

	for (i = 0; i < 10; i++)
	{
		set_led(1);
		sleep(1);
		set_led(0);
		sleep(1);
	}
	
	return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值