我正在嘗試編寫一個程序來上傳文件到一個arduino。該程序可以打開串口並從arduino接收數據。當我嘗試在狀態圖狀態中使用回調函數時,問題就出現了,程序崩潰了。使用boost :: bind來調用boost :: Statechart中的函數
我以前從未使用過增強功能,並決定這是一個很好的嘗試的機會。
我有一個狀態圖對象,其基本轉換如下: Idle; - > PortOpening; - > PortOpen; - > WaitForCurveChoiceConfirmation; - > ChooseFile; - > WaitForFileReceive; - > CompareFiles; - > CloseProgram;
Theres a port closing state too too但that works fine。
我的主要程序是唯一如下
int main(int argc, char* argv[]){
if(argc!=4){
cerr<<"Usage: serialPort baudRate file"<<endl;
return 1;
}
try {
myInterface deviceInterface;
stateMachine fsm(deviceInterface);
fsm.initiate();
} catch (std::exception& e) {
cerr<<"Exception: "<<e.what()<<endl;
}
}
我可以打開串口和完美的接收數據。當我嘗試在WaitForCurveChoiceConfirmation狀態中使用回調函數時,問題就出現了。 arduino每隔幾秒發送一條消息,當程序收到完整的消息時,我使用回調。一旦收到消息並且調用回調,我的程序就會崩潰。
的WaitForCurveChoiceConfirmationState是如下
class WaitForCurveChoiceConfirmation: public sc::state< WaitForCurveChoiceConfirmation, Active > {
public:
WaitForCurveChoiceConfirmation(my_context ctx);
typedef boost::mpl::list<
sc::custom_reaction<EvSensorChoiceConfirm> ,
sc::custom_reaction<EvSensorChoiceTimeout>
> reactions;
sc::result react(const EvSensorChoiceConfirm &);
sc::result react(const EvSensorChoiceTimeout &);
void curveChoiceConfirmed(myMessage & msg);
};
WaitForCurveChoiceConfirmation::WaitForCurveChoiceConfirmation(my_context ctx): my_base( ctx){
context<stateMachine>().getInterface().setfullMsgReceivedCallback(boost::bind(&WaitForCurveChoiceConfirmation::curveChoiceConfirmed, this, _1));
}
void WaitForCurveChoiceConfirmation::curveChoiceConfirmed(my1100Message & msg){
std::cout << "curveChoiceConfirmed callback " << std::endl;
if(msg.isExpectingTemperatureCurve()){
post_event(EvSensorChoiceConfirm());
}
}
sc::result WaitForCurveChoiceConfirmation::react(const EvSensorChoiceConfirm &){
std::cout<<"EvSensorChoiceConfirm"<<std::endl;
return transit<ChooseFile>();
}
sc::result WaitForCurveChoiceConfirmation::react(const EvSensorChoiceTimeout &){
return transit<PortClosing>();
}
的MyInterface的類的有關部分是如下
class myInterface: public CallbackAsyncSerial
{
/** Default constructor */
myInterface();
/** Default destructor */
virtual ~myInterface();
void processReceivedData(const char *data, unsigned int len);
void setfullMsgReceivedCallback(boost::function<void(myMessage &msg)>);
void clearfullMsgReceivedCallback();
private:
boost::circular_buffer<char> * incomingMsg;
static const int MESSAGE_DATA_LENGTH = 73; //length of data, not including flags or checksum
static const uint8_t PROTOCOL_OUTGOING_LENGTH = 22; // number of characters in received message
uint8_t receive_buffer[MESSAGE_DATA_LENGTH + 2]; // plus 2 for checksum
char outgoingMsg[PROTOCOL_OUTGOING_LENGTH + 1];
uint8_t statusByte;
uint8_t statusByte2;
uint8_t userByte;
uint8_t userByte2;
uint8_t notificationByte;
uint8_t errorByte;
uint8_t actionByte;
int msgIndex ;
int flagIndex ;
int byteCount;
int checkSum ;
int dispPreambleCount ;
int rcvCalculatedCheckSum ;
char rcvdFlag;
dispMsgState_t dispMsgState ;
static const int FLAG_COUNT = 17;
static const char flags[FLAG_COUNT] ;
boost::function<void(myMessage & msg)> fullMsgReceivedCallback;
};
// this is used as a callback in CallBackAsyncSerial. It takes the data received by serial and processes it
void myInterface::processReceivedData(const char *data, unsigned int len)
{
for (unsigned int i = 0; i < len; i++)
{
incomingMsg->push_back(data[i]);
switch (dispMsgState){
case DISP_PREAMBLE: {//msg start flags
//std::cout << "DISP_PREAMBLE " <<std::endl;
if(incomingMsg->back() == START_FLAG){
dispPreambleCount++;
if (dispPreambleCount == 5){
dispMsgState = DISP_BYTE;
msgIndex = 0;
flagIndex = 0;
rcvCalculatedCheckSum = 5 * START_FLAG;
dispPreambleCount = 0;
rcvdFlag = 0;
}
}
else{
dispPreambleCount = 0; //reset counter if a different character was found
}
incomingMsg->pop_back();
}
break;
case DISP_BYTE:{ //status, user, notification, error bytes
rcvCalculatedCheckSum += incomingMsg->back();
receive_buffer[msgIndex] = incomingMsg->back();
msgIndex++;
incomingMsg->pop_back();
if (msgIndex == 7){
dispMsgState = DISP_INTEGER_FLAG;
}
}
break;
case DISP_INTEGER_FLAG:{ //integer flag
rcvCalculatedCheckSum += incomingMsg->back();
rcvdFlag = incomingMsg->back();
incomingMsg->pop_back();
dispMsgState = DISP_INTEGER;
}
break;
case DISP_INTEGER:{ // integers
rcvCalculatedCheckSum += incomingMsg->back();
if(rcvdFlag == flags[flagIndex]){
receive_buffer[msgIndex] = incomingMsg->back();
}
incomingMsg->pop_back();
msgIndex++;
byteCount++;
if (byteCount >= 2){
if(msgIndex < 21){
dispMsgState = DISP_INTEGER_FLAG;
}
else{
dispMsgState = DISP_FLOAT_FLAG;
}
byteCount = 0;
flagIndex++;
}
}
break;
case DISP_FLOAT_FLAG:{ // float flag
rcvCalculatedCheckSum += incomingMsg->back();
rcvdFlag = incomingMsg->back();
incomingMsg->pop_back();
dispMsgState = DISP_FLOAT;
}
break;
case DISP_FLOAT:{ // floats
rcvCalculatedCheckSum += incomingMsg->back();
if(rcvdFlag == flags[flagIndex]){
receive_buffer[msgIndex] = incomingMsg->back();
}
incomingMsg->pop_back();
msgIndex++;
byteCount++;
if (byteCount >= 4){
if(msgIndex < 49){
dispMsgState = DISP_FLOAT_FLAG;
}
else{
dispMsgState = DISP_STRING_FLAG;
}
byteCount = 0;
flagIndex++;
}
}
break;
case DISP_STRING_FLAG:{ // pressure flag
rcvCalculatedCheckSum += incomingMsg->back();
rcvdFlag = incomingMsg->back();
incomingMsg->pop_back();
dispMsgState = DISP_STRING;
}
break;
case DISP_STRING:{ // pressure string
rcvCalculatedCheckSum += incomingMsg->back();
if(rcvdFlag == flags[flagIndex]){
receive_buffer[msgIndex] = incomingMsg->back();
}
incomingMsg->pop_back();
msgIndex++;
byteCount++;
if (byteCount >= 8){
if(msgIndex < 73){
dispMsgState = DISP_STRING_FLAG;
}
else{
dispMsgState = DISP_CHECKSUM;
}
byteCount = 0;
flagIndex++;
}
}
break;
case DISP_CHECKSUM:{ // rcv checksum
if (byteCount == 0){
receive_buffer[msgIndex ] = incomingMsg->back() ;
byteCount ++;
}
else{
receive_buffer[msgIndex ] = incomingMsg->back();
if (rcvCalculatedCheckSum == ((receive_buffer[msgIndex - 1 ] << 8) | receive_buffer[msgIndex ])) {
std::cout<<"FULL MSG CONFIRMED "<<std::endl;
statusByte = receive_buffer[0];
statusByte2 = receive_buffer[1];
userByte = receive_buffer[2];
userByte2 = receive_buffer[3];
notificationByte = receive_buffer[4];
errorByte = receive_buffer[5];
actionByte = receive_buffer[6];
myMessage * msg = new myMessage();
msg->initialise(statusByte,statusByte2,userByte,userByte2,notificationByte,errorByte,actionByte) ;
std::cout<<"made new msg"<<std::endl;
fullMsgReceivedCallback(*msg); //THIS IS WHERE IT CRASHES
std::cout<<"callback returned"<<std::endl;
delete msg;
std::cout<<"msg deleted"<<std::endl;
/* to convert string to float
#include <sstream>
using namespace std;
string s = "1.60000000000000000000000000000000000e+01";
istringstream os(s);
double d;
os >> d;
cout << d << endl;
*/
}
else{
std::cout<<"FULL MSG NOT CONFIRMED "<<std::endl;
std::cout << std::hex << rcvCalculatedCheckSum <<" " << std::hex<< int((receive_buffer[msgIndex - 1 ]))<<" "<< std::hex << int(receive_buffer[msgIndex ])<<std::endl;
}
dispMsgState = DISP_PREAMBLE;
rcvCalculatedCheckSum = 0;
msgIndex = 0;
byteCount = 0;
}
msgIndex++;
incomingMsg->pop_back();
}
break;
}
}
//incomingMsg->insert(incomingMsg->end(), data, data + len);
//for(boost::circular_buffer<char>::const_iterator i = incomingMsg->begin(); i != incomingMsg->end(); ++i)
// std::cout << *i ;
for(int i = 0; i < MESSAGE_DATA_LENGTH + 1; i++){
//std::cout << std::hex<< (uint8_t)*i << ' ' ;
std::cout << std::hex << receive_buffer[i] << ' ';
}
std::cout <<endl;
}
void myInterface::setfullMsgReceivedCallback(boost::function<void(my0Message & msg)> cb){
fullMsgReceivedCallback = cb;
}
void myInterface::clearfullMsgReceivedCallback(){
fullMsgReceivedCallback = NULL;
}
發生在線路的碰撞 「fullMsgReceivedCallback(* MSG);」在processReceivedData中。我確定我只是不正確地綁定了函數或者錯誤地聲明瞭函數指針對象。
任何人都可以看到我要去哪裏錯了嗎?
感謝您的幫助
如果您已將問題簡化爲10行代碼,那麼您可能會得到幫助。這對你來說更多的工作,但對其他人來說則更少。我也發現,有時候,減少運動本身可以解決問題。只是一個想法。 – Ant 2014-05-15 11:55:49