2015-01-14 31 views
4

我試圖自學C Sharp製作RFID​​閱讀器。只讀串行端口的8個字符

我已經創造了一些代碼從一個串行端口(RFID閱讀器通過藍牙RS232)讀取

問題IM希望有人能幫助我的是:

我RFID閱讀器在傳送卡代碼非常快速的繼承意思是當我刷卡時,它將不止一次地用我的事件處理程序用卡代碼的不同部分啓動,所以目前我無法在一次命中中收到完整的卡代碼,從而無法處理卡。

我到目前爲止的代碼是:

private SerialPort serialPort = new SerialPort("COM14", 9600, Parity.None, 8, StopBits.One); // set com port 

    String code; // this stores the code from the RFID reader/serial port 
    Int32 id; // this is the ID of the person that the RFID code belongs to 
    String data; 

    bool addtag; 

    public Int32 ID // set the ID so it can be passed to other forms 
    { 
     get { return id; } 
    } 

    public rfidreader() 
    { 
     serialPort.DtrEnable = true; // enable data to flow from the SerialPort 
     OpenSerialPort(); // Call the OpenSerialPort section below 

     serialPort.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); // when data is recieved from the RFID reader fire the event handaler 
    } 

    public void PauseRFIDReader() 
    { 
     addtag = false; 
     OpenSerialPort(); 
    } 

    public void CloseSerialPort() 
    { 
     serialPort.Close(); 
     addtag = true; 
    } 

    private void OpenSerialPort() // called from above 
    { 
     try 
     { 
      serialPort.Open(); // open the serialport 
     } 
     catch // if serail port unavalable show message box, if Retry is pressed run this section again, if cancel carry on without serial port 
     { 
      DialogResult result = MessageBox.Show("Failed to connect to the RFID reader" + "\n" + "Check the reader is powered on and click Retry" + "\n\n" + "Press Cancel to use the program without RFID reader", "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error); 
      if (result == DialogResult.Retry) 
      { 
       OpenSerialPort(); // if retry is pressed run the sectiona gain 
      } 
      else 
      { 
      } 
     } 
    } 

    private void port_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) // data recieved from RFID reader 
    { 
     if (addtag == false) 
     { 
      data = serialPort.ReadExisting(); // read what came from the RFID reader 

      if (data.Length >= 9) // check if the string if bigger than 9 characters 
      { 
       code = data.Substring(0, 9); // if string is bigget than 9 characters trim the ending characters until it is only 9 long 
      } 
      else 
      { 
       code = data; // if less that 9 characters use however many it gets 
      } 
      MessageBox.Show(code.ToString()); 
      Start(); // start to process the person 

     } 
     else 
     { 
     } 
    } 

任何人都可以讓我知道如何從發射直到接收到8個字符,只火一次,第二次限制事件處理程序?

在此先感謝一個很有頭腦猛然一驚瑞安

+1

您無法真正控制串行通信的傳輸方式,但您可以緩衝傳入的數據,直到獲得完整的消息。 – itsme86

+0

你能指出我使用緩衝區請求的方向嗎? – Ryanagray

+0

您可以使用StringBuilder並將傳入數據附加到它,直到builder.Length> = 8,此時您將處理數據並清除構建器以準備進行下一次掃描。 – itsme86

回答

0

你似乎這裏有兩個不同的問題:

  1. 如何一次讀取八個字符。
  2. 如何將輸入處理限制爲每秒一張卡片代碼。

這兩者可以(也應該)一起解決。您可以在您的DataReceived事件處理程序中修復第一個問題,但具體細節取決於第二個問題。

不幸的是,你的問題說你一次只需要八個字符,但是你的代碼卻說了九個。所以我無法確保細節是正確的。我只需添加一個常量,然後讓你決定。 :)

我建議這樣的事情來處理輸入:

private const _maxCharacters = 8; 
private code = ""; 
private BlockingCollection<string> codes = new BlockingCollection<string>(); 

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (addtag == false) 
    { 
     data = serialPort.ReadExisting(); // read what came from the RFID reader 

     while (data.Length > 0) 
     { 
      string fragment = 
       data.Substring(0, Math.Min(maxCharacters - code.Length, data.Length)); 

      code += fragment; 
      data = data.Substring(fragment.Length); 

      if (code.Length == maxCharacters) 
      { 
       codes.Add(code); 
       code = ""; 
      } 
     } 
    } 
    else 
    { 
    } 
} 

注意,上面並沒有實際處理的代碼。相反,爲了完成每秒一個代碼設計目標,您需要使用上述以外的代碼(將延遲引入串行I/O本身只會導致問題)。

所以,在不同的線程:

private static readonly TimeSpan minInterval = TimeSpan.FromSeconds(1); 

private void CodeConsumer() 
{ 
    TimeSpan lastCode = TimeSpan.MinValue; 
    Stopwatch sw = Stopwatch.StartNew(); 

    foreach (string code in codes.GetConsumingEnumerable()) 
    { 
     TimeSpan interval = sw.Elapsed - lastCode; 

     if (interval < minInterval) 
     { 
      Thread.Sleep(minInterval - interval); 
     } 

     ProcessOneCode(code); 
    } 
} 

不要忘記調用codes.CompleteAdding()大功告成從串口讀取時,所以CodeConsumer()線程可以退出。