我正在以 921600 的波特率通过串行从微控制器读取数据。我正在读取大量 ASCII csv 数据,并且由于它来得如此之快,因此缓冲区已被填满,并且所有其余数据在之前都丢失了我可以阅读它。我知道我可以手动编辑 serialwin32 的 pyserial 源代码以增加缓冲区大小,但我想知道是否有另一种解决方法?
我只能估计我将收到的数据量,但它大约是 200kB 的数据量。
我正在以 921600 的波特率通过串行从微控制器读取数据。我正在读取大量 ASCII csv 数据,并且由于它来得如此之快,因此缓冲区已被填满,并且所有其余数据在之前都丢失了我可以阅读它。我知道我可以手动编辑 serialwin32 的 pyserial 源代码以增加缓冲区大小,但我想知道是否有另一种解决方法?
我只能估计我将收到的数据量,但它大约是 200kB 的数据量。
在将命令发送到 uC 以发送数据之前,您是否考虑过在单独的线程中从串行接口读取?
这将消除写入命令和开始读取之后的一些延迟。还有其他 SO 用户使用这种方法取得了成功,当然他们没有缓冲区溢出。
如果不清楚,请告诉我,我可以拼凑一些东西来展示这一点。
编辑
再想一想,如果您尝试从缓冲区读取并将其写入文件系统,即使独立线程也可能无法拯救您。为了尽量减少处理时间,您可以考虑一次读取 100 个字节,serial.Read(size=100)
并将该数据推送到队列中,以便在传输完成后处理所有数据
伪代码示例
def thread_main_loop(myserialobj, data_queue):
data_queue.put_no_wait(myserialobj.Read(size=100))
def process_queue_when_done(data_queue):
while(1):
if len(data_queue) > 0:
poped_data = data_queue.get_no_wait()
# Process the data as needed
else:
break;
有一个“接收缓冲区”滑块,可从设备管理器中 com 端口的属性页面访问。它可以通过“端口设置”选项卡上的“高级”按钮找到。
更多信息:
http://support.microsoft.com/kb/131016在标题接收缓冲区下
http://tldp.org/HOWTO/Serial-HOWTO-4.html在标题下的中断
尝试将其降低一两个档次。
您不需要手动更改 pyserial 代码。
如果你在 Windows 平台上运行你的代码,你只需要在你的代码中添加一行
ser.set_buffer_size(rx_size = 12800, tx_size = 12800)
其中 12800 是我选择的任意数字。您可以将接收(rx)和传输(tx)缓冲区设为 2147483647a
也可以看看:
https://docs.python.org/3/library/ctypes.html
https://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readbuffersize(v=vs.110).aspx
您也许可以从 DLL 设置串行端口 // 设置串行
mySerialPort.BaudRate = 9600;
mySerialPort.PortName = comPort;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.ReadBufferSize = 32768;
属性值 类型:System.Int32 缓冲区大小,以字节为单位。默认值为 4096;最大值是正整数,或 2147483647
然后在 Python 中打开并使用
令我有些惊讶的是,尚未有人提及此类问题的正确解决方案(如果可用),即通过软件 (XON/XOFF) 或微控制器与其接收器之间的硬件流控制进行有效的流控制。这篇网络文章很好地描述了这个问题。
可能是源设备不支持此类协议,在这种情况下,您会遇到一系列解决方案,这些解决方案将问题向上委托给更多可用资源的地方(将其从 UART 缓冲区移动到驱动程序并向上移动到您的应用代码)。如果您正在丢失数据,那么在可能的情况下尝试实施较低的数据速率当然是明智的。
对我来说,问题是从 Arduino 接收数据时缓冲区过载。我所要做的就是mySerialPort.flushInput()
它奏效了。
我不知道为什么mySerialPort.flush()
没有工作。flush()
必须只刷新传出数据?
我所知道的只是mySerialPort.flushInput()
解决了我的问题。