【问题标题】:C# Serial Port communication issueC#串口通信问题
【发布时间】:2012-07-12 20:57:10
【问题描述】:

我遇到了一个小型 C# 应用程序的问题。 该应用程序必须通过串行端口连接到读取数据矩阵代码的条形码扫描仪。数据矩阵代码表示一个字节数组,它是一个 zip 存档。我阅读了很多关于 SerialPort.DataReceived 工作方式的信息,但我找不到一个优雅的解决方案来解决我的问题。并且该应用程序应与不同的条形码扫描仪一起使用,因此我无法使其特定于扫描仪。这是我的一些代码:

    using System;
    using System.IO;
    using System.IO.Ports;
    using System.Windows.Forms;
    using Ionic.Zip;

    namespace SIUI_PE
    {
        public partial class Form1 : Form
        {
            SerialPort _serialPort;

        public Form1()
        {

            InitializeComponent();


        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                _serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error:" + ex.ToString());
                return;
            }
            _serialPort.Handshake = Handshake.None;
            _serialPort.ReadBufferSize = 10000;
            _serialPort.DataReceived += new SerialDataReceivedEventHandler(comPort_DataReceived);
            _serialPort.Open();

        }
        void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
           byte[] data = new byte[10000];
           _serialPort.Read(data, 0, 10000);
           File.WriteAllBytes(Directory.GetCurrentDirectory() + "/temp/fis.zip", data);
             try
             {
                 using (ZipFile zip = ZipFile.Read(Directory.GetCurrentDirectory() + "/temp/fis.zip"))
                 {
                     foreach (ZipEntry ZE in zip)
                     {
                         ZE.Extract(Directory.GetCurrentDirectory() + "/temp");
                     }
                 }
                 File.Delete(Directory.GetCurrentDirectory() + "/temp/fis.zip");

             }
             catch (Exception ex1)
             {
                 MessageBox.Show("Corrupt Archive: " + ex1.ToString());

             }
        }

    }
}

所以我的问题是:我怎么知道我读取了扫描仪发送的所有字节?

【问题讨论】:

  • 核心问题是您的 _serialPort.Read() 调用。它有一个你不能忽略的返回值。它不会为 10000,但是在您调用它时碰巧收到了许多字节。这通常是一对,当然不是构成 .zip 内容的整个字节集。您需要缓冲您阅读的内容。你需要知道你什么时候得到它们。这是您必须找出的东西,请仔细阅读条形码扫描仪手册。

标签: c# serial-port barcode-scanner


【解决方案1】:

我用于读取条码数据的代码在生产环境中已经运行了好几年,看起来像这样:

请注意,我的应用必须读取标准 UPC 条形码以及 GS1 DataBar,因此您可能不需要一些代码...

这里的关键是:

string ScanData = ScannerPort.ReadExisting(); 

在 DoScan 部分中找到,它只是将扫描数据作为字符串读取。它绕过了知道发送了多少字节的需要,并使其余代码更容易处理。


     // This snippet is in the Form_Load event, and it initializes teh scanner
        InitializeScanner();
        ScannerPort.ReadExisting();
        System.Threading.Thread.Sleep(1000);
     // ens snippet from Form_Load.

        this.ScannerPort.DataReceived += new SerialDataReceivedEventHandler(ScannerPort_DataReceived);


delegate void DoScanCallback();  // used for updating the form UI

void DoScan()
    {
        if (this.txtCouponCount.InvokeRequired)
        {
            DoScanCallback d = new DoScanCallback(DoScan);
            this.Invoke(d);
            return;
        }
        System.Threading.Thread.Sleep(100);
        string ScanData = ScannerPort.ReadExisting();
        if (isInScanMode)
        {
            try
            {
                HandleScanData(ScanData);
            }
            catch (Exception ex)
            {
                     System.Media.SystemSounds.Beep.Play();
                     MessageBox.Show("Invalid Scan");
            }
        }
    }
    void ScannerPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        // this call to sleep allows the scanner to receive the entire scan.
        // without this sleep, we've found that we get only a partial scan.
        try
        {
            DoScan();
        }
        catch (Exception ex)
        {
                System.Media.SystemSounds.Beep.Play();
                MessageBox.Show("Unable to handle scan event in ScannerPort_DataReceived." + System.Environment.NewLine + ex.ToString());
        }

    }
    void Port_ErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
    {

          System.Media.SystemSounds.Beep.Play();
          MessageBox.Show(e.EventType.ToString());
    }
    private void HandleScanData(string ScanData)
    {
        //MessageBox.Show(ScanData + System.Environment.NewLine + ScanData.Length.ToString());

        //Determine which type of barcode has been scanned, and handle appropriately.
        if (ScanData.StartsWith("A") && ScanData.Length == 14)
        {
            try
            {
                ProcessUpcCoupon(ScanData);
            }
            catch (Exception ex)
            {
                     System.Media.SystemSounds.Beep.Play();
                     MessageBox.Show("Unable to process UPC coupon data" + System.Environment.NewLine + ex.ToString());

            }
        }
        else if (ScanData.StartsWith("8110"))
        {
            try
            {
                ProcessDataBarCoupon(ScanData);
            }
            catch (Exception ex)
            {
                     System.Media.SystemSounds.Beep.Play();
                     MessageBox.Show("Unable to process DataBar coupon data" + System.Environment.NewLine + ex.ToString());
            }
        }
        else
        {
                System.Media.SystemSounds.Beep.Play();
                MessageBox.Show("Invalid Scan" + System.Environment.NewLine + ScanData);
        }


    }


    private void InitializeScanner()
    {
        try
        {
            ScannerPort.PortName = Properties.Settings.Default.ScannerPort;
            ScannerPort.ReadBufferSize = Properties.Settings.Default.ScannerReadBufferSize;
            ScannerPort.Open();
            ScannerPort.BaudRate = Properties.Settings.Default.ScannerBaudRate;
            ScannerPort.DataBits = Properties.Settings.Default.ScannerDataBit;
            ScannerPort.StopBits = Properties.Settings.Default.ScannerStopBit;
            ScannerPort.Parity = Properties.Settings.Default.ScannerParity;
            ScannerPort.ReadTimeout = Properties.Settings.Default.ScannerReadTimeout;
            ScannerPort.DtrEnable = Properties.Settings.Default.ScannerDtrEnable;
            ScannerPort.RtsEnable = Properties.Settings.Default.ScannerRtsEnable;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Unable to initialize scanner.  The error message received will be shown next.  You should close this program and try again.  If the problem persists, please contact support.", "Error initializing scanner");
            MessageBox.Show(ex.Message);
            Application.Exit();
        }


    }

【讨论】:

  • 您最后一次查看 David 的代码是什么时候?我猜从那时到现在的某个时候,您已经了解到将 MessageBoxIcon 指定给 MessageBox.Show 调用将导致播放适当的声音 ;)
  • 很久很久以前。 (在遥远的银河系中启动。)正如我所说,它已经工作了多年,而且我通常不使用 WinForms 应用程序。那很好笑。如果/当我需要更新它时,我会修复它。谢谢!
【解决方案2】:

如 SerialPort.DataReceived 文档中所述,“使用 BytesToRead 属性确定缓冲区中还有多少数据要读取。”

这里是 SerialPort.BytesToRead 的文档

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.bytestoread.aspx

【讨论】:

    猜你喜欢
    • 2010-10-26
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 2022-12-01
    • 1970-01-01
    相关资源
    最近更新 更多