2012-07-12 106 views
2

我遇到了一个小型C#应用程序的问题。 应用程序必须通过串行端口连接到读取Data Matrix代码的条形码扫描器。 Data Matrix代码表示一个zip文档的字节数组。我读了很多关于SerialPort.DataReceived的工作方式,但我找不到解决我的问题的优雅方案。该应用程序应该与不同的条形码扫描仪一起工作,所以我不能使它成为扫描仪特定的。这里是我的一些代码:C#串行端口通信问题

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()); 

      } 
     } 

    } 
} 

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

+0

的文档的核心问题是您_serialPort.Read()调用。它有一个你不能忽视的返回值。它将*不*为10000,然而在您调用它时会收到很多字节。这通常是一对夫妇,当然不是组成.zip内容的整个字节集合。你需要缓冲你读的东西。而且你需要知道你什么时候得到它们。这是你必须找到的东西,仔细阅读条码扫描仪手册。 – 2012-07-12 21:32:34

回答

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(); 
     } 


    } 
+1

你最后一次看戴维的代码是什么时候?我猜测在此之间的某个时间,现在你已经知道指定'MessageBoxIcon'到'MessageBox.Show'调用将导致播放适当的声音;) – Tergiver 2012-07-12 21:11:23

+0

很久以前。 (在一个遥远的银河系里,开机。)正如我所说,它已经工作了很多年了,而且我通常不会做WinForms应用程序。那很好笑。如果/当我需要更新它,我会解决这个问题。谢谢! – David 2012-07-12 21:13:12