韦东山嵌入式Linux应用开发实验班-学习笔记(二)——使用文件IO操作硬件(SYSFS方式)

写在前面:本系列文章用于记录个人学习过程中的心得体会,可能存在理解偏差或不到位的情况,欢迎指出,互相交流,共同进步!

1.点灯方式

1.通过编写驱动程序点灯。该方法涉及Linux驱动开发的知识,应该是有一套驱动程序框架,主要通过Linux提供的接口open/read/write调用底层驱动。

2.使用GPIO SYSFS系统手动操作GPIO点灯。SYSFS的概念详见如下文章链接。个人理解SYSFS就是提供了一种可以让用户态直接访问GPIO的方式,而原本是应该由内核来访问的。[Linux 基础] -- sysfs 基本原理与使用方法_进程如何使用sysfs-CSDN博客

2.SYSFS点灯步骤

使用SYSFS点灯前提是:清楚要操作的硬件所对应的gpio编号。这需要结合imx6ull的原理图和芯片手册来查看。

2.1 查看芯片的GPIO控制器组

在开发板上访问 /sys/class/gpio/devices 目录,查看一共有几组GPIO

ls /sys/bus/gpio/devices //查看芯片有多少组gpio控制器

//打印的结果
gpiochip0 gpiochip1 gpiochip2 gpiochip3 gpiochip4 gpiochip5

注:Linux中GPIO控制器组从0开始编号,而原理图中LED连接的GPIO5_3,是从1开始编号的,因此应该对应这里的gpiochip4。

2.2 查看每一组GPIO控制器的基编号

这里可以看出从0开始编号,每组32个gpio,由此可以计算出LED的gpio编号为(5-1)*32+3=131。

ls /sys/class/gpio/gpiochip* -d1 //查看每组gpio控制器的第一个gpio口的编号

//打印结果
/sys/class/gpio/gpiochip0
/sys/class/gpio/gpiochip128
/sys/class/gpio/gpiochip32
/sys/class/gpio/gpiochip504
/sys/class/gpio/gpiochip64
/sys/class/gpio/gpiochip96

注:如何验证131就是板子上的LED对应的gpio编号呢?如下图所示查看第4组GPIO的基地址为20ac000,在芯片手册中查找该地址,发现正对应着GPIO5,再偏移3个即可。

2.3 将GPIO引脚导出,使其可以被用户空间程序控制

echo 131 > /sys/class/gpio/export

2.4 将该引脚方向设为out

这里可以理解为设置为输出模式。

echo out > /sys/class/gpio/gpio131/direction

2.5 输出低电平或高电平

根据原理图可知低电平点亮LED。

echo 0 > /sys/class/gpio/gpio131/value

2.6 取消导出引脚

使用结束后可以手动通知系统将该引脚取消导出。

echo 131 > /sys/class/gpio/unexport

3.通过文件IO编写应用程序

上面第2点是手动在命令行进行点灯操作,本质上还是往指定文件里写数据,因此我们可以通过文件IO操作实现一个应用程序来点灯。

上一节编写了QT框架,本节在main函数中对LED初始化操作,在事件处理函数(按钮点击触发)中对LED进行控制即可。

3.1 LED初始化

这里封装一个函数led_init()其实就是实现了2.3和2.4的内容,将两行echo命令通过文件IO的方式向指定文件写入指定内容,直接附上代码。

void led_init()
{
    /* The following functions are implemented through file I/O
     * echo 131 > /sys/class/gpio/export
     * echo out > /sys/class/gpio/gpio131/direction
     */

    /* 1.open the target file */
    // int fd = open("/sys/class/gpio/export", O_RDWR); //open way not compatible with the file
    int fd = open("/sys/class/gpio/export", O_WRONLY);
    if (fd == -1)
    {
        qDebug()<<"/sys/class/gpio/export open error.";
        perror("fopen error:");
        return;
    }

    /* 2.write comman to the file */
    write(fd, "131\n", 4);

    /* 3.close the file */
    close(fd);
}

注:这里open的方式是只写,是因为在板子上查看/sys/class/gpio/export的属性是--w只写,因此这里打开方式序要统一。

3.2 LED控制函数

这里这里封装一个函数led_control()其实就是实现2.5节的内容,原理同3.1,代码如下。

void led_control(int on)
{
    /* The following functions are implemented through file I/O
     * echo 1 > /sys/class/gpio/gpio131/value
     * echo 0 > /sys/class/gpio/gpio131/value
     */

    /* 1.open the target file */
    static int fd = -1; //only open once and keep opening
    if(fd == -1)
    {
        fd = open("/sys/class/gpio/gpio131/value", O_RDWR);
    }
    if(fd < 0)
    {
        qDebug()<<"/sys/class/gpio/gpio131/value open error.";
        return;
    }

    /* 2.write comman to the file */
    if(on)
    {
        write(fd, "0\n", 2);
        qDebug()<<"LED ON.";
    }
    else
    {
        write(fd, "1\n", 2);
        qDebug()<<"LED OFF.";
    }
}

3.3 事件处理函数

事件处理函数逻辑简单,如下所示。这里只需要注意led_status变量,将其声明为static是因为点击同一个按钮实现开灯/关灯,因此每次点击按钮都会触发该函数,那么需要静态变量来记录当前灯的状态。

/* event handle function */
void MainWindow::on_pushButton_clicked()
{
    /* 2.led control */
    qDebug()<<"LED Clicked.";

    static int led_status = 1; // local static variable only init once

    led_control(led_status);
    led_status = !led_status; //led flag toggle
}

4.实验上的一些注意事项

注:本节主要是写给自己的备忘录,各位可以自行选择阅读。

4.1 QT找不到头文件

解决办法:需要重新设置QT里的sysroot路径。

  1. sysroot代表qt会去该路径寻找头文件,先看qt的设置里sysroot路径写的是什么。
  2. 复制这个路径到ubuntu里,然后随便查找一个程序中包含的头文件,例如types.h。
  3. 找到其真实路径,然后把这个新的路径复制下来设置为sysroot。
  4. 在项目文件中添加路径代码。

4.2 环境变量设置

每次开发板重启上电后都需要重新设置环境变量,目前还没学环境变量的永久设置方法,不敢乱改,每次就麻烦一点吧。

export QT_QPA_GENERIC_PLUGINS=tslib:/dev/input/event1

export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0

export QT_QPA_FONTDIR=/usr/lib/fonts/

5.总结

  1. 学会用SYSFS结合芯片手册查看GPIO引脚和地址对应关系,并通过这种命令实现用户态控制GPIO点灯。
  2. 通过文件IO的方式实现对GPIO硬件的简单控制。
  3. 了解了QT的基本操作,有点类似于MFC应用,前面板放置控件,然后写事件处理函数。
  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值