You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raspberry Pi wiringPiISR调用C++类成员函数作为中断报错排查

问题分析与解决方案

嗨,我来帮你拆解这个错误的原因,以及怎么解决它~

首先,你遇到的invalid use of void expression错误,核心原因是**wiringPiISR的参数要求和你传入的内容完全不匹配**:

wiringPiISR的第三个参数需要的是一个无参数的void类型函数指针,但你现在写的RPMPouet.FreqCounter(36)是直接调用了这个成员函数,而且这个函数返回void——你相当于把一个void类型的执行结果当成函数指针传进去了,这显然不符合要求,编译器自然会报错。

另外还有一个隐藏问题:类的非静态成员函数默认会隐式携带this指针作为第一个参数,所以它的实际函数签名是void (RPMCounter::*)(int),和wiringPiISR要求的void (*)(void)完全不兼容,哪怕你不传参数,也不能直接把非静态成员函数指针传给它。

接下来给你几个可行的解决方案:

方案1:把成员函数改为静态成员函数(适合不需要访问类非静态成员的场景)

如果你的FreqCounter函数不需要访问RPMCounter类里的非静态成员变量或函数,可以把它改成静态成员函数——静态成员函数没有this指针,签名可以匹配wiringPiISR的要求:

class RPMCounter {
public:
    // 改为静态成员函数
    static void FreqCounter() {
        // 这里可以直接用固定的脉冲数36,或者用静态成员变量存储
        static const int pulsesPerRev = 36;
        // 你的测速逻辑
    }
};

然后调用wiringPiISR时,传入静态函数的指针:

wiringPiISR(你的引脚编号, INT_EDGE_RISING, RPMCounter::FreqCounter);

方案2:用全局函数作为中间层(适合需要访问类成员的场景)

如果FreqCounter必须访问类的非静态成员,那可以通过一个全局中间函数来间接调用成员函数:

  1. 先定义一个全局指针,用来保存你的RPMCounter实例:
// 全局变量,用来保存类实例的指针
RPMCounter* g_rpmCounter = nullptr;
  1. 写一个全局的包装函数,它的签名符合wiringPiISR的要求:
void freqCounterWrapper() {
    // 检查指针有效后,调用成员函数
    if (g_rpmCounter != nullptr) {
        g_rpmCounter->FreqCounter(36); // 传入你的脉冲数
    }
}
  1. 在初始化时把你的实例指针赋值给全局变量:
RPMCounter RPMPouet;
g_rpmCounter = &RPMPouet;
  1. 最后调用wiringPiISR:
wiringPiISR(你的引脚编号, INT_EDGE_RISING, freqCounterWrapper);

额外提醒

中断处理函数里要尽量简短、高效,避免做耗时操作(比如printf、文件IO、复杂计算等),否则会影响树莓派的系统响应和中断触发的准确性。

内容的提问来源于stack exchange,提问作者zepeu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:27:42