2015-06-13 77 views
4

我正在使用visual basic编写一个程序,并遇到了一个奇怪的问题。我正在通过串口发送字符串到望远镜支架。当我发送check字符串时,作用域可以返回chr(0)或chr(255)。这在python和C++返回chr(255)中工作正常。但是,当我在Visual Basic中运行脚本时,它会返回chr(0)或chr(63)。VB.net将chr(255)返回为chr(63)

下面是两个相同的函数,一个用于python,一个用于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() 

脚本(返回不正确的值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 
+0

根据MSDN字符型保持无符号的16位(2字节)的代码点 – jeffpkamp

回答

6

在.NET SerialPort类有an Encoding associated with it,用于在端口上发送的文本和字节之间进行转换。该文件说明它用于“文本前后传输转换”。用EncodingEncoding转换为string的文本转换为(但这可能是“后传输”的意思)。

无论如何,我敢肯定这就是你的255角色发生的情况。 ReadTo()方法使用Encoding将收到的数据转换为文本以放入string。默认EncodingASCIIEncoding,它只处理0x00 - 0x7f范围内的字符。该范围之外的字节将被编码为'?'字符,恰好具有63的ASCII值。

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

更新:我发现BCL团队的某人发布了一篇博客文章,确认了这一点,并指出了一个未经修改即可传递8位数据的编码对象。瑞安拜因顿称为"SerialPort Encoding" on the Base Class Library (BCL) Blog的一篇文章中写道:2006年5月26日:

SerialPort类使用 SerialPort.Encoding属性指定的字符串和字符数组转换 以字节通过串行端口发送的编码。从串行端口读取时,使用 将编码从 串行端口收到的字节转换为字符串和字符数组。

默认情况下,SerialPort类使用ASCII编码其中所有 字符转换为0-127的值,以一个单一的字节以相同的 值。所以“Hello”被转换为字节数组{72,101,108,108, 111}。但是其他每个字符都将转换为一个字节,其值为 或6333或'?'。这适用于如果串行端口接收到的字节数组{72,101,108,108,111}它 将转换读取以及如此 此为“Hello”,并以大于 值127的任何字节将被转换到该'?'字符。

的ASCII编码工作完全适合大多数串行设备,但 仍有相当,要么与价值观 超过127字节发送一些设备或需要使用值大于127,您 有两个选项发送字节;一个是使用的API,可处理byte[] 并绕过Encoding,或使用正确的编码。然而 找到正确的编码是有点棘手,作为 处理127以上的值将使用这可能 不会连接到串行端口的设备工作的多个字节,多数编码。唯一 编码该转换字节 到字符时所有字符与值0-255转换成与相应的值,反之亦然单个 字节是“西欧(ISO)”编码。使用 下面的代码来使用该编码与SerialPort类:

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

哇,高兴一个检回。感谢您的彻底解答!如果可以的话,我会给你两张票。 – jeffpkamp