Raspberry:如何检查串口写缓冲区中的剩余字节

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

我在做什么:

实施 RS-485 协议,我必须:

  1. 写入引脚设置为high并进入写入模式
  2. 将我的数据(16字节长)写入串口。
  3. 再次将我的密码设置为 low 并进入 阅读模式
  4. 等到 16 个字节到达。
  5. 传输结束。

详细信息包括为什么写入引脚必须设置为高电平和低电平,为什么恰好是 16 个数据包,以及......是一些我无法更改的硬件实现细节。


当前解决方案:

// .....

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;


问题

在我进入读取模式之前(将pin设置为low)我必须等到串行缓冲区中的所有数据都被传输。我正在使用 Pi4J 库,它没有检查缓冲区中剩余字节的工具。肮脏的解决方案是等待常数 DELAY_M 毫秒,但这个常数时间会在不同的环境、不同的硬件和...

中发生变化

查看 Pi4J 的代码,在本机实现 (JNI) 中它调用 WiringPi 的 API。 WiringPi 依次将串行端口视为常规 linux 文件并写入文件。同样,WiringPi 没有提供检查缓冲区中剩余字节的方法。那么它一定是 Linux-Hardware-Kernely 的东西,不一定是 Pi4j 的责任。那么:如何查看树莓派串口缓冲区中的剩余数据呢?这是 /dev/ttyAMA0

P.S: Pi4j 中的串行接口有一个方法 flush() 和这个文档:

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!

更新:

关于@sawdust 在评论中指出的内容,我发现 this tutorial. It enables what's called RTS and CTS (more about these flags here and here) 但它还没有用。我的示波器在 CTS 和 RTS 引脚上没有显示信号。

另请注意,the article 可以追溯到 2013 年,gpio_setfunc 甚至无法编译。它需要一些在任何地方都找不到的奇怪脚本。但是请查看带有 apt-cache search gpio 的 apt-get 包列表,您会找到所需的工具。

您可以将接收启用保持在低电平,这意味着您可以接收自己的传输。这样您就知道传输何时完成,然后可以将 Tx 使能设为低电平。然后从响应中过滤您的传输。

例如。对于您的传输例程:

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

和接收:

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