.net 字节128-255的C#字符串表示法

.net 字节128-255的C#字符串表示法,.net,serial-port,.net,Serial Port,我正在重新构建/改进以前开发的C#/.NET项目。 串行通讯器无法将字节128-255转换为专用字符串。我尝试根据这个项目的工作版本中看到的字符应用Unicode编码。应用编码后,将抛出“Message failed to send exception(消息发送失败异常)”。对于任何关于进一步解决/探索这个问题的建议,我们都将不胜感激。 谢谢 公共虚拟字符串写入数据(字符串s,int-expectedResponseLength) { 锁(messageLock) { resetEvent.Re

我正在重新构建/改进以前开发的C#/.NET项目。 串行通讯器无法将字节128-255转换为专用字符串。我尝试根据这个项目的工作版本中看到的字符应用Unicode编码。应用编码后,将抛出“Message failed to send exception(消息发送失败异常)”。对于任何关于进一步解决/探索这个问题的建议,我们都将不胜感激。 谢谢

公共虚拟字符串写入数据(字符串s,int-expectedResponseLength)
{
锁(messageLock)
{
resetEvent.Reset();
}
message=string.Format(“WriteData:{0}\r\n消息类型={1}\r\n”,s,MessageType.Outgoing);
expectedLength=expectedResponseLength;
如果(!comPort.IsOpen)
comPort.Open();
字节[]bs=新字节[s.Length];
对于(int i=0;i=expectedLength)
{
resetEvent.Set();
}
}
}

首先,您需要知道其他设备(通过串行端口与您通信的设备)需要什么代码页。理论上它可能是UTF-8(Unicode),但对于较旧的设备,它很可能是一些单字节代码页。例如,西欧Windows代码页可能是Windows-1252。因此,根据其他设备的不同,您可能需要更改
comPort.Encoding=new unicodeincoding()OpenPort
中的code>

comPort.Encoding = new Encoding.GetEncoding(1252);
然后,由于您似乎只使用字符串(即通信协议中没有二进制数据)进行交换,请使用
SerialPort.Write(String)
重载,而不是
SerialPort.Write(Byte[],Int32,Int32)
。如果您正确设置了
编码
属性,前者将负责代码页转换。这意味着您需要删除所有
bs
数组内容,只需调用

comPort.Write(s);
在您的
WriteData
方法中

顺便说一下,如果输入字符串中可能出现非ASCII字符,
bs
填充代码是不正确的。您最好使用
Encoding.GetBytes
来获得它:
byte[]bs=Encoding.Unicode.GetBytes(s)

SerialPort\u DataReceived
中,方法
ReadExisting()
将响应读取为
字符串
,可以随时使用(同样,前提是您正确设置了
编码
属性)。因此无需使用
GetBytes
/
GetString
重新转换,只需设置
响应

response += comPort.ReadExisting();
您还需要修复代码中的同步。您必须使用
lock…
访问
response
变量,因为它是从两个线程进行读写访问的。我还试图确保
WriteData
没有被并发调用(在下面的示例中没有实现)

因此,我建议重写串行端口的读写方法,如下所示:

public virtual string WriteData(string s, int expectedResponseLength)
{
    resetEvent.Reset(); // no need to lock this

    expectedLength = expectedResponseLength;

    if (!comPort.IsOpen)
        comPort.Open();

    for (int i = 0; i < 3; i++)       
    {
        lock (messageLock)
        {
            response = string.Empty;
        }
        comPort.Write(s);
        if (resetEvent.WaitOne(5000))
            lock (messageLock)
            {
                return response;
            }
    }

    throw new Exception("Message failed to send.");
}

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    string received = comPort.ReadExisting();
    lock (messageLock)
    {
        response += received;
        if (response.Length >= expectedLength)
        {
            resetEvent.Set();
        }
    }
}
公共虚拟字符串写入数据(字符串s,int-expectedResponseLength)
{
resetEvent.Reset();//无需锁定此
expectedLength=expectedResponseLength;
如果(!comPort.IsOpen)
comPort.Open();
对于(int i=0;i<3;i++)
{
锁(messageLock)
{
response=string.Empty;
}
撰写;
if(resetEvent.WaitOne(5000))
锁(messageLock)
{
返回响应;
}
}
抛出新异常(“消息发送失败”);
}
私有void SerialPort_DataReceived(对象发送方,SerialDataReceivedEventArgs e)
{
接收到的字符串=comPort.ReadExisting();
锁(messageLock)
{
响应+=收到;
如果(response.Length>=expectedLength)
{
resetEvent.Set();
}
}
}
这一切仍然不能保证
WriteData
返回一些响应,而不是抛出
“消息发送失败”。
异常。在协议违反或编码问题的情况下,设备仍可能无法在给定超时内提供请求长度的响应。您需要跟踪由
ReadExisting()
返回的数据以跟踪问题。

Encode
public virtual string WriteData(string s, int expectedResponseLength)
{
    resetEvent.Reset(); // no need to lock this

    expectedLength = expectedResponseLength;

    if (!comPort.IsOpen)
        comPort.Open();

    for (int i = 0; i < 3; i++)       
    {
        lock (messageLock)
        {
            response = string.Empty;
        }
        comPort.Write(s);
        if (resetEvent.WaitOne(5000))
            lock (messageLock)
            {
                return response;
            }
    }

    throw new Exception("Message failed to send.");
}

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    string received = comPort.ReadExisting();
    lock (messageLock)
    {
        response += received;
        if (response.Length >= expectedLength)
        {
            resetEvent.Set();
        }
    }
}