Java linux下串口的读写
我需要通过Raspberry Pi上的串行端口实现两个设备之间的通信(最后一个Raspbian在板上)。两者都使用CP2102控制器并连接到Pi 终端:Java linux下串口的读写,java,c++,linux,serial-port,raspbian,Java,C++,Linux,Serial Port,Raspbian,我需要通过Raspberry Pi上的串行端口实现两个设备之间的通信(最后一个Raspbian在板上)。两者都使用CP2102控制器并连接到Pi 终端: pi@pi ~ $ ls -l /dev/serial/by-id total 0 Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB2 pi@pi ~ $ ls -l /dev/serial/by-path total 0
pi@pi ~ $ ls -l /dev/serial/by-id
total 0
Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB2
pi@pi ~ $ ls -l /dev/serial/by-path
total 0
platform-bcm2708_usb-usb-0:1.2.1:1.0-port0 -> ../../ttyUSB1
platform-bcm2708_usb-usb-0:1.2.4:1.0-port0 -> ../../ttyUSB2
platform-bcm2708_usb-usb-0:1.3:1.0-port0 -> ../../ttyUSB0
public class Bridge_rxtx {
public static final int baudrate = 115200;
protected SerialPort spDevB_Data;
SerialReader devB_DataListener;
protected SerialPort spDevA_Data;
SerialReader DevA_DataListener;
protected SerialPort spDevA_Control;
SerialPortEventListener DevA_ControlListener;
public Bridge_rxtx(String comDevB_Data, String comDevA_Data, String comDevA_Control) {
try {
spDevB_Data = setupPort(comDevB_Data);
spDevA_Data = setupPort(comDevA_Data);
spDevA_Control = setupPort(comDevA_Control);
} catch (Exception ignored){
ignored.printStackTrace();
}
try {
devB_DataListener = new SerialReader(spDevB_Data.getInputStream(), spDevA_Data.getOutputStream(), "B-A");
DevA_DataListener = new SerialReader(spDevA_Data.getInputStream(), spDevB_Data.getOutputStream(), "A-B");
DevA_ControlListener = new SerialPortEventListener() {
@Override
public void serialEvent(SerialPortEvent spe) {
throw new UnsupportedOperationException("Not supported yet.");
}
};
spDevB_Data.notifyOnDataAvailable(true);
spDevA_Data.notifyOnDataAvailable(true);
spDevA_Control.notifyOnDataAvailable(true);
} catch (IOException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void launchBridge(){
System.out.println("Starting...");
try {
spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0x00}, 0, 2);
} catch (IOException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
try {
spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0xFF}, 0, 2);
} catch (IOException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Started");
}
SerialPort setupPort(String portName) throws Exception {
SerialPort serialPort = null;
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if (commPort instanceof SerialPort) {
serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} else {
System.out.println("Error: Only serial ports are handled by this code.");
}
}
return serialPort;
}
public static void main(String[] args) {
Bridge_rxtx bridge = new Bridge_rxtx("/dev/ttyUSB0", "/dev/ttyUSB2", "/dev/ttyUSB1");
bridge.launchBridge();
}
}
public class Bridge {
public static Bridge instance;
public static final int baudrate = 115200;
protected Serial spDevB_Data;
SerialDataListener devB_DataListener;
protected Serial spDevA_Data;
SerialDataListener devA_DataListener;
protected Serial spDevA_Control;
SerialDataListener devA_ControlListener;
private Bridge() {
}
public Bridge(String comDevB_Data, String comDevA_Data, String comDevA_Control) {
instance = this;
devA_ControlListener = new SerialDataListener() {
//SerialDataEvent in Pi4J doesn't support binary
//data by default. I implemented this myself.
public void dataReceived(SerialDataEvent event) {
System.out.println(bytesToHex(toPrimitives(event.getBinaryData())));
}
};
devB_DataListener = new SerialDataListener() {
public void dataReceived(SerialDataEvent event) {
byte[] data = toPrimitives(event.getBinaryData());
instance.spDevA_Data.write(data);
System.out.println("B -> A: " + bytesToHex(data));
}
};
devA_DataListener = new SerialDataListener() {
public void dataReceived(SerialDataEvent event) {
byte[] data = toPrimitives(event.getBinaryData());
instance.spDevB_Data.write(data);
try {
Thread.sleep(15);
} catch (InterruptedException ex) {
Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("B <- A: " + bytesToHex(data));
}
};
spDevB_Data = SerialFactory.createInstance();
spDevB_Data.addListener(devB_DataListener);
spDevA_Data = SerialFactory.createInstance();
spDevA_Data.addListener(devA_ControlListener);
spDevA_Control = SerialFactory.createInstance();
spDevA_Control.addListener(devA_DataListener);
spDevB_Data.setMonitorInterval(40);
spDevA_Data.setMonitorInterval(80);
spDevA_Control.setMonitorInterval(25);
spDevB_Data.open(comDevB_Data, baudrate);
spDevA_Data.open(comDevA_Data, baudrate);
spDevA_Control.open(comDevA_Control, baudrate);
}
public void SetupBridge() {
spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0x00});
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex);
}
spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0xFF});
}
}
通常,当我向串行A发送命令时,设备A通过串行A应答,并通过串行B发送数据。之后,我需要将此数据重新传输到设备B(串行C),并从串行C接收应答
问题是串行A应答出现在串行B上,串行B数据出现在串行A上 我尝试过不同的语言和串行库,但结果是一样的。所以问题是:为什么在使用树莓皮时会发生这种情况?如何在Raspberry Pi上实现此功能 另外,两个装置都工作正常。我的C#代码工作得很好。我使用System.IO.Ports.SerialPort类实现该实现,它看起来像Pi4J和RXTX解决方案 p.p.S.我尝试在RPi上使用的一些代码: ,C++:(一段非常糟糕的代码) Pi4J,Java:
pi@pi ~ $ ls -l /dev/serial/by-id
total 0
Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 -> ../../ttyUSB2
pi@pi ~ $ ls -l /dev/serial/by-path
total 0
platform-bcm2708_usb-usb-0:1.2.1:1.0-port0 -> ../../ttyUSB1
platform-bcm2708_usb-usb-0:1.2.4:1.0-port0 -> ../../ttyUSB2
platform-bcm2708_usb-usb-0:1.3:1.0-port0 -> ../../ttyUSB0
public class Bridge_rxtx {
public static final int baudrate = 115200;
protected SerialPort spDevB_Data;
SerialReader devB_DataListener;
protected SerialPort spDevA_Data;
SerialReader DevA_DataListener;
protected SerialPort spDevA_Control;
SerialPortEventListener DevA_ControlListener;
public Bridge_rxtx(String comDevB_Data, String comDevA_Data, String comDevA_Control) {
try {
spDevB_Data = setupPort(comDevB_Data);
spDevA_Data = setupPort(comDevA_Data);
spDevA_Control = setupPort(comDevA_Control);
} catch (Exception ignored){
ignored.printStackTrace();
}
try {
devB_DataListener = new SerialReader(spDevB_Data.getInputStream(), spDevA_Data.getOutputStream(), "B-A");
DevA_DataListener = new SerialReader(spDevA_Data.getInputStream(), spDevB_Data.getOutputStream(), "A-B");
DevA_ControlListener = new SerialPortEventListener() {
@Override
public void serialEvent(SerialPortEvent spe) {
throw new UnsupportedOperationException("Not supported yet.");
}
};
spDevB_Data.notifyOnDataAvailable(true);
spDevA_Data.notifyOnDataAvailable(true);
spDevA_Control.notifyOnDataAvailable(true);
} catch (IOException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void launchBridge(){
System.out.println("Starting...");
try {
spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0x00}, 0, 2);
} catch (IOException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
try {
spDevA_Control.getOutputStream().write(new byte[] {(byte)0xAA, (byte) 0xFF}, 0, 2);
} catch (IOException ex) {
Logger.getLogger(Bridge_rxtx.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Started");
}
SerialPort setupPort(String portName) throws Exception {
SerialPort serialPort = null;
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
if (portIdentifier.isCurrentlyOwned()) {
System.out.println("Error: Port is currently in use");
} else {
CommPort commPort = portIdentifier.open(this.getClass().getName(), 2000);
if (commPort instanceof SerialPort) {
serialPort = (SerialPort) commPort;
serialPort.setSerialPortParams(baudrate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
} else {
System.out.println("Error: Only serial ports are handled by this code.");
}
}
return serialPort;
}
public static void main(String[] args) {
Bridge_rxtx bridge = new Bridge_rxtx("/dev/ttyUSB0", "/dev/ttyUSB2", "/dev/ttyUSB1");
bridge.launchBridge();
}
}
public class Bridge {
public static Bridge instance;
public static final int baudrate = 115200;
protected Serial spDevB_Data;
SerialDataListener devB_DataListener;
protected Serial spDevA_Data;
SerialDataListener devA_DataListener;
protected Serial spDevA_Control;
SerialDataListener devA_ControlListener;
private Bridge() {
}
public Bridge(String comDevB_Data, String comDevA_Data, String comDevA_Control) {
instance = this;
devA_ControlListener = new SerialDataListener() {
//SerialDataEvent in Pi4J doesn't support binary
//data by default. I implemented this myself.
public void dataReceived(SerialDataEvent event) {
System.out.println(bytesToHex(toPrimitives(event.getBinaryData())));
}
};
devB_DataListener = new SerialDataListener() {
public void dataReceived(SerialDataEvent event) {
byte[] data = toPrimitives(event.getBinaryData());
instance.spDevA_Data.write(data);
System.out.println("B -> A: " + bytesToHex(data));
}
};
devA_DataListener = new SerialDataListener() {
public void dataReceived(SerialDataEvent event) {
byte[] data = toPrimitives(event.getBinaryData());
instance.spDevB_Data.write(data);
try {
Thread.sleep(15);
} catch (InterruptedException ex) {
Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("B <- A: " + bytesToHex(data));
}
};
spDevB_Data = SerialFactory.createInstance();
spDevB_Data.addListener(devB_DataListener);
spDevA_Data = SerialFactory.createInstance();
spDevA_Data.addListener(devA_ControlListener);
spDevA_Control = SerialFactory.createInstance();
spDevA_Control.addListener(devA_DataListener);
spDevB_Data.setMonitorInterval(40);
spDevA_Data.setMonitorInterval(80);
spDevA_Control.setMonitorInterval(25);
spDevB_Data.open(comDevB_Data, baudrate);
spDevA_Data.open(comDevA_Data, baudrate);
spDevA_Control.open(comDevA_Control, baudrate);
}
public void SetupBridge() {
spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0x00});
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE, null, ex);
}
spDevA_Control.write(new byte[]{(byte) 0xAA, (byte) 0xFF});
}
}
公共类桥{
公共静态桥梁实例;
公共静态最终整数波特率=115200;
受保护的串行spDevB_数据;
SerialDataListener dev_DataListener;
受保护的串行spDevA_数据;
SerialDataListener devA_DataListener;
受保护的串行spDevA_控制;
SerialDataListener devA_ControlListener;
私人桥梁(){
}
公共网桥(字符串comDevB_数据、字符串comDevA_数据、字符串comDevA_控件){
实例=此;
devA_ControlListener=新的SerialDataListener(){
//Pi4J中的SerialDataEvent不支持二进制文件
//默认情况下是数据。我自己实现了这个。
已接收公共无效数据(SerialDataEvent事件){
System.out.println(bytesToHex(toPrimitives(event.getBinaryData()));
}
};
devB_DataListener=new SerialDataListener(){
已接收公共无效数据(SerialDataEvent事件){
byte[]data=toPrimitives(event.getBinaryData());
实例.spDevA_Data.write(数据);
System.out.println(“B->A:+bytesToHex(数据));
}
};
devA_DataListener=新的SerialDataListener(){
已接收公共无效数据(SerialDataEvent事件){
byte[]data=toPrimitives(event.getBinaryData());
实例.spDevB_Data.write(数据);
试一试{
睡眠(15);
}捕获(中断异常例外){
Logger.getLogger(Bridge.class.getName()).log(Level.SEVERE,null,ex);
}
System.out.println(“B声誉不足,无法评论:
我有根据地猜测,这与Linux如何枚举硬件有关。我认为您的USB设备可能会有另一个串行路径,具体取决于使用的发行版和连接顺序
是否确定每次都使用相同的USB端口?并且正确的USB端口映射到/dev/tty
通过确保具有udev规则,您可以强制HID始终具有相同的名称。一些信息“问题是串行a应答显示在串行B上,串行B数据显示在串行a上“一个简单的补救方法可能是简单地为通过每个端口发送的数据添加一个标识符前缀。然后进入算法以确定是接受回复还是拒绝回复。RPi有两个USB端口。每个设备连接到其中一个端口。因此接线正常:)Prefix使系统复杂化,所以如果它是唯一能让它工作的方法,那么它是可以接受的。好吧,我仍然没有一点关于手头问题的线索,但是如果你使用JDK 7+,你至少能在Java代码中使用try with resources吗?我确信这个问题与Linux中的设备枚举没有任何共同之处。实际上,我已经放弃了使用Prefix的想法将两台设备都连接到Pi,因为它不再相关。不过,感谢您的回复。不客气;我刚刚被一条评论触发,说windows上的C运行良好。我不知道您在Raspberry上运行的C是什么意思。