Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从串行端口仅读取8个字符_C#_Event Handling_Serial Port - Fatal编程技术网

C# 从串行端口仅读取8个字符

C# 从串行端口仅读取8个字符,c#,event-handling,serial-port,C#,Event Handling,Serial Port,我试着自学制作RFID阅读器 我已经创建了一些从串行端口读取的代码(通过蓝牙RS232的rfid阅读器) 我希望有人能帮我解决的问题是: 我的RFID读卡器以非常快的速度连续传输卡代码,这意味着当我刷卡时,它将使用卡代码的不同部分多次触发我的事件处理程序,因此目前我无法一次性收到完整的卡代码,从而无法处理卡 到目前为止,我掌握的代码是: private SerialPort serialPort = new SerialPort("COM14", 9600, Parity.None, 8

我试着自学制作RFID阅读器

我已经创建了一些从串行端口读取的代码(通过蓝牙RS232的rfid阅读器)

我希望有人能帮我解决的问题是:

我的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个字符之前不触发,并且每秒只触发一次吗


提前感谢一位非常困惑的Ryan

您似乎有两个不同的问题:

  • 如何一次读八个字符
  • 如何将输入处理限制为每秒一个卡代码
  • 这两个问题可以(也应该)一起解决。您可以在
    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
        {  
        }
    }
    
    private const\u maxCharacters=8;
    私人密码=”;
    私有BlockingCollection代码=新建BlockingCollection();
    私有无效端口\u DataReceived(对象发送方,SerialDataReceivedEventArgs e)
    {
    if(addtag==false)
    {
    data=serialPort.ReadExisting();//读取来自RFID阅读器的内容
    而(data.Length>0)
    {
    字符串片段=
    子字符串(0,Math.Min(maxCharacters-code.Length,data.Length));
    代码+=片段;
    data=data.Substring(fragment.Length);
    if(code.Length==maxCharacters)
    {
    代码。添加(代码);
    代码=”;
    }
    }
    }
    其他的
    {  
    }
    }
    
    请注意,上面的代码实际上并不处理代码。相反,为了实现每秒一个代码的设计目标,您需要使用上述代码之外的代码(将延迟引入串行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);
        }
    }
    
    private static readonly TimeSpan minInterval=TimeSpan.FromSeconds(1);
    私有void CodeConsumer()
    {
    TimeSpan lastCode=TimeSpan.MinValue;
    秒表sw=Stopwatch.StartNew();
    foreach(codes.GetConsumingEnumerable()中的字符串代码)
    {
    TimeSpan interval=sw.appead-lastCode;
    if(间隔<最小间隔)
    {
    睡眠(最小间隔-间隔);
    }
    ProcessOneCode(代码);
    }
    }
    

    从串行端口读取完数据后,不要忘记调用
    codes.CompleteAdding()
    ,这样
    CodeConsumer()
    线程就可以退出。

    您无法真正控制串行通信的到达方式,但是您可以缓冲传入数据,直到您拥有整个消息。您能告诉我使用缓冲区的方向吗?您可以使用StringBuilder并将传入数据附加到它,直到builder.Length>=8,此时,您将处理数据并清除构建器以准备下一次扫描。您正在用新的传入数据覆盖数据。与其覆盖它,不如添加到它。而不是“data=serialPort.ReadExisting();“do”data+=serialPort.ReadExisting()。然后,当您处理一块数据时,删除您处理的数据。与其使用字符串,不如使用字节或字符缓冲区、数组或队列。RFID阅读器几乎总是可以配置为在字符串末尾发送特殊字符。可能已经有了,换行是标准的。它允许您使用ReadLine(),现在它很简单。