基于C#实现USB转串口读取扫描枪数据

基于C#实现USB转串口读取扫描枪数据方案,结合串口通信原理与工业级实践:


一、硬件连接与配置

1. 设备连接示意图

扫描枪 → USB转串口模块 → 计算机
          ↑
          └─ 波特率:9600-115200
              数据位:8
              停止位:1
              校验位:无

2. 驱动安装指南

  1. 自动安装
    插入USB转串口设备 → 系统自动识别 → 设备管理器查看新生成的COM端口(如COM3)

  2. 手动安装(以CH340芯片为例)

    1. 下载驱动:https://www.wch.cn/downloads/CH341SER_ZIP.html
    2. 设备管理器 → 右键未知设备 → 更新驱动程序 → 选择下载的驱动目录
    3. 完成安装后确认COM端口分配
    

二、核心代码实现

1. 串口通信类(SerialPortHelper.cs)

using System;
using System.IO.Ports;
using System.Threading;

public class SerialPortHelper : IDisposable
{
    private SerialPort _serialPort;
    private Thread _readThread;
    private object _lock = new object();
    private bool _isRunning = false;

    public event Action<string> DataReceived;

    public SerialPortHelper(string portName, int baudRate = 9600)
    {
        _serialPort = new SerialPort(portName, baudRate)
        {
            Parity = Parity.None,
            DataBits = 8,
            StopBits = StopBits.One,
            Handshake = Handshake.None
        };
    }

    public bool OpenPort()
    {
        try
        {
            _serialPort.Open();
            _isRunning = true;
            _readThread = new Thread(ReadData);
            _readThread.Start();
            return true;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"打开串口失败: {ex.Message}");
            return false;
        }
    }

    private void ReadData()
    {
        while (_isRunning)
        {
            try
            {
                if (_serialPort.IsOpen)
                {
                    string data = _serialPort.ReadLine();
                    lock (_lock)
                    {
                        DataReceived?.Invoke(data.Trim());
                    }
                }
            }
            catch (TimeoutException) { /* 超时处理 */ }
            catch (IOException) { /* 断开连接处理 */ }
        }
    }

    public void ClosePort()
    {
        _isRunning = false;
        _serialPort?.Close();
    }

    public void Dispose()
    {
        ClosePort();
        _serialPort?.Dispose();
    }
}

2. 主窗体实现(Form1.cs)

public partial class Form1 : Form
{
    private SerialPortHelper _serialHelper;
    private StringBuilder _buffer = new StringBuilder();

    public Form1()
    {
        InitializeComponent();
        InitializeSerialPort();
    }

    private void InitializeSerialPort()
    {
        _serialHelper = new SerialPortHelper("COM3", 9600);
        _serialHelper.DataReceived += OnDataReceived;
        if (!_serialHelper.OpenPort())
        {
            MessageBox.Show("无法打开串口设备");
        }
    }

    private void OnDataReceived(string data)
    {
        if (InvokeRequired)
        {
            Invoke(new Action<string>(OnDataReceived), data);
            return;
        }

        // 处理数据格式(示例:去除头尾符号)
        string processedData = data.TrimStart('<').TrimEnd('>');

        // 更新UI
        txtBarcode.AppendText($"[{DateTime.Now:HH:mm:ss}] {processedData}{Environment.NewLine}");
        txtBarcode.ScrollToCaret();
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        _serialHelper?.Dispose();
        base.OnFormClosing(e);
    }
}

三、关键功能实现

1. 多线程数据处理

// 使用线程池处理耗时操作
private void ProcessBarcode(string code)
{
    ThreadPool.QueueUserWorkItem(_ => 
    {
        // 数据库存储
        SaveToDatabase(code);
        
        // 网络传输
        SendToServer(code);
    });
}

2. 数据校验与解析

public class BarcodeParser
{
    public static BarcodeData Parse(string rawData)
    {
        // 假设数据格式:[类型][长度][数据][校验码]
        if (rawData.Length < 5) return null;

        byte type = byte.Parse(rawData.Substring(0, 2), NumberStyles.HexNumber);
        ushort length = ushort.Parse(rawData.Substring(2, 4), NumberStyles.HexNumber);
        string data = rawData.Substring(6, length * 2);
        byte checksum = byte.Parse(rawData.Substring(6 + length * 2, 2), NumberStyles.HexNumber);

        return new BarcodeData
        {
            Type = (BarcodeType)type,
            Content = data,
            Checksum = checksum
        };
    }
}

public enum BarcodeType : byte
{
    EAN13 = 0x01,
    QR_CODE = 0x02,
    CODE128 = 0x03
}

参考代码 usb转串口 读取扫描枪扫描信息 www.youwenfan.com/contentcng49494.html

四、异常处理机制

1. 异常捕获策略

public class SerialExceptionHandler
{
    public static void Handle(Exception ex)
    {
        if (ex is TimeoutException)
        {
            // 重试机制
            RetryConnection();
        }
        else if (ex is IOException)
        {
            // 设备断开处理
            DeviceReconnected();
        }
        else
        {
            // 日志记录
            Logger.LogError(ex);
        }
    }
}

2. 自动重连逻辑

private void RetryConnection()
{
    int retryCount = 0;
    while (retryCount < 3)
    {
        try
        {
            _serialPort.Close();
            _serialPort.Open();
            return;
        }
        catch
        {
            retryCount++;
            Thread.Sleep(2000);
        }
    }
    throw new Exception("无法恢复串口连接");
}

五、调试与维护工具

1. 串口调试助手

public class DebugHelper
{
    public static void CaptureData(string portName)
    {
        using (var sp = new SerialPort(portName))
        {
            sp.Open();
            File.WriteAllBytes("debug_data.bin", sp.ReadByte());
        }
    }
}

2. 数据包分析

public class PacketAnalyzer
{
    public static void Analyze(byte[] data)
    {
        if (data[0] == 0x02 && data[1] == 0x10)
        {
            // 解析EAN13条码
            var ean = ParseEAN13(data.Skip(2).ToArray());
            LogEAN(ean);
        }
    }
}

六、部署建议

  1. 权限配置

    • 在app.manifest中添加:

      <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      
  2. 依赖项管理

    <!-- NuGet依赖 -->
    <PackageReference Include="System.IO.Ports" Version="6.0.0" />
    <PackageReference Include="CsvHelper" Version="28.0.0" />
    
  3. 安装包制作

    • 使用Inno Setup创建安装程序
    • 包含.NET Framework 4.8运行时
    • 添加USB设备驱动安装步骤

七、扩展功能实现

1. 多设备支持

public class MultiPortManager
{
    private Dictionary<string, SerialPortHelper> _ports = new();

    public void AddPort(string portName)
    {
        if (!_ports.ContainsKey(portName))
        {
            var port = new SerialPortHelper(portName);
            port.DataReceived += OnDataReceived;
            port.OpenPort();
            _ports.Add(portName, port);
        }
    }
}

2. 数据加密传输

public class SecureSerialPort : SerialPort
{
    private Aes _aes = Aes.Create();

    public byte[] EncryptData(byte[] data)
    {
        using (var encryptor = _aes.CreateEncryptor())
        {
            return encryptor.TransformFinalBlock(data, 0, data.Length);
        }
    }

    public byte[] DecryptData(byte[] data)
    {
        using (var decryptor = _aes.CreateDecryptor())
        {
            return decryptor.TransformFinalBlock(data, 0, data.Length);
        }
    }
}
posted @ 2025-09-10 16:41  yijg9998  阅读(54)  评论(0)    收藏  举报