【问题标题】:VB.net returns chr(255) as chr(63)VB.net 将 chr(255) 返回为 chr(63)
【发布时间】:2015-06-13 04:57:29
【问题描述】:

我正在用 Visual Basic 编写一个程序,但遇到了一个奇怪的问题。我正在通过串行端口将字符串发送到望远镜支架。当我发送 check 字符串时,范围可以返回 chr(0) 或 chr(255)。这在返回 chr(255) 的 python 和 c++ 中运行良好。但是,当我在 Visual Basic 中运行脚本时,它会返回 chr(0) 或 chr(63)。

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

谁能告诉我为什么 Visual Basic 返回 63 而不是 255?

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

【问题讨论】:

  • 根据 msdn char 类型保存无符号的 16 位(2 字节)代码点

标签: vb.net chr


【解决方案1】:

.NET SerialPort 类具有 an Encoding associated with it,用于在端口上发送的文本和字节之间进行转换。文档说它用于“文本的传输前和传输后转换”。尚不清楚Encoding 是否用于将接收到的字节转换为从ReadTo() 返回的string 的文本(但这可能是“传输后”的意思)。

无论如何,我很确定这就是你的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 的文章中写道:

SerialPort 类使用由 SerialPort.Encoding 属性转换字符串和字符数组 要通过串行端口发送的字节。这种编码也被使用 当从串口读取转换接收到的字节 串口转字符串和字符数组。

默认情况下,SerialPort 类使用 ASCII 编码,它将所有 值为 0-127 的字符转换为具有相同的单个字节 价值。所以 "Hello" 被转换为字节数组 {72, 101, 108, 108, 111}。然而,每个其他字符都被转换为一个字节 值 63 或 '?' 字符。这也适用于阅读 如果串口收到字节数组 {72, 101, 108, 108, 111} 它 将其转换为 "Hello" 和任何值大于的字节 127 将被转换为'?' 字符。

ASCII 编码适用于大多数串行设备,但 仍然有不少设备发送带有值的字节 超过 127 或者您需要发送值大于 127 的字节。您 有两种选择;一种是使用处理byte[] 的API 并绕过Encoding,或使用正确的编码。然而 找到正确的编码有点棘手,因为大多数编码 处理高于 127 的值将使用多个字节,这可能 不适用于连接到串行端口的设备。唯一的 将值 0-255 的所有字符转换为单个字符的编码 转换字节时具有相应值的字节,反之亦然 to characters是“西欧(ISO)”编码。使用 以下代码将此编码与 SerialPort 类一起使用:

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

【讨论】:

  • 哇,很高兴回来查看。感谢您的详尽回答!如果可以的话,我会给你两票。
猜你喜欢
  • 2021-10-12
  • 2015-10-05
  • 2015-01-17
  • 2013-01-23
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 2012-09-18
相关资源
最近更新 更多