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

如何从RS232串口数据中提取特定重量数值?

从RS232串口重量数据中提取特定数值

我通过USB转RS232串口连接重量指示器,开发了接收数据的应用(已能显示指示器发送的全部数据),但需要从返回数据中提取实际重量读数(比如15,000)。附当前C#代码及指示器数据表截图。

当前代码

namespace Weight_Test
{
public partial class Form1 : Form
{
string dataIN;

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        string[] ports = SerialPort.GetPortNames();
        cbComPort.Items.AddRange(ports);
        btnOpen.Enabled = true;
        btnClose.Enabled = false;
    }

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        dataIN = serialPort1.ReadExisting();
        this.Invoke(new EventHandler(ShowData));
    }

    private void ShowData(object sender, EventArgs e)
    {
        txtWeight.Text = dataIN;
    }

    private void btnOpen_Click(object sender, EventArgs e)
    {
        try
        {
            serialPort1.PortName = cbComPort.Text;
            serialPort1.BaudRate = Convert.ToInt32(9600);
            serialPort1.DataBits = Convert.ToInt32(8);
            serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
            serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), "None");

            serialPort1.Open();
            btnOpen.Enabled = false;
            btnClose.Enabled = true;
        }
        catch (Exception err)
        {
            MessageBox.Show(err.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            btnOpen.Enabled = true;
            btnClose.Enabled = false;
        }
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)
        {
            serialPort1.Close();
            btnOpen.Enabled = true;
            btnClose.Enabled = false;
        }
    }
}
}

解决方案

提取重量数值的核心是根据指示器的数据帧格式解析返回字符串,以下是通用处理方案及代码示例:

1. 先明确指示器的数据格式

从数据表截图中确认关键信息:

  • 重量数据在帧中的固定位置(起始偏移、长度)
  • 数据帧的分隔符(如\r\n、特定前缀/后缀)
  • 数值格式(是否带千分位逗号、符号、小数位)

2. 代码修改示例

场景1:重量位于固定位置的子串

假设数据帧格式为WEIGHT:15,000\r\n,重量从第7位开始,长度6:

private void ShowData(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(dataIN))
    {
        // 清除换行/回车干扰符
        string cleanData = dataIN.Replace("\r", "").Replace("\n", "");
        // 提取固定位置的重量字符串
        string weightStr = cleanData.Substring(7, 6);
        // 转换为数值(去除千分位逗号)
        if (double.TryParse(weightStr.Replace(",", ""), out double weightValue))
        {
            txtWeight.Text = weightValue.ToString("N0"); // 保留千分位显示
        }
        else
        {
            txtWeight.Text = "解析失败";
        }
    }
}

场景2:数据以分隔符分割(如逗号)

如果返回数据是ID,123,15,000,UNIT,重量为第3个字段:

private void ShowData(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(dataIN))
    {
        string cleanData = dataIN.Replace("\r", "").Replace("\n", "");
        string[] parts = cleanData.Split(',');
        if (parts.Length >= 4)
        {
            string weightStr = parts[3];
            if (double.TryParse(weightStr, out double weightValue))
            {
                txtWeight.Text = weightValue.ToString("N0");
            }
            else
            {
                txtWeight.Text = "解析失败";
            }
        }
    }
}

场景3:用正则匹配数值

如果重量是帧中唯一带千分位的数字:

using System.Text.RegularExpressions; // 添加该命名空间

private void ShowData(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(dataIN))
    {
        // 匹配带千分位的整数/小数,如15,000或15,000.50
        Match match = Regex.Match(dataIN, @"\d{1,3}(,\d{3})*(\.\d+)?");
        if (match.Success)
        {
            string weightStr = match.Value;
            if (double.TryParse(weightStr.Replace(",", ""), out double weightValue))
            {
                txtWeight.Text = weightValue.ToString("N0");
            }
            else
            {
                txtWeight.Text = "解析失败";
            }
        }
        else
        {
            txtWeight.Text = "未找到重量数据";
        }
    }
}

3. 额外注意事项

  • 串口数据可能分多次接收,建议缓存完整帧后再解析(比如直到收到结束符\r\n):
    // 将全局变量dataIN替换为StringBuilder
    StringBuilder dataBuffer = new StringBuilder();
    
    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        string newData = serialPort1.ReadExisting();
        dataBuffer.Append(newData);
        // 检测结束符,触发解析
        if (dataBuffer.ToString().Contains("\r\n"))
        {
            string fullFrame = dataBuffer.ToString().Split(new[] {"\r\n"}, StringSplitOptions.RemoveEmptyEntries)[0];
            dataBuffer.Clear();
            this.Invoke(new Action(() => ShowData(fullFrame)));
        }
    }
    
    // 修改ShowData接收完整帧
    private void ShowData(string fullFrame)
    {
        // 此处用fullFrame执行解析逻辑
    }
    
  • 确保串口参数(波特率、数据位等)与指示器设置完全一致,避免乱码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 01:20:39