简体   繁体   English

串口写入/读取linux

[英]Serial ports writing/reading in linux

I need to implement communication between two devices through serial ports on Raspberry Pi (with last Raspbian on board). 我需要通过Raspberry Pi上的串口实现两台设备之间的通信(板载最后一个Raspbian)。 Both uses CP2102 controller and connected to the Pi. 两者都使用CP2102控制器并连接到Pi。

数据流

Terminal: 终奌站:

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

Normally when I send command to SERIAL A, Device A replies through SERIAL A and sends data through SERIAL B. After that I need to retranslate this data to Device B (SERIAL C) and receive answer from SERIAL C. 通常当我向SERIAL A发送命令时,Device A通过SERIAL A回复并通过SERIAL B发送数据。之后我需要将这些数据重新转换为Device B(SERIAL C)并从SERIAL C接收回答。

The problem is that SERIAL A reply appears on SERIAL B and SERIAL B data appears on SERIAL A. 问题是SERIAL A回复出现在SERIAL B上,SERIAL B数据出现在SERIAL A上。

I've tried different languages and serial libraries but the result is the same. 我尝试过不同的语言和串行库,但结果是一样的。 So the questions are: why is it happening when using Raspberry Pi? 所以问题是:为什么在使用Raspberry Pi时会发生这种情况? How can I implement this functionality on Raspberry Pi? 如何在Raspberry Pi上实现此功能?

PS Both devices are working properly. PS这两个设备都正常工作。 My C# code works perfect. 我的C#代码非常完美。 I used System.IO.Ports.SerialPort class for that implementation and it looks like Pi4J and RXTX solutions. 我为该实现使用了System.IO.Ports.SerialPort类,它看起来像Pi4J和RXTX解决方案。

PPS Some code that I tried to use on RPi: PPS我尝试在RPi上使用的一些代码:

Serial , C++: (very bad piece of code) Serial ,C ++ :(非常糟糕的一段代码)

Serial port("/dev/ttyUSB2", 115200U);
Serial port1("/dev/ttyUSB1", 115200U);
port1.setTimeout(Timeout::max(), 250, 0, 250, 0);
port.setTimeout(Timeout::max(), 250, 0, 250, 0);

cout << "Is the serial port open?";
if (port1.isOpen()) {
    cout << " Yes." << endl;
    uint8_t data[2] = { 0xAA, 0x00 };
    port1.write(data, 2);
    data[1] = 0xFF;
    sleep(1);
    port1.write(data, 2);
    while (port.available() < 7);
    int av = port.available();
    string ss;
    port.read(ss, av);
    for (int i = 0; i < av; i++){
        cout << (uint)ss.at(i) << " ";
    }
    cout << "av: " + (uint)av << endl;
}

RXTX, Java: RXTX,Java:

    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();
        }
    }

Pi4J, Java: Pi4J,Java:

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});
    }
}

Not enough reputation to comment: My educated guess would be that it has something to do with how Linux enumerates hardware. 没有足够的声誉评论:我的有根据的猜测是,它与Linux枚举硬件的方式有关。 I think it's possible that your USB devices will have another serial-path depending on the used distro, and order of connecting them. 我认为您的USB设备可能会有另一个串行路径,具体取决于使用的发行版和连接顺序。

Are you sure that you use the same USB port every time? 您确定每次都使用相同的USB端口吗? And that the correct USB port is mapped to /dev/tty? 并且正确的USB端口映射到/ dev / tty?

You can force a HID to always have the same name by making sure you have a udev rule for it. 您可以通过确保具有相应的udev规则来强制HID始终具有相同的名称。 Some info here 这里有一些信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM