问题描述
我把自己编程到了一个角落,在这个过程中,我意识到我真的缺乏对 C++ 函数指针和虚函数的理解。目标是在树莓派上实现温度控制器。我不会详细介绍其他组件,因为它们不相关。我目前正在研究按钮控制器。这更像是一个架构问题。
- TempCtrl 是调用所有其他类的主类。它还调用 ButtonController::addButton() 来注册按钮,并包含回调。
- ButtonCtrl 读取 gpio 寄存器并循环浏览存储在 Button 类型向量中的注册按钮。
- Button 类应该是一个非常简单的容器,它只有一个指定 gpio 和回调的整数。这就是问题所在。
我以前从未真正做过这样的事情,但我想要一些非常干净的东西。基本上,一旦我完成了按钮控制器,我就希望能够不理会它,除非我添加了功能。为此,我希望在 TempCtrl 函数中定义回调函数。
到目前为止,这还没有奏效。如果可能的话,我确定我的语法是关闭的。我也对实现这一目标的其他方法感兴趣。
代码如下。我只贴了相关的header,以及buttoncontroller.cpp,因为有很多代码。如果需要更多信息,我很乐意发布更多代码,所以请询问:
button.hpp
#ifndef BUTTON_HPP
#define BUTTON_HPP
#include <ctime>
#include <cstdint>
#define HOLDTIME 500 // milliseconds
class TempCtrl;
enum State_E
{
BP_LOW,BP_HIGH
};
class Button
{
public:
Button(
uint8_t _gpio,void(TempCtrl::*)(),void(TempCtrl::*)());
~Button();
void update(State_E newValue);
uint8_t getGpio() const;
private:
void (TempCtrl::*onFallingEdge)();
void (TempCtrl::*onLongHold)();
void (TempCtrl::*onRisingEdge)();
uint8_t gpio;
State_E state;
time_t timeStamp;
};
#endif /* BUTTON_HPP */
buttonprocessor.hpp
#ifndef BUTTONPROCESSOR_HPP
#define BUTTONPROCESSOR_HPP
#include "button.hpp"
#include <cstdint>
#include <vector>
#define GPIO_MAX 53
#define BLOCK_SIZE (4*1024)
#define GPLEV0 13
#define GPLEV1 14
#define SCAN_RATE 100 // milliseconds
class ButtonProcessor
{
public:
ButtonProcessor();
virtual ~ButtonProcessor();
bool init();
bool shutdown();
size_t addButton(Button button);
void startEventLoop(bool &terminate);
private:
int fd;
volatile uint32_t *gpio_base;
std::vector<Button> buttonDb;
};
#endif /* BUTTONPROCESSOR_HPP */
tempctrl.hpp
#ifndef TEMPCTRL_HPP
#define TEMPCTRL_HPP
#include "button.hpp"
#include "lcdscreen.hpp"
#include "buttonprocessor.hpp"
#include <cstdlib>
#include <vector>
#include <string>
#include <time.h>
#include <cstring>
#include <memory>
#define W1_DEV_ROOT "/sys/bus/w1/devices/w1_bus_master1/"
#define W1_SLAVE_COUNT W1_DEV_ROOT "w1_master_slave_count"
#define W1_SLAVES W1_DEV_ROOT "w1_master_slaves"
#define POLL_FREQ 1000
/***********************************************
* A structure for holding a single data point *
* of temperature in degrees celsius,as well *
* as the temp probe ID and a time stamp. *
************************************************/
struct TempStruct
{
time_t ts;
std::string id;
float temp;
};
enum TScale_E
{
CELSIUS,fareNHEIT,KELVIN,RANKINE,MAX_VALUE_TSCALE
};
#define DEFAULT_TEMP_SCALE fareNHEIT
enum InputMode_E
{
SETPOINT,LOAD_PROFILE,PID_TUNE,MAX_VALUE_INPUT_MODE
};
class TempCtrl
{
public:
TempCtrl();
virtual ~TempCtrl();
/***********************************************
* Fetches the current time from the specified *
* temperature controller,and stores the *
* returned value with time stamp and device *
* id,in the tempStruct array.
************************************************/
void getTemp(int);
void setTempScale(TScale_E);
void lcdToggleEnable(int bits);
void wait(size_t seconds);
void printTemp(enum TScale_E);
std::vector<std::string> slavesArr;
std::vector<TempStruct> tempStruct;
TScale_E tempScaleVal = CELSIUS;
int fd;
// These should not be public
void onFallingEdge();
void onLongHold();
void onRisingEdge();
private:
void lcdInit();
uint8_t tempInit(void);
/***********************************************
* exclusive access to atomic safe lcdscreen *
* manipulation. Logic is completely decoupled *
************************************************/
std::unique_ptr<LcdScreen> mLcdScreen;
/***********************************************
* The responsibility of the button processor *
* is to detect edge changes in for specified *
* GPIO's,determine the type of press and call *
* the relavant callback. *
************************************************/
std::unique_ptr<ButtonProcessor> mButtonProcessor;
};
#endif /* TEMPCTRL_HPP */
buttonprocessor.cpp
#include "button.hpp"
Button::Button(
uint8_t _gpio,void(TempCtrl::*_onFallingEdge)(),void(TempCtrl::*_onLongHold)(),void(TempCtrl::*_onRisingEdge)())
: state(BP_LOW),timeStamp(time(NULL)),onFallingEdge(_onFallingEdge),onLongHold(_onLongHold),onRisingEdge(_onRisingEdge)
{
}
Button::~Button()
{
}
void Button::update(State_E newValue)
{
if(
newValue != state &&
state == BP_HIGH) // Rising edge
{
timeStamp = time(NULL);
state = newValue;
// ((Button*)this)->Button::onRisingEdge();
}
else if(
state == BP_HIGH &&
newValue == state &&
((time(NULL) - timeStamp) > HOLDTIME)) // Long Hold
{
timeStamp = time(NULL);
state = newValue;
// ((Button*)this)->Button::onLongHold();
}
else if(
newValue != state &&
state == BP_LOW) // Falling edge
{
timeStamp = time(NULL);
state = newValue;
TempCtrl.(*((Button*)this)->Button::onFallingEdge());
//onFallingEdge();
}
}
uint8_t Button::getGpio() const
{
return gpio;
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)