Raspberry:如何检查串口写缓冲区中的剩余字节
Raspberry: How to check remaining bytes in serial port's write buffer
我在做什么:
实施 RS-485 协议,我必须:
- 将写入引脚设置为
high
并进入写入模式。
- 将我的数据(16字节长)写入串口。
- 再次将我的密码设置为
low
并进入 阅读模式。
- 等到 16 个字节到达。
- 传输结束。
详细信息包括为什么写入引脚必须设置为高电平和低电平,为什么恰好是 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;
}
}
我在做什么:
实施 RS-485 协议,我必须:
- 将写入引脚设置为
high
并进入写入模式。 - 将我的数据(16字节长)写入串口。
- 再次将我的密码设置为
low
并进入 阅读模式。 - 等到 16 个字节到达。
- 传输结束。
详细信息包括为什么写入引脚必须设置为高电平和低电平,为什么恰好是 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;
}
}