使用libgpiod库中的事件方式监测多个输入事件

 Linux下要同时检测多个GPIO输入的方法有很多,这里我使用libgpiod库中的API实现多个GPIO输入检测,可以达到类似STM32利用外部中断实现输入事件检测的效果,示例代码如下所示:

/* 示例使用的libgpiod库版本为V1.2.1 */
//示例功能是通过libgpiod库捕获GPIO输入事件

#include <stdbool.h>
#include <stdio.h>
#include "gpiod.h"

/* GPIO组路径 */
#define GPIO_CHIP_PATH "/dev/gpiochip0"

/* GPIO组 */
struct gpiod_chip *Test_Gpio_Chip;

/* 电源切换信号输入 */
struct gpiod_line *Gpio_Line_In_Switch;
#define LINE_IN_SWITCH_ID   113  /* PD17 */

/* 脉冲信号输入 */
struct gpiod_line *Gpio_Line_In_PPS;
#define LINE_IN_PPS_ID   115  /* PD19 */

/**
 * 配置GPIO输入
 * 
 * 本函数用于配置GPIO线脚为输入模式,并设置其触发事件。需要指定GPIO芯片、引脚ID号、触发事件以及GPIO线脚的客户端名称。
 * 
 * @param chip 指向GPIO芯片的指针。
 * @param line 指向GPIO线脚的指针的地址,函数执行成功后,会在这里返回配置好的线脚指针。
 * @param line_id 要配置的GPIO线脚的ID。
 * @param edge 触发事件的类型,0表示下降沿触发,1表示上升沿触发,2表示同时触发。
 * @param consumer 指定使用这个GPIO线脚的客户端名称。
 * @return 成功返回0,否则返回错误码。
 * @note 触发事件类型为0表示下降沿触发,1表示上升沿触发,2表示同时触发。
 */
int gpio_input_config(struct gpiod_chip* chip, struct gpiod_line** line, int line_id, int edge, const char* consumer)
{
    struct gpiod_line* tmp_line;
    int ret;
    if (!chip || !consumer || !line)
    {
        return -1;
    }
    tmp_line = gpiod_chip_get_line(chip, line_id);
    if (!tmp_line) 
    {

        return -2;
    }

    if(edge == 0)
    {
        ret = gpiod_line_request_falling_edge_events(tmp_line, consumer);
    }
    else if(edge == 1)
    {
        ret = gpiod_line_request_rising_edge_events(tmp_line, consumer);
    }
    else
    {
        ret = gpiod_line_request_both_edges_events(tmp_line, consumer);
    }

    if (ret < 0) 
    {
        gpiod_line_release(tmp_line);
        return -3;
    }

    *line = tmp_line;
    return ret;
}

/**
 * GPIO清理函数
 * 
 * 本函数用于释放GPIO资源,包括释放GPIO线脚和关闭GPIO芯片。
 */
void gpio_cleanup(void) 
{
    if(Gpio_Line_In_PPS)
    {
        gpiod_line_release(Gpio_Line_In_PPS);
    }
    if(Gpio_Line_In_Switch)
    {
        gpiod_line_release(Gpio_Line_In_Switch);
    }

    if(Gnss_Gpio_Chip)
    {
        gpiod_chip_close(Gnss_Gpio_Chip);
    }
}


/**
 * GPIO初始化函数
 * 
 * 本函数用于初始化GPIO,将GPIO配置为输入。
 * 
 * @return 成功返回0,否则返回-1。
 */
int gpio_init(void) 
{
    int init_sta = 0;
    int ret;
    /* 打开芯片GPIO组 */
    Test_Gpio_Chip = gpiod_chip_open(GPIO_CHIP_PATH);
    if (!Test_Gpio_Chip ) 
    {
        return -1;
    }
    
    /* PPS引脚输入配置 */
    ret = gpio_input_config(Test_Gpio_Chip, &Gpio_Line_In_PPS, LINE_IN_PPS_ID, 0, "pps");
    if (ret == 0) 
    {
        init_sta++;
    }
    else
    {
        printf ("gpio %d input config failed: %d\n", LINE_IN_PPS_ID, ret);
    }

    /* 电源切换信号输入配置 */
    ret = gpio_input_config(Test_Gpio_Chip, &Gpio_Line_In_Switch, LINE_IN_SWITCH_ID, 0, "switch");
    if (ret == 0) 
    {
        init_sta++;
    }
    else
    {
        printf ("gpio %d input config failed: %d\n", LINE_IN_SWITCH_ID, ret);
    }    

    /* 如果配置失败,则关闭芯片并返回错误 */
    if (init_sta == 0)
    {
        if(Test_Gpio_Chip)
        {
            gpiod_chip_close(Test_Gpio_Chip);
        }
        return -1;
    }

    return 0;
}



/**
 * GPIO输入事件处理线程
 * 
 * 本函数用于处理GPIO输入事件,通过调用gpiod_line_event_wait和gpiod_line_event_read函数来获取事件。
 * 
 * @param arg 线程参数,这里没有使用。
 */
void* gpio_input_event_thread(void* arg)
{
    struct gpiod_line_bulk gpiod_line_bulk, event_bulk;
    struct gpiod_line_event event;
    int ret;
    gpiod_line_bulk_add(&gpiod_line_bulk, Gpio_Line_In_PPS);
    gpiod_line_bulk_add(&gpiod_line_bulk, Gpio_Line_In_Switch);    
    while(1)
    {
        /* 无限阻塞,直到输入事件到来 */
        ret = gpiod_line_event_wait_bulk(&gpiod_line_bulk, NULL, &event_bulk);
        if (ret < 0)
        {
            printf("gpiod line event wait error\n");
        }
        else if(ret == 0)
        {
            printf("gpiod line event wait timeout\n");
        }
        else
        {
            /* 解析检测到的事件 */
            for(unsigned int i=0; i<event_bulk.num_lines; i++)
            {
                if(gpiod_line_event_read(event_bulk.lines[i], &event) == 0)
                {
                    printf("line %d event happen\n", gpiod_line_offset(event_bulk.lines[i]));
                    /* 还可以根据event中的内容判断当前检测到的事件是上升沿还是下降沿*/
                }                  
            }
        }
    }
}

int main(void) 
{
     if (gpio_init() != 0) 
     {
         printf("gpio init failed\n");
         return 1;
     }

     gpio_input_event_thread(NULL);
     gpio_cleanup();
     return 0;
}

运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/682523.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端逆向之下载canvas引用的图片

前端逆向之下载canvas引用的图片 一、来源二、解决三、如果在Network这里也找不到呢&#xff1f; 一、来源 当我们用dom检查器的时候无法选中想要扒下来的图片&#xff0c;只能选中canvas&#xff0c;这种时候该怎么办呢&#xff1f; 二、解决 这个时候应该换个脑子&#xf…

SAP PP学习笔记17 - MTS(Make-to-Stock) 按库存生产(策略70)

上几章讲了几种策略&#xff0c;策略10&#xff0c;11&#xff0c;30&#xff0c;40。 SAP PP学习笔记14 - MTS&#xff08;Make-to-Stock) 按库存生产&#xff08;策略10&#xff09;&#xff0c;以及生产计划的概要-CSDN博客 SAP PP学习笔记15 - MTS&#xff08;Make-to-St…

MySQL的联合索引及案例分析

1. 联合索引 关于联合索引的详解参考博客【Mysql-----联合索引和最左匹配】&#xff0c;包含讲解 最左匹配 联合索引失效的情况 不遵循最左匹配原则范围查询右边失效原理like索引失效原理 比较关注的点在于&#xff1a; 对A、B、C三个字段创建一个联合索引&#xff08;A, …

计算机SCI期刊,中科院3区,对国人相当友好

一、期刊名称 Image and Vision Computing 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;4.7 中科院分区&#xff1a;3区 三、期刊征稿范围 图像和视觉计算的主要目标是为图像解释和计算机视觉各个方面的高质量理论和应…

跟着大佬学RE(四)

几个API函数 [ACTF新生赛2020]Universe_final_answer 一个很多方程组的函数&#xff0c;还有一个嗯&#xff0c;对input进行一些操作的函数 嗯&#xff0c;确实方程解出来得到 key 直接运行就可以得到 flag 了&#xff0c;不过还是去分析了一下。 v22 __readfsqword(0x28u);…

2024.6.5

1、react原理学习&#xff0c; hook、fiber 2、瀑布流组件完善 3、代码随想录二刷

6.4分享会

介绍 严格意义上讲&#xff0c;我们在 JavaScript 阶段学习的知识绝大部分属于 ECMAScript 的知识体系&#xff0c;ECMAScript 简称 ES 它提供了一套语言标准规范&#xff0c;如变量、数据类型、表达式、语句、函数等语法规则都是由 ECMAScript 规定的。浏览器将 ECMAScript 大…

opencv快速安装以及各种查看版本命令

安装opencv并查看其版本&#xff0c;直接通过一个可执行文件实现。 #!/bin/bashwget https://codeload.github.com/opencv/opencv/zip/3.4 -O opencv-3.4.zip && unzip opencv-3.4.zip && cd opencv-3.4 && \mkdir build && cd build &&a…

亮数据——全球网络数据一站式平台

在我们日常的项目开发和研究中&#xff0c;数据获取总是一个让人既爱又恨的话题。找到一个既高效又安全的工具&#xff0c;简直就像是在茫茫沙漠中找到绿洲。近期&#xff0c;我测评了&#xff0c;数十家数据获取工具&#xff0c;最后锁定了&#xff0c;亮数据&#xff0c;本篇…

攻防世界—webbaby详解

1.ssrf注入漏洞 ssrf&#xff08;服务端请求伪造&#xff09;是一种安全漏洞&#xff0c;攻击者通过该漏洞向受害服务器发出伪造的请求&#xff0c;从而访问并获取服务器上的资源&#xff0c;常见的ssrf攻击场景包括访问内部网络的服务&#xff0c;执行本地文件系统命令&#…

如何在 Java 中使用 JOptionPane 显示消息对话框

在 Java 开发中&#xff0c;JOptionPane 是一个非常实用的类&#xff0c;可以用来显示各种类型的对话框&#xff0c;例如信息对话框、警告对话框、错误对话框等。今天&#xff0c;我们将深入探讨如何使用 JOptionPane.showMessageDialog 方法来显示消息对话框&#xff0c;以及如…

【Unity | Editor强化工具】资产快速访问工具

经常在Project窗口中翻找资产相对麻烦&#xff0c;Unity自带的Favorite功能又和Project窗口强绑定&#xff0c;且只能在双列视图下使用&#xff0c;故制作了一个可以在独立窗口中列举常用资产的小工具&#xff1a; Unity Asset Quick Access 。 CSDN弄了个Github加速计划&…

天润融通,荣获2024中国AI应用层创新企业

AI技术发展日新月异&#xff0c;可谓“AI一天&#xff0c;人间一年”。 从2023年到2024年&#xff0c;短短一年的时间&#xff0c;大模型技术的发展就已经逐步从追求“技术突破”转向了追求“应用落地”。如何将大模型的技术与企业的生产、运营、销售等场景结合起来&#xff0…

C语言的printf输出问题

看到这段代码的时候&#xff0c;想到这个printf输出的值是多少? 若您想到的答案是1-2&#xff0c;真的是这样吗&#xff1f; #include <stdio.h>int main(int argc, char *argv[]) {int i 1;printf("%d-%d\r\n", i, i);return 0; }先了解一个知识点&#xf…

计算机三级等级考试

计算机等级考试&#xff1a; 一&#xff1a;理论知识考试 100分考60分 1&#xff1a;题库 二&#xff1a;技能考试 100分考60分 1&#xff1a;写文档 项目概述 功能描述 数据库设计 UML 绘 图 用例图 与 包图&#xff08;两个图&#xff09; 2&…

web学习笔记(六十二)

目录 1.键盘事件 2.KeepAlive 3.组件传值 3.1 兄弟组件传值 3.2 组件树传值 3.3 发布订阅者传值 1.键盘事件 keydown表示键盘事件&#xff0c;在不加修饰符的情况下&#xff0c;点击键盘上的任意位置都可以触发键盘事件&#xff0c; <template><div><!--…

【Kubernetes】9-Pod控制器

一、什么是 pod 的控制器 Pod控制器&#xff0c;又称之为工作负载&#xff08;workload&#xff09;&#xff0c;是用于实现管理pod的中间层 确保pod资源符合预期状态&#xff1b;pod的资源故障时会进行重启&#xff1b; 当重启策略无效时&#xff0c;则会重新新建pod的资源 二…

基于51单片机的智能晾衣架设计资料

第三章:硬件单元电路 经过上述分析明确了本次设计的主要目标,为了实现晾衣自身能够完成对外界数据的采集与分析,集成控制环节我们采用了ATMEL公司生产的AT89C52单片机,与市面上的其他嵌入式控制单元相比较在体积与功耗方面都相当出色。此次设计主要突破在于设计合理的控制电…

注册用户超6亿,哈啰发布年度可持续发展暨ESG报告

6月5日&#xff0c;哈啰发布《2023年度可持续发展暨ESG报告》&#xff0c;深入全面地展示2023年哈啰在可持续发展领域的举措和阶段性成果。 报告显示&#xff0c;哈啰始终遵循健康可持续的商业模式&#xff0c;以科技创新推动出行进化&#xff0c;在促进行业发展、环境友好、社…

特征工程及python实现

一、特征构建 概述 从原始数据中构建新的特征&#xff0c;一般需要根据业务分析&#xff0c;生成能更好体现业务特性的新特征&#xff0c;这些新特征要与目标关系紧密&#xff0c;能提升模型表现或更好地解释模型。 方法 时间周期&#xff1a;不同的时间切片长度&#xff0…