简体   繁体   中英

Raspberry: How to check remaining bytes in serial port's write buffer

What I'm doing:

Implementing RS-485 protocol, I have to:

  1. Set a write pin to high and go into write mode .
  2. Write my data (of 16 bytes length) to serial port.
  3. Set my pin to low again and go into read mode .
  4. Wait until 16 bytes have arrived.
  5. End transmission.

The details including why a write pin must be set to high and low, why 16 packets exactly, and ... are some hardware implementation details I can not change.


Current solution:

// .....

private final Serial serial;
private final GpioPinDigitalOutput pin;
private final long DELAY_M = 2;
private final int DELAY_N = 0

// .....

public boolean send(final byte[] packet) {

  result = false;

  try {
      this.pin.high();
      this.serial.write(packet);
      Thread.sleep(DELAY_M, DELAY_S); // -> THE TROUBLE MAKER
      this.pin.low();
      result = true;
  }

  // ... Now in read mode, recv 16 bytes in a pre-defined time window

  return result;


The problem

Before I go into read mode (setting the pin to low ) I must wait till all data in the serial buffer is transmitted. I am using Pi4J library and it has no facility for checking the remaining bytes in buffer. The dirty solution is to wait a constant DELAY_M milliseconds BUT this constant time changes in different environments, different hardware and ...

Looking into Pi4J's code, in native implementations (JNI) it's calling WiringPi's API. WiringPi in turn treats the serial port as a regular linux file and writes into the file. Again, WiringPi provides no method to check the remaining bytes in buffer. Then it must be a Linux-Hardware-Kernely thing and not necessarily Pi4j's responsibility. So: How do you check remaining data in raspberry's serial port buffer? wich is /dev/ttyAMA0

PS: the serial interface in Pi4j has a method flush() with this documentation:

Forces the transmission of any remaining data in the serial port transmit buffer. Please note that this does not force the transmission of data, it discards it!

Update:

Regarding what @sawdust pointed out in comments, I've found this tutorial. It enables what's called RTS and CTS (more about these flags here and here ) BUT it is not working yet. My oscilloscope shows no signal on CTS and RTS pins.

Also note that the article dates back to 2013 and gpio_setfunc wont even compile. It needs some strange scripts not available anywhere. But do look in apt-get packages list with apt-cache search gpio and you'll find the required tools.

You can hold the receive enable low which means you receive your own transmission. That way you know when the transmission is complete and can then take Tx enable low. Then just filter your transmission from the response.

eg. for your transmit routine:

 synchronized(mutex) {
     transmitEnable.high();
     awaitingEcho = true;
     expectedEcho = "test\n";
     serial.writeln("test");
 }

and the receive:

synchronized(mutex) {
    data = event.getAsciiString();
    if (awaitingEcho && data.contains(expectedEcho)) {
        transmitEnable.low();
        data = data.replace(expectedEcho, EMPTY);
        expectedEcho = null;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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