0

私はModbusプロトコルにまったく慣れていません。私のセットアップは、異なるアドレスを持つ 3 つのデバイスで構成されています。それらはすべて RS232 経由で COM1 に接続されています。Modbus Poll を使用して入力データを確認しましたが、正常に動作しています。私が今やりたいことは、vc++ (MFC) アプリケーションで保持レジスタを読み取ることです。シリアル通信には、MSComm クラスを使用します。少しコードを書きましたが、入力がまったく得られません。

現時点での私のコード:

BOOL Crs232test4Dlg::OpenConnection ()
{
    char error [513];

    try
    {
        if (! m_MSComm.GetPortOpen ())
        {
            m_MSComm.SetCommPort (1);
            m_MSComm.SetSettings ("9600,N,8,1");
            m_MSComm.SetInputLen (4);
            // Receive Data as Text
            m_MSComm.SetInputMode (0);
            m_MSComm.SetPortOpen (true);
            m_MSComm.SetCommID (1);
           return m_MSComm.GetPortOpen ();
        }
        AfxMessageBox ("Success!!!!", MB_OK);
        return TRUE;
    }

    catch (CException *e)
    {
        e->GetErrorMessage (error, 512);
        AfxMessageBox (error, MB_OK);
        return FALSE;
    }
}


void Crs232test4Dlg::OnVaisalaComm ()
{
    if (m_MSComm.GetCommEvent () == 2)
    {
        COleVariant in_dat;
        in_dat = m_MSComm.GetInput ();
        Sleep (100);
        CString strInput (in_dat.bstrVal);
        m_Input = m_Input + strInput;
        UpdateData (FALSE);
    }
}

今m_Inputを出したいのですが、ちょっと変わっていません。SetCommID を設定するときに警告 (Property is read-only) も表示されますが、これは重要ではないと思います。

現時点で私は本当に無知なので、誰かが私を案内してもらえますか。

よろしく

EDIT:通信例によると、デバイスをファイルのように扱おうとしました。

m_hCom = CreateFile(m_sComPort, 
        GENERIC_READ | GENERIC_WRITE,
        0, // exclusive access
        NULL, // no security
        OPEN_EXISTING,
        0, // no overlapped I/O
        NULL); // null template
// :(colon) Address=1 Function=3 Starting register= 40001 (To write 400001 or 0?)
Registers to read=4 checksum CR LF
char    strASCII[] = "3A 30 31 30 33 30 30 30 30 30 30 30 34 46 38 0D 0A";

bWriteRC = WriteFile (m_hCom, strASCII, strlen(strASCII), &iBytesWritten, NULL);

memset(sBuffer,0,sizeof(sBuffer));
// Reading output of the M3
bReadRC = ReadFile (m_hCom, &sBuffer, 1, &iBytesRead, NULL);

if (bReadRC && iBytesRead > 0)
    {
        sResult = sBuffer;
    }
    else
    {
        sResult = "Read Failed";
        dwError = GetLastError();

        sprintf(sMsg, "Read length failed: RC=%d Bytes read=%d, "
                "Error=%d ",
                bReadRC, iBytesRead, dwError);
        AfxMessageBox(sMsg);
    } 

read length failed エラーが発生します。strASCII は通常は分離されていません。現在は概要を把握しやすいようになっています。Modbus Pollで通信を確認しました。私の出力は正しいですが、データを取得していないようです。

編集:わかりました。ご助力ありがとうございます。間違ったチェックサムを入れていました。

4

3 に答える 3

1

答えではなく、トラブルショットのガイドです。

  • あなたの親友は次のようになります。

    1)ヌルモデム232female <-> comポートを備えた2台目のコンピューターを備えた232femaleケーブル(またはusb->シリアルコンバーターを備えたラップトップ)...自己ワイヤーでケーブルをワイヤーにはんだ付けするのがおそらく最善の解決策です。

    2)ほとんどのWindowsにプリインストールされているWindowsハイパーターミナルのシンプルで信頼性の高いアプリケーション...モジュールに期待するのと同じビットレート/パリティ/ストップビットパラメータを使用して、comPortモードで起動します。


  • まず、コンプと「チャット」の両方でhtermを実行して、接続とケーブルに問題がないかどうかを確認します。
  • 2番目に、最初のcompで実行してプログラムに問題がないかどうかを確認し、他のcompでhtermを実行します。
  • Modbusモジュールは、マスターがモジュールアドレスに関するクエリを送信する前に何も送信しないことがあるため、プログラムが最初に何かを送信する必要がある場合があります(その調査では、MBUSモジュールの代わりに接続された他のコンプでmodbusPoolをログに記録できます)

... WindowsシグナリングキューとMSCOmmクラスに関してはおそらく問題ありませんが、プロジェクトの開始時に通信障害が発生する可能性のあるすべての理由を排除するために、COMポートをファイルとして脅し、whileループ内で読み取ることをお勧めします。 ...この例の短いバージョン...開始時にシリアルパラメータを設定し、comXという名前のファイルを読み取ります。

上記のリンクにはダウンロード時に優れたcSerialClass実装がありますが、エラーチェックのない簡単な入門書はここpastebinにあります。

于 2013-02-04T17:45:00.740 に答える
1

ここに 2 つの問題があります。

1/ RS232 で 3 つのデバイスを一緒に接続することはできません。RS232 はポイント ツー ポイントです。つまり、2 つのデバイスしか接続できません。

2/ スレーブは、マスターから問い合わせがあった場合にのみデータを送信します。マスターが最初に MODBUS リクエストを送信しない場合、スレーブからの応答は得られません。

PS: m_MSComm.SetCommID() は、ポートが開かれた後ではなく、開かれる前に呼び出す必要があると感じています。

適切なリクエストを作成するために、標準を参照できます。

最初のドキュメントではリクエスト (PDU) の作成方法を説明し、2 つ目のドキュメントではリクエストをシリアル通信に適した「トランスポート」フレーム (ADU) にカプセル化する方法を詳しく説明します。

最も一般的な要求は、「保持レジスタの読み取り」(func. #3) です。スレーブ デバイスのアドレスが 5 で、アドレス 10 から始まる 2 つのレジスタを読み取る場合、要求は次のようになります。('????' は CRC16 の値で、計算が面倒です)。

于 2013-02-05T11:34:23.497 に答える