VB.net returns chr(255) 作为 chr(63)

VB.net returns chr(255) as chr(63)

我正在用 visual basic 编写程序,运行 遇到了一个奇怪的问题。我正在通过串行端口将字符串发送到 telescope 安装。当我发送 check 字符串时,范围可以 return chr(0) 或 chr(255)。这在 python 和 c++ returning chr(255) 中工作正常。但是,当我 运行 visual basic 中的脚本时,它 returns chr(0) 或 chr(63).

下面是两个相同的函数,一个在 python 中,一个在 Visual Basic 中。

谁能告诉我为什么 visual basic returns 63 而不是 255?

python中的函数(returns 正确值 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 中的脚本(return 错误值 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

.NET SerialPort class 具有 an Encoding associated with it 用于在端口上发送的文本和字节之间进行转换。文档说它用于 "pre- and post-transmission conversion of text"。尚不清楚 Encoding 用于将接收到的字节转换为从 ReadTo() 返回的 string 的文本(但这可能是 "post-transmission" 的意思)。 =37=]

无论如何,我很确定这就是您的 255 角色正在发生的事情。 ReadTo() 方法使用 Encoding 将接收到的数据转换为文本以放入 string。默认的 EncodingASCIIEncoding,它只处理 0x00 - 0x7f 范围内的字符。超出该范围的字节将被编码为 '?' 个字符,其 ASCII 值恰好为 63.

改为使用 ReadByte() 方法从端口读取数据,而不涉及任何文本编码。

更新:我发现 BCL 团队的某个人发的博文证实了这一点,还指出了一个编码对象,该对象将不加修改地传递 8 位数据。 Ryan Byington 于 2006 年 5 月 26 日在一篇名为 "SerialPort Encoding" on the Base Class Library (BCL) Blog 的文章中写道:

The SerialPort class uses the encoding specified by the SerialPort.Encoding property to convert strings and character arrays to bytes to send across the serial port. This encoding also gets used when reading from the serial port to convert bytes received by the serial port to strings and character arrays.

By default the SerialPort class uses ASCII encoding which converts all characters with the value of 0-127 to a single byte with the same value. So "Hello" gets converted to the byte array {72, 101, 108, 108, 111}. However every other character gets converted to a byte with the value of 63 or the '?' character. This applies for reading as well so if the serial port received the byte array {72, 101, 108, 108, 111} it will convert this to "Hello" and any byte with a value greater then 127 will get converted to the '?' character.

The ASCII encoding works perfectly fine for most serial devices but there are still quite a few device that either send bytes with values beyond 127 or you need to send bytes with values greater then 127. You have two options; one would be to use the API’s that deal with byte[] and bypass the Encoding, or to use the correct Encoding. However finding the correct encoding is a bit tricky as most encodings that deal with values above 127 will use multiple bytes which probably won’t work with the device attached to the serial port. The only encoding that converts all characters with a value 0-255 to a single byte with the corresponding value and vice versa when converting bytes to characters is the "Western European (ISO)" encoding. Use the following code to use this Encoding with the SerialPort class:

SerialPort mySerialPort = new SerialPort("COM1");
mySerialPort.Encoding = Encoding.GetEncoding(28591);