Serial Port BytesToRead and readbuffer
本文关键字:readbuffer and BytesToRead Port Serial | 更新日期: 2023-09-27 17:53:30
我正试图以非常快的速度连续从串行端口获取数据。波特率为"230400
"。当我将数据,时间戳和BytesToRead
打印到文件中时,我注意到每当BytesToRead
下降到个位数并且readLine()
没有在200ms中读取任何内容时,都会发生200ms的延迟。延迟之后,BytesToRead
回到3000左右,这个过程一次又一次地发生。从本质上讲,我没有连续地获取数据。
我想也许我的阅读速度比缓冲区中积累的速度数据快,所以我尝试改变readBuffer大小,并将此线程休眠1ms,以便让缓冲区保持我正在阅读的速度。没有一个成功。还有一些延误。
欢迎有任何想法。
private void dostuff()//The thread I created after the port is opened
{
var startTime = DateTime.Now;
var stopwatch = Stopwatch.StartNew();
while (serialPortEncoder.IsOpen)
{
if (serialPortEncoder.BytesToRead > 210)
{
try
{
var line = serialPortEncoder.ReadLine();
var timestamp = (startTime + stopwatch.Elapsed);
var lineString = string.Format("{0} ----{1}",
line,
timestamp.ToString("HH:mm:ss:fff") + " "+serialPortEncoder.BytesToRead+"'r'n");
richTextBoxEncoderData.BeginInvoke(new MethodInvoker(delegate()
{
richTextBoxEncoderData.Text = line;//update UI
}));
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
}}
除非每210字节换行一次,否则您的ReadLine()函数可能超时并且不返回任何内容。ReadLine()将读取输入缓冲区,直到遇到换行值,然后返回它之前的数据。http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readline.aspx
什么样的信息正在通过端口?如果您想读取特定大小的缓冲区,只需使用Read
方法。如果你需要一直读到换行,使用ReadLine()并经常检查它是否返回一个字符串。
你的代码从根本上是有缺陷的,它遭受了"热等待循环"的错误。当串行端口没有足够的数据时,您的循环正在燃烧100%核心。这将使Windows在你烧毁量子后把你的线程关在狗屋里一段时间,给其他线程一个运行的机会。在狗窝里呆200毫秒是有点长,但肯定不是不寻常的。
你应该做不同的,你应该给Windows一个机会,当有实际的数据可用从串行端口唤醒你。当它寻找下一个要调度的线程时,它倾向于已经完成I/O的线程。这很容易做到,只需删除BytesToRead测试。ReadLine()调用是一个阻塞调用,在接收到换行符之前不会返回。你的线程现在将消耗接近0%的cpu周期。
当机器负载过重或垃圾收集器运行时,您仍然会损失任意数量的时间。不,这还不足以可靠地读取编码器并关闭反馈回路。要做到这一点,需要一个具有可预测实时行为的微控制器。可从工业电子产品供应商处获得。
在网上进行了无休止的研究之后,我找到了延迟的原因。设备管理器->端口---->advance---->将延迟更改为1ms将解决问题。现在,每次当缓冲区下降到零时,它只需要最多2ms就能恢复正常。我现在使用一个单独的线程轮询数据。它工作得很好。
但就像汉斯·帕桑特说的,我正在努力找出一个更好的设计方法。