4

Visual Basic でプログラムを作成していて、奇妙な問題に遭遇しました。シリアルポート経由で文字列を望遠鏡マウントに送信しています。文字列を送信するcheckと、スコープは chr(0) または chr(255) を返すことができます。これは、chr(255) を返す Python および C++ で正常に機能します。ただし、Visual Basic でスクリプトを実行すると、chr(0) または chr(63) が返されます。

以下は、Python と Visual Basic の 2 つの同一の関数です。

Visual Basic が 255 ではなく 63 を返す理由を誰か教えてもらえますか?

Python の関数 (正しい値 0 と 255 を返します):

global d, check
d=chr(80)+chr(4)+chr(16)+chr(2)+chr(1)+chr(112)+chr(252)+chr(0)
check=chr(80) + chr(1) + chr(16) + chr(19) + chr(0) + chr(0) + chr(0)+chr(1)


def test():
    ser.write(d)
    time.sleep(.1)
    print ser.readline()
    ser.write(check)
    time.sleep(.1)
    out=ser.readline()[0]
    print "out=",ord(out)
    while out == chr(0):
            print "out = ", ord(out)
            ser.write(check)
        time.sleep(.1)
            out=ser.readline()[0]
        print "out=",ord(out)
    print "out is now", ord(out)
    ser.readline()

Visual Basic のスクリプト (正しくない値 0 と 63 を返します)

Public Sub test()
    Dim out As Char
    Dim d As String = Chr(80) + Chr(4) + Chr(16) + Chr(2) + Chr(1) + Chr(112) + Chr(252) + Chr(0)
    Dim check As String = Chr(80) + Chr(1) + Chr(16) + Chr(19) + Chr(0) + Chr(0) + Chr(0) + Chr(1)
    port.Write(d)
    Threading.Thread.Sleep(100)
    Console.Write(port.ReadTo("#"))
    port.Write(check)
    Threading.Thread.Sleep(100)
    out = port.ReadTo("#")
    Console.Write(vbNewLine & "out=" & out)
    While out = Chr(0)
        Console.Write("out = " & Convert.ToInt16(out))
        port.Write(check)
        Threading.Thread.Sleep(0.1)
        out = port.ReadTo("#")
        Console.Write("out=" & Convert.ToInt16(out))
    End While
    Console.Write("out is now" & Convert.ToInt16(out))
    port.ReadLine()


End Sub
4

1 に答える 1

9

.NETSerialPortクラスにはEncodingポートで送信されるテキストとバイト間の変換に使用される が関連付けられています。ドキュメントには、「テキストの送信前および送信後の変換」に使用されると書かれています。受信したバイトを返された fromtEncodingのテキストに変換するために が使用されることは明確ではありません (しかし、それは「送信後」が意味するものかもしれません)。stringReadTo()

255いずれにせよ、それがあなたのキャラクターに起こっていることだと確信しています. このReadTo()メソッドは、を使用しEncodingて、受信したデータをテキストに変換し、 に入れますstring。デフォルトEncodingASCIIEncodingで、範囲内の文字のみを処理します0x00- 0x7f。その範囲外のバイトは文字にエンコードされ'?'、たまたま ASCII 値が63.

代わりにメソッドを使用して、ReadByte()テキスト エンコーディングを使用せずにポートからデータを読み取ります。

更新: これを確認し、8 ビット データを変更せずに渡すエンコーディング オブジェクトを指摘している BCL チームの誰かからのブログ投稿を見つけました。Ryan Byington は、 2006 年 5 月 26 日の Base Class Library (BCL) ブログの「SerialPort Encoding」という記事に次のように書いています。

このSerialPortクラスは、プロパティで指定されたエンコーディングを使用して、 SerialPort.Encoding文字列と文字配列をバイトに変換し、シリアル ポート経由で送信します。このエンコードは、シリアル ポートから読み取るときにも使用され、シリアル ポートが受信したバイトを文字列や文字配列に変換します。

デフォルトでは、SerialPortクラスは ASCII エンコーディングを使用し、値が 0 ~ 127 のすべての文字を同じ値の 1 バイトに変換します。したがって、「Hello」はバイト配列 {72, 101, 108, 108, 111} に変換されます。ただし、他のすべての文字は、値が 63 または'?'文字のバイトに変換されます。これは読み取りにも適用されるため、シリアル ポートがバイト配列 {72, 101, 108, 108, 111} を受信した場合、これは「Hello」に変換され、127 より大きい値を持つバイトは'?'文字に変換されます。

ASCII エンコーディングはほとんどのシリアル デバイスで問題なく機能しますが、127 を超える値のバイトを送信するか、127 を超える値のバイトを送信する必要があるデバイスがまだかなりあります。2 つのオプションがあります。byte[] 1 つは、処理してバイパスするAPI を使用することです。Encoding、または正しいエンコーディングを使用します。ただし、127 を超える値を処理するほとんどのエンコーディングは複数のバイトを使用するため、シリアル ポートに接続されたデバイスでは機能しない可能性があるため、正しいエンコーディングを見つけるのは少し注意が必要です。バイトを文字に変換する際に、値が 0 ~ 255 のすべての文字を対応する値を持つ 1 バイトに、またはその逆に変換する唯一のエンコーディングは、「西ヨーロッパ (ISO)」エンコーディングです。次のコードを使用して、この Encoding を SerialPort クラスで使用します。

SerialPort mySerialPort = new SerialPort("COM1");
mySerialPort.Encoding = Encoding.GetEncoding(28591);
于 2015-06-13T05:23:23.137 に答える