0

我正在尝试编写一个程序来将文件上传到 arduino。该程序可以打开一个串行端口并从 arduino 接收数据。当我尝试对处于状态图状态的函数使用回调时,问题就出现了,程序崩溃了。

我以前从未使用过 boost,并决定这是一个尝试的好机会。

我有一个带有基本转换的状态图对象:空闲;-> 开港;-> 端口开放;-> 等待曲线选择确认;-> 选择文件;-> 等待文件接收;-> 比较文件;-> 关闭程序;

还有一个端口关闭状态,但工作正常。

我的主程序只有以下

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);”行 在处理接收数据中。我确定我只是错误地绑定了函数或错误地声明了函数指针对象。

谁能看到我哪里出错了?

感谢您的帮助

4

1 回答 1

0

我已经设法解决了。这与状态图、绑定或函数无关。

调用回调是我的错误。我正在调用“收到完整消息”回调,即使它没有分配回调并且只是 NULL。我通过添加 and 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;
}
于 2013-03-20T13:14:35.927 回答