我实现了一个维护与不同端口的串行通信的代码。
但是,相同的代码在 USB 端口 /dev/ttyUSB0 上运行良好,但在端口 /dev/ttyAMA0 上无法运行(如果我使用 PI4J 库,此端口正在运行)
波特率:
/dev/ttyAMA0 - 115200
/dev/ttyUSB0 - 9600
我在带有 Java 9 的树莓派 3B 上运行
我在这里缺少什么?
这是我的代码:
public class JSerialComm extends BaseSerial
{
private SerialPort serial = null;
private Object recLock = new Object();
public JSerialComm()
{
super();
}
@Override
protected boolean checkIsClosed()
{
return this.serial == null || !this.serial.isOpen();
}
@Override
protected void registerToSerialEventListener()
{
this.serial.addDataListener(new SerialPortPacketListener()
{
@Override
public void serialEvent(SerialPortEvent event)
{
try
{
synchronized (recLock)
{
if(event.getSerialPort().bytesAvailable()>=getPacketSize())
{
final byte[] newData = new byte[getPacketSize()];
event.getSerialPort().readBytes(newData, getPacketSize());
notifyHandlers(newData);
}
}
}
catch(Exception e)
{
}
}
@Override
public int getListeningEvents()
{
return SerialPort.LISTENING_EVENT_DATA_AVAILABLE;
}
@Override
public int getPacketSize()
{
return MindoLifeJSerialComm.this.getPacketSize();
}
});
}
@Override
protected int sendByteToSerial(byte[] input) throws Exception
{
return sendByteToSerial(input,input.length);
}
@Override
protected void openPort(String portName, int baudRate) throws Exception
{
for (SerialPort port : SerialPort.getCommPorts())
{
if (portName.toLowerCase().endsWith(port.getSystemPortName().toLowerCase()))
{
serial = port;
}
}
if(serial == null)
{
throw new Exception("Couldn't find port " + portName );
}
serial.setBaudRate(baudRate);
serial.setComPortTimeouts(SerialPort.TIMEOUT_NONBLOCKING, 0, 0);
serial.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED);
serial.setParity(SerialPort.NO_PARITY);
serial.setNumStopBits(SerialPort.ONE_STOP_BIT);
if (!serial.openPort())
{
throw new Exception("Couldn't open port " + portName + " opened with baud " + baudRate);
}
}
@Override
protected int sendByteToSerial(byte[] input, int length) throws Exception {
int res = serial.writeBytes(input, length);
// TODO:flush
return res;
}
@Override
protected void closePort() {
this.serial.closePort();
}
}
基类:
public abstract class BaseSerial
{
HasSerialMessageHandler handler;
private Object recLock = new Object();
private int packetSize = 1;
private String portName;
protected final void notifyHandlers(byte[] newData)
{
if (handler != null)
{
handler.incoming(newData);
}
}
private Object writeLock = new Object();
public int write(byte[] input) throws Exception
{
return write(input, -1);
}
public int write(byte[] input, int length) throws Exception
{
int res = sendByteToSerial(input,length);
return res;
}
public void addListener(final HasSerialMessageHandler handler) throws TooManyListenersException
{
this.handler = handler;
registerToSerialEventListener();
}
public boolean isClosed()
{
return checkIsClosed();
}
public void open(String portName, int baudRate) throws Exception
{
this.portName = portName;
openPort(portName, baudRate);
Thread.sleep(1000);
}
public int getPacketSize()
{
return packetSize;
}
public void setPacketSize(int packetSize)
{
this.packetSize = packetSize;
}
public void close()
{
closePort();
}
public String getPortName()
{
return portName;
}
protected abstract boolean checkIsClosed();
protected abstract void registerToSerialEventListener();
protected abstract void openPort(String portName, int baudRate) throws Exception;
protected abstract int sendByteToSerial(byte[] input) throws Exception;
protected abstract int sendByteToSerial(byte[] input, int length) throws Exception;
protected abstract void closePort();
}
初始化和使用(对于两个端口):
public class Main
{
public static void main(String[] args)
{
BaseSerial serial = new JSerialComm ();
serial.setPacketSize(14);
serial.addListener(new HasSerialMessageHandler() {
@Override
public void incoming(final byte[] message)
{
if (message.length > 0)
{
sysout(message);
}
}
serial.open("/dev/ttyAMA0", 115200);
});
}
}
我/etc/inittab
的设置如下:
1:2345:respawn:/sbin/getty --noclear 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6
# Example how to put a getty on a serial line (for a terminal)
#
#T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
#T1:23:respawn:/sbin/getty -L ttyS1 9600 vt100
# Example how to put a getty on a modem line.
#
#T3:23:respawn:/sbin/mgetty -x0 -s 57600 ttyS3
#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100