Java RXTX和Arduino之间的串行通信

12
我正在尝试使用串口通信在我的电脑(Windows 7,使用Netbeans和RXTX)与一个Arduino Pro之间进行通信。实际上,Arduino是使用FTDI电缆连接到计算机的。
这段代码基于Java SimpleRead.Java,可以在这里找到。
目前,当Arduino启动时,它只会打印出一个字符串。我的Java程序应该打印出已经读取的字节数,然后打印出内容。这个Java程序正在工作,但有些问题...
如果字符串很长(大于10个字节左右),输出将会被分割成几部分。
因此,如果我在Arduino上打印:
Serial.println("123456789123456789"); //20 bytes including '\r' and '\n'

我的Java程序的输出可能会像这样:

Number of Bytes: 15   
1234567891234  
Number of Bytes: 5  
56789
或者
Number of Bytes: 12   
1234567891  
Number of Bytes: 8  
23456789

我认为这是一个时间问题,因为当我使用调试器手动浏览代码时,结果字符串总是正确的:一个20字节的字符串。

我已经尝试了一些不同的方法,但还是没有解决问题。

以下是导致问题的代码部分:

static int baudrate = 9600,
           dataBits = SerialPort.DATABITS_8,
           stopBits = SerialPort.STOPBITS_1,
           parity   = SerialPort.PARITY_NONE;    

byte[] readBuffer = new byte[128];

...
...

public void serialEvent(SerialPortEvent event)
{
   if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {

    try {
        if (input.available() > 0) { 
            //Read the InputStream and return the number of bytes read
            numBytes = input.read(readBuffer);

            String result  = new String(readBuffer,0,numBytes);
            System.out.println("Number of Bytes: " + numBytes);
            System.out.println(result);
        }
    } catch (IOException e) {
        System.out.println("Data Available Exception");
    }
}
3个回答

7

串行数据只是一串数据。根据读取时间和缓冲,当您读取数据时可能只有部分数据可用。

由于您正在使用面向行的数据,因此您需要缓冲数据直到看到行终止符,然后再处理数据。


由于某种原因,我假设数据将以单个流的方式连续发送。在 PC 端,我只需要查看串行输出,因此我认为我不会费心尝试存储完整的传入行,然后再显示它。我认为我只需按字节逐个显示数据即可。因此,我将使用 aByte = input.read(); 而不是 input.read(readBuffer);。 - SharpBarb
@SharpBarb - 没有必要切换到逐字节读取。如果你真的想这样做,我建议先读取缓冲区,然后在你的应用程序中分别处理每个字节。 - R Samuel Klatchko

3

我没有使用过Java RXTX,但是我玩过Arduino和Processing,从Arduino读/写值非常容易。这里有一个带有Processing的读取示例(文件>示例>库>串行>简单读取)。

/**
 * Simple Read
 * 
 * Read data from the serial port and change the color of a rectangle
 * when a switch connected to a Wiring or Arduino board is pressed and released.
 * This example works with the Wiring / Arduino program that follows below.
 */


import processing.serial.*;

Serial myPort;  // Create object from Serial class
int val;      // Data received from the serial port

void setup() 
{
  size(200, 200);
  // I know that the first port in the serial list on my mac
  // is always my  FTDI adaptor, so I open Serial.list()[0].
  // On Windows machines, this generally opens COM1.
  // Open whatever port is the one you're using.
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, 9600);
}

void draw()
{
  if ( myPort.available() > 0) {  // If data is available,
    val = myPort.read();         // read it and store it in val
  }
  background(255);             // Set background to white
  if (val == 0) {              // If the serial value is 0,
    fill(0);                   // set fill to black
  } 
  else {                       // If the serial value is not 0,
    fill(204);                 // set fill to light gray
  }
  rect(50, 50, 100, 100);
}



/*

// Wiring / Arduino Code
// Code for sensing a switch status and writing the value to the serial port.

int switchPin = 4;                       // Switch connected to pin 4

void setup() {
  pinMode(switchPin, INPUT);             // Set pin 0 as an input
  Serial.begin(9600);                    // Start serial communication at 9600 bps
}

void loop() {
  if (digitalRead(switchPin) == HIGH) {  // If switch is ON,
    Serial.print(1, BYTE);               // send 1 to Processing
  } else {                               // If the switch is not ON,
    Serial.print(0, BYTE);               // send 0 to Processing
  }
  delay(100);                            // Wait 100 milliseconds
}

*/

据我所记,当你实例化Serial时,在Arduino中设置波特率是非常重要的。例如,如果你使用9600发送信息,那么你应该使用相同的数字来监听。
此外,将你的信息发送为BYTE非常重要,否则会有像\r或\n这样的东西妨碍你。
简短版本,请尝试:
Serial.println(123456789123456789,BYTE);

越简单越好。

你好,Processing能否在没有Papplet的情况下工作?因为我正在尝试将其与我的Java代码集成... - wizztjh
感谢回复,@geory。假设我想从Arduino获取模拟输入,并且每当我向Arduino发送某些内容时,Arduino都会回复模拟值。根据链接中的代码,它只会打印出内容,而不是将其保存在变量中。我该如何将这个块存储到变量中?因为公共同步void serialEvent无法返回值,我认为... - wizztjh
1
@wizztjh 这是我脑海中的想法,但你有这段代码:byte chunk[] = new byte[available]; input.read(chunk, 0, available); ...之后,数据以字节形式存储,你应该能够使chunk变量对于整个类可见,而不仅仅是那个块。如果需要一个字符串,你可以创建一个类变量,并在input.read部分之后将其值设置为new String(chunk)。希望对你有所帮助。 - George Profenza

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接