【问题标题】:Reading wrong value from serial port从串口读取错误值
【发布时间】:2011-07-17 21:31:15
【问题描述】:

我必须从 RFID 阅读器读取 12 位标签号并将其打印到控制台。当我使用这个程序来读取标签时,我得到了一些奇怪的间距。

例如我的标签号是 4400E6EF1A57。当我继续扫描这个标签时,控制台窗口显示如下:

4400E6EF1
A57

4400E
6EF1A57

4400E6EF1A57

4400E6EF1
A57

4400E6EF1A57

4400
E6EF1A57

4
400E6EF1A57

4400E6EF1A
57

4
400E6EF1A57

4400E6EF1A5
7

4400E6EF1A57

4400E6EF1
A57

4400E6EF1A57

4400E
6EF1A57

4400
E6EF1A57

4400E6EF1A57

4400E6EF1A57

4400E6EF 1A57

4400E
6EF1A57

似乎有一长串 0 和 1 被读取,其中只有少数是实际的标签 ID。我不知道我阅读这些 0 和 1 的顺序是什么。

这是我的代码:(包含一些 SQL 和 JDBC 的东西,可以忽略)

import java.io.*;
import java.util.*;
import gnu.io.*;
import java.sql.*;


public class trying5 implements Runnable, SerialPortEventListener {
static Enumeration portList;
static CommPortIdentifier portId;

SerialPort serialPort;
InputStream inputStream;
Thread readThread;
Connection con;

public static void main(String[] args) {
    portList = CommPortIdentifier.getPortIdentifiers();
    while (portList.hasMoreElements()) {
        portId = (CommPortIdentifier) portList.nextElement();
        if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
             if (portId.getName().equals("COM3")) {
                trying5 reader = new trying5();

            }
        }
    }
}

public trying5()   {


    try {
        serialPort = (SerialPort) portId.open("trying5Application", 2000);
        }
        catch (PortInUseException e) 

        {
            System.out.println(e);
        }

    try {
        inputStream = serialPort.getInputStream();
        } 
        catch (IOException e) 

        {
            System.out.println(e);
        }

    try {
        serialPort.addEventListener(this);
        } 
        catch (TooManyListenersException e) 

        {
            System.out.println(e);
        }

        serialPort.notifyOnDataAvailable(true);

    try {
        serialPort.setSerialPortParams(9600,
            SerialPort.DATABITS_8,
            SerialPort.STOPBITS_1,
            SerialPort.PARITY_NONE);

        } 

    catch (UnsupportedCommOperationException e) 
        {
            System.out.println(e);
        }

    readThread = new Thread(this);
    readThread.start();

    }

public void run() {
    try {
        Thread.sleep(20000);
        } 
    catch (InterruptedException e) 
        {
            System.out.println(e);
        }
}

public void serialEvent(SerialPortEvent event) {
    switch(event.getEventType()) {
        case SerialPortEvent.BI:
        case SerialPortEvent.OE:
        case SerialPortEvent.FE:
        case SerialPortEvent.PE:
        case SerialPortEvent.CD:
        case SerialPortEvent.CTS:
        case SerialPortEvent.DSR:
        case SerialPortEvent.RI:
        case SerialPortEvent.OUTPUT_BUFFER_EMPTY:   
        break;

        case SerialPortEvent.DATA_AVAILABLE:

        byte[] readBuffer = new byte[20];



        // print to console

        try {
            while (inputStream.available() > 0) {
                int numBytes = inputStream.read(readBuffer);


            }



            String newtuple = new String(readBuffer);



            usercon newcon = new usercon(con, newtuple);

            System.out.print(newtuple + "\n");

        } catch (IOException e) 
        {
            System.out.println(e);
        }
        break;
    }
}
}

【问题讨论】:

    标签: java serial-port


    【解决方案1】:

    见http://download.oracle.com/javase/6/docs/api/java/io/InputStream.html#available() inputstream.available - 返回您可以在不阻塞的情况下读取多少字节(阻塞 = 等待更多字节)

    while (inputStream.available() > 0) {
      int numBytes = inputStream.read(readBuffer);
    }
    

    在某个时刻,您(例如)内部缓冲区中有 3 个字节可供读取。你读了它,用 while() 检查没有更多的 ready 字节,你就退出了循环。比您打印 3 个字节并输入 '\n' ... 这就是您的身份证损坏的原因。您应该继续阅读,直到您填充适当大小的缓冲区,当您的设备/com-port 将提供足够的字节时,阻塞并等待。

    使用 read(buf,off,len) 方法

    byte[] buf = new byte[12];
    int len = is.read(buf,0,buf.length);
    if (len != buf.length ) {
        throw new RuntimeException("the stream is closed and i failed to read enough data");
    }
    

    它将在内部阻塞直到读取所需的字节数,或者如果输入流在达到该数量之前报告“我完成了”,它将提前返回。

    【讨论】:

    • 我已经试过你建议的方式,这里是输出:4400E6EF1A57 4400E6EF1A57 00E6EF1A57 4400E6EF1A57 400E6EF1A57 4400E6EF1A5 0E6EF1A57 4400E6EF1A5 4400E6EF1A57 0E6EF1A57 00E6EF1A57 4400E6EF1A57大部分的时间,我可以正确读取12位标签号码,但有时它缺少一两个字节。我应该如何解决这个问题?
    • 你能依靠适当的 rfid 的大小而忽略较短的吗?我已经好几年没见过 com-port 软件了,但我记得我的 gps 接收器能够吞下一些字符,但会不断生成数据流——所以我们尝试解析一个块数据,如果出现错误,则简单地跳过该块.顺便说一句:其他活动可能对您有用。从 System.out.println 开始,他们已经发生并阅读日志可能是某些事件总是接近错误。
    【解决方案2】:

    流给你它所拥有的,你添加换行符:

    System.out.print(newtuple + "\n");
    

    您需要某种类型的缓冲区,例如 BufferedInputStream。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      相关资源
      最近更新 更多