IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 使用文件IO操作GPIO引脚之花式点灯(/sys/class/gpio) -> 正文阅读

[C++知识库]使用文件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;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:17:37  更:2022-04-22 18:20:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:07:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码