You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#串口读取十六进制数据异常问题求助

解决SerialPort读取单片机十六进制数据时高位字节被替换为0x3F的问题

问题根源

你遇到的0x7F以上字节被替换为0x3F(问号)的问题,核心是SerialPort的Encoding设置错误。你设置的Windows-1252编码会将无法映射的字节强制替换为0x3F,而你需要读取的是原始十六进制字节流,不是文本字符,这个编码设置完全多余,反而会干扰原始字节的读取。

解决方案

1. 修正SerialPort的编码设置

直接移除serialPort1.Encoding = Encoding.GetEncoding("Windows-1252");这行代码,或者替换为不会修改原始字节的编码(比如iso-8859-1,它会将每个字节一对一映射为对应字符,不会产生替换):

// 推荐:直接移除编码设置,或者使用iso-8859-1
serialPort1.Encoding = Encoding.GetEncoding("iso-8859-1");

2. 优化字节读取逻辑

当前代码每次只读1个字节,效率低且容易出现读取不完整的情况。建议先获取可用字节数,一次性读取所有到达的字节,再逐个处理:

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    try
    {
        SerialPort sp = (SerialPort)sender;
        int bytesAvailable = sp.BytesToRead;
        byte[] tempBuffer = new byte[bytesAvailable];
        int bytesRead = sp.Read(tempBuffer, 0, bytesAvailable);

        foreach (byte b in tempBuffer.Take(bytesRead))
        {
            byte_input[count - 1] = b;
            count--;

            string hexValue = b.ToString("X2");
            this.BeginInvoke(new Action(() => textBox1.AppendText(hexValue + " ")));

            if (count == 0)
            {
                value = BitConverter.ToSingle(byte_input, 0);
                Array.Clear(byte_input, 0, byte_input.Length);
                this.BeginInvoke(new EventHandler(ShowData));
                count = 4;
            }
        }
    }
    catch (Exception ex)
    {
        this.BeginInvoke(new Action(() => textBox1.AppendText($"读取错误: {ex.Message}\n")));
    }
}

3. 校验串口参数

务必确保SerialPort的波特率、数据位、停止位、奇偶校验位和单片机的配置完全一致,参数不匹配也会导致读取到错误的字节。

补充说明

  • 基于字符的读取方法(比如ReadChar、ReadExisting)会受Encoding设置影响,读取原始字节时,优先使用Read(byte[])这类直接操作字节的方法。
  • 调试时可以直接输出读取到的字节值,确认是否在读取阶段就已经出现错误,而不是后续显示环节的问题。

内容的提问来源于stack exchange,提问作者user24354609

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:14:50