【问题标题】:timer couldn't work with wiringPiISR (QtQuick application)计时器无法与 WiringPiISR(QtQuick 应用程序)一起使用
【发布时间】:2021-03-30 10:51:13
【问题描述】:

我创建了一个类Capteur_Input,构造函数中的一个选项使用wiringPiISR创建了一个中断

wiringPiISR(m_pin, INT_EDGE_RISING, isrInput);

我的班级还有一个属性m_impulsion,每次发生中断时我都会增加这个值。

这就是我的中断处理程序的样子

void Capteur_Input::isrCallback()
{
    if(m_pin== Pin_vitesse)
{
    increment_impulsion();
        emit digital_inputChanged(m_impulsion);
}
    else
        emit digital_inputChanged(m_value);
}

在我的main.cpp 我创建了这个类的一个实例

static void isrInput_vitesse();

static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);

static void isrInput_vitesse()
{
    vitesse.isrCallback();
}

一切正常,qml 和 C++ 部分。

现在我想计算每秒检测到的脉冲数。但我做不到。

我的班级Capteur_Input也有定时器,我在构造函数中配置了

m_timer =new QTimer (this);
    m_timer->setTimerType(Qt::PreciseTimer);
    connect (m_timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
    m_timer->start(500);

我尝试在 SLOT onTimeout() 中进行测试,但这个 qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse; 从未出现。我不知道为什么可能是因为wiringPiISR 是一个线程并且具有比定时器更高的优先级? 有人可以向我解释一下,如何制作一个计算准确时间的计时器并使中断同时工作? 计时器正在为这个类的其他实例工作,这些实例只是输入,没有中断

void Capteur_Input::onTimeout()
{
    qDebug()<<"time is up"<<m_pin;

    if(m_pin== Pin_vitesse)
    {
        qDebug()<<"m_pin== Pin_vitesse";
    int vitesse;

    vitesse= int (calcul_vitesse/4*2.166);//*0.001/3600;
    qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse;

    emit vitesse_Changed(vitesse);
    qDebug()<<"VITESSEEEEEEEE"<<m_pin <<readPin()<<vitesse;


    }
    else{

        emit digital_inputChanged(readPin());
        qDebug()<<"signal DIGITAL emitted m_pin"<<m_pin <<"value"<<readPin();
    }
}

实际上,onTimeout 插槽适用于这 2 个实例

#define Pin_vitesse 3
#define PinFrein 0
#define PinClignotnat_G 2

Capteur_Input frein(PinFrein,PUD_UP,NO_INTERRUPT);
Capteur_Input clignotant_G(PinClignotnat_G,PUD_DOWN,NO_INTERRUPT);

并且不适用于这个中断static Capteur_Input vitesse(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);

这是我得到的输出

time is up 0
signal DIGITAL emitted 0 1
time is up 2
signal DIGITAL emitted 2 0

time is up 0
signal DIGITAL emitted 0 1

计时器正在为其他实例工作,但它不适用于作为中断的实例

【问题讨论】:

  • 这可能是您在emit vitesse_Changed(vitesse) 上有一个循环,因为如果信号连接到的插槽是DirectConnection,它将运行。因此,如果您在看到它出现之前将 qDebug 调用移至该行
  • 我移动了它,但它没有出现:/
  • 似乎处理定时器事件的事件循环不起作用(主事件循环)。你有类似 app.exec() 的东西吗? Capteur_Input 是基于类定义中的 Q_OBJECT 宏的 QObject?
  • 我编辑了我的帖子,计时器适用于此类的其他实例,并且 Capteur_Input 类继承自 Capteur_ 类,Capteur_ 是一个 QObject 类并包含宏 Q_OBJECT

标签: c++ qt qt5 qtimer wiringpi


【解决方案1】:

Qt 中不支持静态 QObject 实例,如下所述(QObject reentrancy section ):

一般来说,不支持在 QApplication 之前创建 QObject 并且可能导致退出时出现奇怪的崩溃,具体取决于平台。这个 表示也不支持 QObject 的静态实例。一个适当的 结构化的单线程或多线程应用程序应该使 QApplication 是第一个创建的,最后一个销毁的 QObject。

如果您需要在 isr 中断出现时进行回调,则静态指针应该可以工作:

static void isrInput_vitesse();

static Capteur_Input *vitesse = nullptr;

static void isrInput_vitesse()
{
    if(!vitesse) //not initialized yet
         return; 
    
    QMetaObject::invokeMethod( vitesse, "isrCallback", Qt::QueuedConnection ); //or blockingQueue if you need to handle it directly in Qt way.
}

vitesse指针应该在QApplication实例初始化后在main()中初始化。

 int main(int argc, char *argv[])
 {
       QApplication a(argc, argv);

       //.....  your main application body  

       vitesse = new  Capteur_Input(Pin_vitesse,PUD_OFF,INT_EDGE_RISING,isrInput_vitesse);

       //...
 } 

【讨论】:

  • 感谢您的澄清。但是当我试图测试这个告诉 invokeMethod is not a membre of QObjectQVariant::QVariant(void*) 在这个上下文中是私有的时我得到了一个错误 ctx->setContextProperty("vitesse", &vitesse); ^
  • 我的错误,它的意思是QMetaObject而不是QObject。我已经编辑了我的回答者。 isrCallback 应声明为 Qt 插槽函数。
  • 它修复了第一个错误,正如你所说,我将 isrCallback 声明为插槽public slots: void isrCallback(); 但我仍然遇到这两个错误:83:错误:'QVariant::QVariant(void*)' 是私有的在此上下文中 ctx->setContextProperty("vitesse", &vitesse); ^
  • 由于我没有您的代码,因此 setContextProperty() 似乎使用 vitesse 实例指针作为其“vitesse”属性。尝试将其修改为ctx-&gt;setContextProperty("vitesse", vitesse),因为 vitesse 变量现在是指针,而不是类实例。
  • 哦,是的,它是一个指针.. 现在它正在工作:D 谢谢你,A LO。我试图解决这个问题已经有一段时间了!再次感谢您:D
【解决方案2】:

您的timeout 信号可能受到干扰或延迟。

您可以尝试指定 Qt::Connectiontype 以强制 Qt 在发出 timeout 信号后立即对其进行处理。

QObject::connect(m_timer, &QTimer::timeout, this, &Capteur_Input::onTimeOut, Qt::DirectConnection);

这将在timeout 信号发出后立即将其传送到ontimeOut 插槽。

【讨论】:

  • 我刚刚编辑了我的帖子,计时器与该类的其他 2 个非中断实例一起正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多