EasyARM i.mx287学习笔记——文件IO方式操作GPIO

news/2024/7/4 12:57:23
0 前言
    本文描述如果通过文件IO sysfs方式控制EasyARM GPIO端口。通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入。
    Linux学习可从应用出发,先不纠结Linux驱动编写,先把Linux给玩起来。

    【相关博文】
    【 EasyARM i.mx28学习笔记——安装和使用tftp】
    【 树莓派学习笔记——Shell脚本操作GPIO】
    【  Linux学习笔记——例说makefile 索引博文】

    【代码仓库】
    代码仓库位于bitbucket—— easyarm-gpio-sysfs,请使用Hg克隆或者直接下载zip包。请不要使用任何版本的IE浏览器访问链接,除非你已经知道所使用的IE浏览器符合HTML5标准。推荐使用谷歌或者火狐浏览器访问,若使用国产双核浏览器请切换到极速模式。

1 暴露GPIO操作接口
static int gpio_export(int pin)
{
    char buffer[BUFFER_MAX];
    int len;
    int fd;

    fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd < 0) {
        fprintf(stderr, "Failed to open export for writing!\n");
        return(-1);
    }

    len = snprintf(buffer, BUFFER_MAX, "%d", pin);
    if (write(fd, buffer, len) < 0) {
        fprintf(stderr, "Fail to export gpio!");
        return -1;
    }
   
    close(fd);
    return 0;
}

2 隐藏GPIO操作接口
static int gpio_unexport(int pin)
{
    char buffer[BUFFER_MAX];
    int len;
    int fd;

    fd = open("/sys/class/gpio/unexport", O_WRONLY);
    if (fd < 0) {
        fprintf(stderr, "Failed to open unexport for writing!\n");
        return -1;
    }

    len = snprintf(buffer, BUFFER_MAX, "%d", pin);
    if (write(fd, buffer, len) < 0) {
        fprintf(stderr, "Fail to unexport gpio!");
        return -1;
    }
   
    close(fd);
    return 0;
}

3 配置GPIO方向
static int gpio_direction(int pin, int dir)
{
    static const char dir_str[] = "in\0out";
    char path[DIRECTION_MAX];
    int fd;

    snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);
    fd = open(path, O_WRONLY);
    if (fd < 0) {
        fprintf(stderr, "failed to open gpio direction for writing!\n");
        return -1;
    }

    if (write(fd, &dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3) < 0) {
        fprintf(stderr, "failed to set direction!\n");
        return -1;
    }

    close(fd);
    return 0;
}
    【简单说明】
    【1】dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3 如果输入为常数宏IN, 取dir_str[0]=“in”;若输入常数宏为OUT,取dir_str[0]=“out”。此处巧妙的使用了在数组中的“\0”。

4 控制GPIO输出
static int gpio_write(int pin, int value)
{
    static const char values_str[] = "01";
    char path[DIRECTION_MAX];
    int fd;

    snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);
    fd = open(path, O_WRONLY);
    if (fd < 0) {
        fprintf(stderr, "failed to open gpio value for writing!\n");
        return -1;
    }

    if (write(fd, &values_str[value == LOW ? 0 : 1], 1) < 0) {
        fprintf(stderr, "failed to write value!\n");
        return -1;
    }

    close(fd);
    return 0;
}

5 获得GPIO输入
static int gpio_read(int pin)
{
    char path[DIRECTION_MAX];
    char value_str[3];
    int fd;

    snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);
    fd = open(path, O_RDONLY);
    if (fd < 0) {
        fprintf(stderr, "failed to open gpio value for reading!\n");
        return -1;
    }

    if (read(fd, value_str, 3) < 0) {
        fprintf(stderr, "failed to read value!\n");
        return -1;
    }

    close(fd);
    return (atoi(value_str));
}

6 GPIO翻转操作
    【main函数】
int main(int argc, char *argv[])
{
    int i = 0;
    gpio_export(P24);

    gpio_direction(P24, OUT); // GPIO为输出状态
    for (i = 0; i < 10; i++) {
        printf("LED Blink\n");
        gpio_write(P24, i % 2);
        usleep(500 * 1000);
    }
    gpio_write(P24, 0); // 恢复输出低电平

    gpio_unexport(P24);
    return 0;
}

    【makefile】——此处的代码tab显示可能存在问题,请以代码仓库为主。
# 可执行文件
TARGET=test
# 源文件
SRCS=gpio-sysfs.c

# 目标文件
OBJS=$(SRCS:.c=.o)

# 指令编译器和选项
CROSS=arm-fsl-linux-gnueabi-
CC=$(CROSS)gcc
STRIP=$(CROSS)strip
CFLAGS=-Wall -std=gnu99 -O2

$(TARGET):$(OBJS)
 $(CC) -o $@ $^
 $(STRIP) $@

clean:
 rm -rf $(TARGET) $(OBJS)

# 连续动作,先清除再编译链接,复制到tftpboot中
install:clean $(TARGET)
 @echo 复制到tftpboot目录
 cp $(TARGET) ~/tftpboot
 @echo 复制结束

# 编译规则 $@代表目标文件 $< 代表第一个依赖文件
%.o:%.c
 $(CC) $(CFLAGS) -o $@ -c $<
    
    【交叉编译并复制到tftp根目录】
    make
    再把可执行文件test复制到tftp根目录中,makefile的使用详见【  Linux学习笔记——例说makefile 索引博文】

    【目标板中使用tftp获得可执行文件】
    为了方便操作,在目标板中新建一个名为run-test.sh的脚本并修改执行权限,tftp的使用方法详见【 EasyARM i.mx28学习笔记——安装和使用tftp】
#!/bin/sh                                                                       
tftp -g -r test 192.168.1.106                                                   
chmod a+x test                                                                  
echo "start to run test."                                                       
./test 

    【执行脚本 运行test】
    ./run-test.sh

图1 最终效果
7  总结
【1】文件IO方式操作GPIO,使用到了4个函数open close read write。
【2】向export写入具体的GPIO编号便可把控制接口从内核空间暴露到用户空间。
【3】使用文件IO操作Linux外设的方法具有通用性,树莓派同样可以使用该方法。


http://www.niftyadmin.cn/n/670908.html

相关文章

ps ico插件_常用PS插件合集(1)

小松鼠看到上面蓝色字了么&#xff1f;关注下吧&#xff01;强大的图像处理软件Photoshop有着海量不错的插件今天就向大家介绍几个常用的吧&#xff01;一、磨皮滤镜Imagenomic Portraiture这是个强大的磨皮插件可以设置细节平滑&#xff0c;肤色蒙版&#xff0c;调节清晰度、柔…

反囤地风暴愈演愈烈 查处力度偏轻带来负面效果

[作者]肖宾 [来源]京华时报 [选稿]amy 2007-11-09 09:31:19 字体&#xff1a; [大 中 小] 记者 胡雪柏 摄近日来&#xff0c;全国各地风起云涌地掀起了声势浩大的“土地执法百日行动”&#xff0c;各地纷纷公布了今年以来清查结果。整体看来&#xff0c;尽管清查涉及面积…

噎死人的话

1&#xff1a;工资就像大姨妈&#xff0c;一个月一次&#xff0c;一周左右就没了 2&#xff1a;.我平胸我骄傲&#xff0c;我为国家省布料。 3&#xff1a;人生就像打电话&#xff0c;不是你先挂&#xff0c;就是我先挂。 4&#xff1a;长寿秘诀 ---- 保持呼吸&#xff0c;不要…

树莓派学习笔记——使用文件IO操作GPIO SysFs方式

0 前言本文描述如果通过文件IO sysfs方式控制树莓派 GPIO端口。通过sysfs方式控制GPIO&#xff0c;先访问/sys/class/gpio目录&#xff0c;向export文件写入GPIO编号&#xff0c;使得该GPIO的操作接口从内核空间暴露到用户空间&#xff0c;GPIO的操作接口包括direction和value等…

python seo cms_巧用帝国CMS系统变量提升网站用户体验 完善SEO优化

使用帝国CMS的小伙伴们可能都会在帝国CMS手册里面看到一些自带的系统变量&#xff0c;举个例子&#xff0c;也是最近刚开始使用的一个系统变量即&#xff1a;$GLOBALS[navclassid]这个变量意思是当前栏目id&#xff0c;$GLOBALS[navclassid]--这个变量怎么使用&#xff1f;或者…

考察环境和配套设施 四招教你挑选二手房

http://house.online.sh.cn 2007-11-08 09:05:43 [来源]&#xff1a;21CN 【 浏览字号&#xff1a;大 中 小】 住房成为商品&#xff0c;“二手房”交易将成为整个房地产交易市场中最活跃的部分。目前&#xff0c;国家已开始加大促进二手房交易的力度&#xff0c;因此&#x…

Entity Framework 数据上下文的一些操作

using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace ModelFirst {class Program{static void Main(string[] args){DataModelContainer db new DataModelContainer();#region 关联实体插入数据库//创建一个309 创建学生放到数…

敏捷测试的团队构成

各自分离的功能小组会让敏捷团队更困难。持续的交流至关重要。团队成员需要互相亲密地工作&#xff0c;不管工作是通过虚拟环境还是在同一个地点完成。敏捷测试专家Lisa和Janet分享了敏捷测试团队的组织经验。 独立的质量保证团队 许多组织&#xff0c;不管大还是小&#xff0c…