关于树莓派的介绍这里就不做过多描述了,关于树莓派的更多信息请移步:
树莓派学习笔记——GPIO功能学习
由于 wiringPi 的中断不会在新中断来临时将之前还没有执行完的中断函数给终止掉(最多会存在两个),因此不能使用 delay 的方式做延时消抖,在这里我采用的办法是使用 QTimer
来做异步的延时消抖。
但是如果直接在 wiringPi 的中断处理函数中调用QTimer
的start()
方法,会导致QTimer
的timeout
信号无法在超时之后发出来,而是需要其他的信号驱动,比如另外的QTimer
发出了timeout
信号,这时在 wiringPi 中断中调用start()
方法开启的那个QTimer才会发出timeout
信号。
这大概是由于 wiringPi 的中断处理函数与 QTimer 不在一个线程导致的,所以我们需要借助另外一个信号来开启定时器,即在 wiringPi 的中断函数中不直接开定时器,而是发出一个信号,在这个信号的草函数(与定时器是一个线程了)中开定时器,这样就可以防止出现上面说的问题。
下面是代码(手打,没有编译过,仅仅是一个思路)
rpikey.h
#ifndef RPIKEY_H
#define RPIKEY_H
#include <QObject>
#define KEY_POWER 2
#define IRPiKey RPiKey::getInstance()
class QTimer;
class RPiKey : public QObject
{
Q_OBJECT
explicit RPiKey(QObject *parent = 0);
public:
static RPiKey *getInstance();
void initialize();
friend void INT_KeyPower();
signals:
keyPowerClicked();
keyPowerInterrupted();
private slots:
void onTimeout();
void onKeyPowerInterrupted();
private:
static RPiKey *self;
static QTimer *m_pKeyPowerTimer;
};
void INT_KeyPower();
#endif // RPIKEY_H
rpiKey.cpp
#include "rpikey.h"
#include <QTimer>
#include <QMutex>
#include <wiringPi.h>
void INT_KeyPower()
{
emit IRPiKey->keyPowerInterrupted();
return;
}
RPiKey *RPiKey::self = 0;
RPiKey *RPiKey::getInstance()
{
if (!self)
{
QMutex mutex;
QMutexLocker locker(&mutex);
if (!self)
self= new RPiKey;
}
return self;
}
RPiKey::RPiKey(QObject *parent) :
QObject(parent)
{
m_pKeyPowerTimer = new QTimer;
m_pKeyPowerTimer->setSingleShot(true);
connect(m_pKeyPowerTimer, &QTimer::timeout, \
this, &RPiKey::onTimeout);
connect(this, &RPiKey::keyPowerInterrupted, \
this, &RPiKey::onKeyPowerInterrupted);
}
void RPiKey::initialize()
{
wiringPiSetup();
pinMode(KEY_POWER, INPUT);
pullUpDnControl(KEY_POWER, PUD_UP);
wiringPiISR(KEY_POWRE, INT_EDGE_FALLING, &INT_KeyPower);
return;
}
void RPiKey::onTimerOut()
{
emit keyPowerClicked();
return;
}
void RPiKey::onKeyPowerInterrupted()
{
m_pKeyPowerTimer->start(10);
return;
}