Linux下QT使用poll()函数监听gpio的变化

1 篇文章 0 订阅

关于linux的GPIO子系统:https://blog.csdn.net/mirkerson/article/details/8464290

用法总结:

        1. 通过向文件/sys/class/gpio/export 写入io号生成相应io口的节点:

                 echo 204 > /sys/class/gpio/export

                 此时/sys/class/gpio目录下边生成一个gpio204的目录

        2.通过向/sys/class/gpio/gpio204/direction 写入in 或者out 设置io口为输入或者输出:

                echo in > /sys/class/gpio/gpio204/direction

        3.输出模式下通过向/sys/class/gpio/gpio204/value 写入0 或者 1设置io口为低电平或者高电平:

                echo 1 > /sys/class/gpio/gpio204/value

        4.输入模式下通过向/sys/class/gpio/gpio204/edge 写入"none", "rising", "falling","both"设置输入口的模式:

                none表示引脚为输入,不是中断引脚

                rising表示引脚为中断输入,上升沿触发

                falling表示引脚为中断输入,下降沿触发

                both表示引脚为中断输入,边沿触发 

                echo both > /sys/class/gpio/gpio204/edge

        为了使用poll()或者select()监听io口的变化,我们需要先把io口设置为中断模式。对于是both,falling还是rising依赖具体硬件的中断的触发方式。

        关键代码:

void GpioApi::run()
{
    struct pollfd fds[20];
    int i = 0;
    foreach (int fd, mapListenIo.keys())
    {
        fds[i].fd = fd;
        fds[i].events  = POLLPRI;
        i++;
    }
    runFlag = true;

    while(runFlag)
    {
        int ret = poll(fds, i,-1);
        if( ret == -1 )
        {
            printf("[GpioApi]:run: poll failed ! error message:%s\n", strerror(errno));
            break;
        }
        for(int j=0; j<i; j++)
        {
            if( fds[j].revents & POLLPRI)
            {
                int gpio_fd = fds[j].fd;
                ret = lseek(gpio_fd,0,SEEK_SET);
                if( ret == -1 )
                {
                    printf("[GpioApi]:run: lseek failed ! error message:%s\n", strerror(errno));
                    break;
                }
                char buf[2];
                int ret = read(gpio_fd,buf,sizeof(buf));
                if( ret == -1 )
                {
                    printf("[GpioApi]:run: read failed ! error message:%s\n", strerror(errno));
                    break;
                }
                IO_NUM ioNum = mapListenIo.value(gpio_fd);
                emit ioChanged(ioNum, buf[0]-48);
//                qDebug()<<ret<<ioNum<<"ioChanged"<<buf[0];
            }
        }
    }
}

遇到问题:使用poll监听的时候,io口电平发生了变化,但poll事件没有被触发,而使用select也不能正常触发。

解决办法:写入中断触发方式的时候,先写入一次其他触发方式,然后再写入你需要的触发方式,edge文件变化下就可以正常触发了。

封装类GpioApi使用示例:

    GpioApi ioTest = new GpioApi(this);
    ioTest->addOutIO(GpioApi::IO_C_0);
    ioTest->addInIO(GpioApi::IO_G_11);
    ioTest->addInIO(GpioApi::IO_G_10);
    ioTest->addInIO(GpioApi::IO_G_12);
    ioTest->setOutIO(GpioApi::IO_C_0, 1);
    ioTest->start();

封装类GpioApi的完整代码下载:

https://download.csdn.net/download/birdman_1992/11235102

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值