基于libgpiod与C++实现多GPIO线路变化监听及值获取问询
问题描述
在树莓派4上使用C++结合libgpiod库开发时,编写了monitor函数监听GPIO线路变化,但调用event_wait等待事件触发后,无法确定具体哪条线路发生了变化,也无法获取线路的当前值和事件时间戳。同时想确认遍历所有线路的方案是否可行。
初始代码:
void monitor() { const std::string chipname = "gpiochip0"; const std::vector<int> offsets = {4, 5}; // Lines 4 and 5 for testing try { gpiod::chip chip(chipname); gpiod::line_bulk lines; for (int offset : offsets) { auto line = chip.get_line(offset); line.request({"monitor", gpiod::line_request::EVENT_BOTH_EDGES, 0}); lines.append(line); } while (true) { // Infinite waiting on all lines auto signals = lines.event_wait(std::chrono::nanoseconds(0)); // STUCK HERE - How can I find out which line has changed and get its value and timestamp. } } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; } }
尝试的版本1代码:
void monitor() { const std::string chipname = "gpiochip0"; const std::vector<int> offsets = {4, 5}; // Lines 4 and 5 for testing try { gpiod::chip chip(chipname); gpiod::line_bulk lines; for (int offset : offsets) { auto line = chip.get_line(offset); line.request({"monitor", gpiod::line_request::EVENT_BOTH_EDGES, 0}); lines.append(line); } while (true) { // Infinite waiting on all lines auto signals = lines.event_wait(std::chrono::nanoseconds(0)); for (unsigned int i = 0; i < lines.size(); ++i) { if (lines[i].event_wait(std::chrono::seconds(0))) { std::cout << "Change detected on GPIO line " << offsets[i] << std::endl; } } } } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; } }
解决方案
1. 直接定位触发事件的线路
line_bulk::event_wait返回的signals对象已经包含了所有触发事件的GPIO线路,不需要遍历全部线路。直接遍历这个返回的line_bulk就能精准定位发生变化的线路。
2. 获取事件时间戳与线路当前值
对每个触发事件的线路,调用line::event_read()可获取gpiod::line_event对象:
timestamp字段是事件发生的纳秒级时间戳type字段标记事件为上升沿(gpiod::line_event::EVENT_RISING_EDGE)或下降沿(gpiod::line_event::EVENT_FALLING_EDGE)
再调用line::get_value()就能获取线路当前的电平值。
3. 遍历方案的可行性
你尝试的遍历所有线路的方案是可行的,但效率不如直接使用event_wait返回的signals。因为返回的signals已经明确告知触发事件的线路,逐个检查全部线路属于冗余操作。如果监听的线路数量很少,两者差异不大,但推荐用返回的signals处理,代码更简洁高效。
修改后的完整代码
void monitor() { const std::string chipname = "gpiochip0"; const std::vector<int> offsets = {4, 5}; // Lines 4 and 5 for testing try { gpiod::chip chip(chipname); gpiod::line_bulk lines; for (int offset : offsets) { auto line = chip.get_line(offset); line.request({"monitor", gpiod::line_request::EVENT_BOTH_EDGES, 0}); lines.append(line); } while (true) { // 无限等待事件触发 auto signals = lines.event_wait(std::chrono::nanoseconds(0)); // 遍历所有触发事件的线路 for (const auto& line : signals) { // 读取事件信息 auto event = line.event_read(); // 获取当前线路电平值 int value = line.get_value(); // 输出事件详情 std::cout << "GPIO线路 " << line.offset() << " 发生变化: "; if (event.type == gpiod::line_event::EVENT_RISING_EDGE) std::cout << "上升沿"; else std::cout << "下降沿"; std::cout << " | 当前值: " << value << " | 时间戳: " << event.timestamp.count() << "ns" << std::endl; } } } catch (const std::exception &e) { std::cerr << "Error: " << e.what() << std::endl; } }
内容的提问来源于stack exchange,提问作者Mendes
相关产品推荐
相关产品推荐

