2013-03-12 66 views
0

我正在嘗試編寫一個程序來上傳文件到一個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中。我確定我只是不正確地綁定了函數或者錯誤地聲明瞭函數指針對象。

任何人都可以看到我要去哪裏錯了嗎?

感謝您的幫助

回答

0

我已經設法解決它。這與狀態圖,綁定或功能無關。

這是我調用回調的錯誤。我正在調用「完整消息收到」回調,即使它沒有分配給它的回調並且只是NULL。我通過添加if子句來解決這個問題:

if (fullMsgReceivedCallback!= NULL){ 
    Message * msg = Message ; 
    std::cout<<"made new msg"<<std::endl; 
    msg->initialise(statusByte,statusByte2,userByte,userByte2,notificationByte,errorByte,actionByte); 
    std::cout<<" msg initialised"<<std::endl; 
    fullMsgReceivedCallback(*msg); 
    delete msg; 
    std::cout<<"msg deleted"<<std::endl; 
} 
+0

如果您已將問題簡化爲10行代碼,那麼您可能會得到幫助。這對你來說更多的工作,但對其他人來說則更少。我也發現,有時候,減少運動本身可以解決問題。只是一個想法。 – Ant 2014-05-15 11:55:49

相關問題