首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从串口读取8个字符

从串口读取8个字符
EN

Stack Overflow用户
提问于 2015-01-14 21:07:24
回答 1查看 1.6K关注 0票数 4

我试着用制造RFID阅读器来教自己C夏普。

我创建了一些从串口读取的代码(基于蓝牙RS232的rfid读取器)

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

我的RFID阅读器非常快地连续发送卡片代码,这意味着当我刷卡时,它会用卡片代码的不同部分不止一次地解雇我的事件处理程序,因此目前我无法在一击中收到完整的卡片代码,因此无法处理该卡。

到目前为止,我的代码是:

代码语言:javascript
复制
    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个字符之前触发,并且每秒钟只触发一次吗?

“谢谢你,”瑞恩心烦意乱地说。

EN

回答 1

Stack Overflow用户

发布于 2015-01-15 06:04:28

你在这里似乎有两个不同的问题:

  1. 如何一次读八个字符。
  2. 如何将输入的处理限制为每秒一张卡片代码。

这两个问题可以(而且应该)一起处理。您可以修复DataReceived事件处理程序中的第一个问题,但具体细节将取决于第二个问题。

不幸的是,你的问题说你一次需要八个字符,但是你的代码是九个。所以我没有办法确保细节是正确的。我会加一个常数,让你决定。:)

我推荐这样的东西来处理输入:

代码语言:javascript
复制
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本身中引入延迟只会导致问题)。

因此,在另一个线程中:

代码语言:javascript
复制
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()线程就可以退出。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27952452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档