C# 从串行端口仅读取8个字符
我试着自学制作RFID阅读器 我已经创建了一些从串行端口读取的代码(通过蓝牙RS232的rfid阅读器) 我希望有人能帮我解决的问题是: 我的RFID读卡器以非常快的速度连续传输卡代码,这意味着当我刷卡时,它将使用卡代码的不同部分多次触发我的事件处理程序,因此目前我无法一次性收到完整的卡代码,从而无法处理卡 到目前为止,我掌握的代码是: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
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(),现在它很简单。