2017-02-25 7 views
1

私は、STM32マイクロコントローラ用のmbedライブラリの上にカスタムの上位層のCANシリアル通信プロトコルを記述しています。シリアル通信スタックでの多態性の使用C++

私はプロトコルで使用される約2ダースのメッセージを定義しました。メッセージのうちのいくつかはセグメント化されている(すなわち、連続して来るかしないかの3つの別々のメッセージ)。私はメッセージIDに基づいて、着信メッセージを処理するための大きなswitch文を持っており、それは次のようになります瞬間

switch (msgID){ 
    case END_CHARGE_REPORT_1_MSG: 
     return processEndChargeReportMsg(msgID); 
    case END_CHARGE_REPORT_2_MSG: 
     return processEndChargeReportMsg(msgID); 
    case END_CHARGE_REPORT_3_MSG: 
     return processEndChargeReportMsg(msgID); 
    case END_CHARGE_REQUEST_MSG: 
     return processEndChargeRequestMsg(msgID); 

    case START_CHARGE_REPORT_1_MSG: 
     return processStartChargeReportMsg(msgID); 
    case START_CHARGE_REPORT_2_MSG: 
     return processStartChargeReportMsg(msgID); 
    case START_CHARGE_REPORT_3_MSG: 
     return processStartChargeReportMsg(msgID); 

は次に、各処理機能でIは、セグメント内であれば、すべてのメッセージをご確認くださいメッセージ・グループを受信し、メッセージ・データを解析/フォーマットし、そのデータをパラメータとして受信メッセージに対応する機能への呼び出しとして使用する。

多形性でこれを行う方法がより良い/クリーナー/高速であるように感じますが、どうやってそれを行うかわからないようです。

私が何かしたい:

class myCANMessages{ 
    virtual process() 
} 

//Derived classes for each type of message group 
class startChargeMessageGroup : public myCANMessages{ 
    CANMessage fullMsgGroup[3]; 
    process(){ 
      load CANMessage into fullMsgGroup 
      if(allMessagesReceived) 
       parse(CANMessage) 
       take_action(decoded data from CANMessage) 
    } 
} 

class endChargeMessageGroup : public myCANMessages{ ///etc...etc... 

をしてからちょうどパラメータとして受け取ったデータを使用して、対応する関数を呼び出す、すべてが受信されたときにそれらを解析し、バッファ内の関連するCANメッセージにインデックスを保存する(受信CANMessagesを処理し続けます)のような構造を持っています:

myCANMessages *polymorphPointer 

while(1){ 
CANMessage = readCANMessage(); 

--> somehow assign this automagically to correct derivedObject type 


polymorphPointer = &derivedObject; 
polymorphPointer->process 


} 

....まだ分かりません。

答えて

1

抽象基本クラスとして「CANメッセージ」を持つことができ、それから各ユニークなCAN識別子に対してこれを継承することができます。しかし、それは私に少し残酷に聞こえる。

通常、私は識別子の後にソートされたルックアップテーブルでこれらの状況を解決します。表の各項目には、サポートされている識別子と関数ポインタが含まれています。 (本質的に、これはとにかく多形が沸騰するのです)。

メッセージを受信すると、テーブルをバイナリ検索して、識別子がサポートされているかどうかを確認します。その場合は、関数を呼び出します。

基本的に、この擬似コード:

CAN_msg msg = can_read(); 
const CAN_msg* supported = binary_search(table, msg.id); 
if(supported) 
{ 
    supported->process(); 
} 

また、サイズ(DLC)とRTRビットが与えられた識別子について予想と一致した場合は常にチェックすることをお勧めします。

+0

私はこのようなやり方が好きです(多形性の代わりにすばやく汚れています)。どのようにルックアップテーブルの宣言/ポピュレートを行うのですか?私はいくつかの種類のtypedefまたは構造体のキー/値ペアを含むと仮定します。ここで、キーは私のmsgID intであり、値はvoid関数ポインタですか? – macdonaldtomw

+0

@macdonaldtomwはい、値のペア構造体です。関数ポインタはおそらくパラメータとしてCANメッセージを取るべきです。 – Lundin