Чтение ftdi для отображения строки

Я использую этот код для чтения чипа RFID SN через считыватель ftdi usb. Я хочу использовать RFID SN (0DBFFC21) позже в SQL-запросах.

Моя проблема в том, что я получаю SN много раз, разбитый на две строки ... Как мне поставить задержку или что-то в этом роде, чтобы я мог каждый раз получать полную строку?

введите описание изображения здесь

    #region Namespace Inclusions
using System;
using System.IO.Ports;
using System.Windows.Forms;
#endregion

namespace SerialPortExample
{
  class SerialPortProgram
  {
    // Create the serial port with basic settings
    private SerialPort port = new SerialPort("COM1",
      9600, Parity.None, 8, StopBits.One);

    [STAThread]
    static void Main(string[] args)
    { 
      // Instatiate this class
      new SerialPortProgram();
    }

    private SerialPortProgram()
    {
      Console.WriteLine("Incoming Data:");

      // Attach a method to be called when there
      // is data waiting in the port's buffer
      port.DataReceived += new 
        SerialDataReceivedEventHandler(port_DataReceived);

      // Begin communications
      port.Open();

      // Enter an application loop to keep this thread alive
      Application.Run();
    }

    private void port_DataReceived(object sender,
      SerialDataReceivedEventArgs e)
    {
      // Show all the incoming data in the port's buffer
      Console.WriteLine(port.ReadExisting());
    }
  }
}

person nordscan    schedule 21.02.2017    source источник
comment
вы можете добавить к своему вопросу ожидаемую полную строку? согласно добавленному вами скриншоту.   -  person KernelMode    schedule 21.02.2017
comment
у этой строки есть определенная длина? Какое значение имеет port.BytesToRead, когда событие DataReceived запускается каждый раз? Соответствует ли это прочитанной строке?   -  person Mong Zhu    schedule 21.02.2017
comment
@KernelMode, всегда должно быть 0DBFFC21. И проблема хорошо известна (хотя не удается найти красивый дубликат, возможно, этот). SerialPort.DataReceived не гарантируется, что будет повышен для полного пакета (я полагаю, если вы не установите тайм-аут и не используете рукопожатие), это может произойти после получения всего одного байта. Вы должны сами объединять сообщения.   -  person Sinatr    schedule 21.02.2017
comment
Мне нужно прочитать серийный номер с чипов RFID, я могу получить из sql имя сотрудника. Также другой чип, другой серийный номер, может иметь разную длину   -  person nordscan    schedule 21.02.2017
comment
@Sinatr, спасибо. Так как же узнать, что вы прочитали все СН?   -  person KernelMode    schedule 21.02.2017
comment
Я новичок в C #, но моя идея примерно такая: прочтите чип - ›получите значение (SN) -› подождите 1000 мс (чтобы я получил полный SN) - ›запустите sql query   -  person nordscan    schedule 21.02.2017
comment
Вы можете получить только часть, если вы ждете слишком мало или наоборот, слишком долгое ожидание будет сцеплено несколько раз SN (например, 0DBFFC210DB). Вы что-нибудь знаете наверняка? Например. всегда ли это 8 символов, отправляется ли оно каждую секунду и т. д.?   -  person Sinatr    schedule 21.02.2017
comment
Хорошо, можно попробовать всегда с 8чаром   -  person nordscan    schedule 21.02.2017
comment
Ваш снимок экрана показывает перевод строки в конце каждого полного серийного номера. Почему бы вам просто не выполнить буферизацию, пока не увидите перевод строки?   -  person Scott Mermelstein    schedule 21.02.2017
comment
мы можем попробовать это с переводом строки, может быть, это лучше   -  person nordscan    schedule 22.02.2017


Ответы (1)


Правильный подход может отличаться, но вот один простой способ чтения данных известного размера:

string _buffer;

void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    _buffer += port.ReadExisting(); // read into buffer
    if (_buffer.Length > 7) // wait until at least 8 characters are received
    {
        Console.WriteLine(_buffer.Substring(0, 8)); // display
        _buffer = _buffer.Substring(8, _buffer.Length - 8); // remove from buffer
    }
}

если задержка между пакетами достаточно велика, может быть достаточно следующего кода:

    _buffer += port.ReadExisting();
    if (_buffer.Length >= 8)
    {
        Console.WriteLine(_buffer);
        _buffer = null;
    }
person Sinatr    schedule 21.02.2017
comment
@Sintar, если полученные данные имеют длину 100, почему в последней строке вы присваиваете buffer 92 символа? Какой в ​​этом смысл? - person KernelMode; 22.02.2017
comment
я пробую, но теперь он работает правильно см. здесь, первое нормально, а второе плохо .. .. - person nordscan; 22.02.2017
comment
@KernelMode, может случиться так, что вы прочитаете несколько байтов следующего пакета в момент наступления события. Если это не так (например, если между пакетами большая задержка, быстрая обработка и т. Д.), Тогда просто очистите буфер (_buffer = null). - person Sinatr; 22.02.2017
comment
@Sinatr, вы всегда печатаете первые 8 символов, а затем вырезаете последние 8 символов. Вы хотели вырезать первые 8? - person KernelMode; 22.02.2017
comment
теперь его на 99% нормально, но иногда (1 из 20 попыток) его нет в одной строке здесь , но я могу предотвратить это, проверяя длину перед запросом sql. - person nordscan; 22.02.2017