我正在使用select call与外部子系统(使用串行端口RS232提供并实现为Qt线程的协议)进行通信。我们没有外部系统的硬件,因此我们开发了使用.Net 2.0和C#的内部模拟器来模拟底层子系统硬件的行为。有5个不同的子系统与我们的应用程序通信。子系统的每个接口都实现为Qt线程。由于这不是实时应用程序,并且当我们使用模拟器进行通信时我们没有实际的硬件,所有系统都会发现24小时左右,之后通信会上下波动,最终所有通信都会中断,但是当我重新启动模拟器机器而不关闭我的应用程序时,事情变得没有问题。为什么会这样?
我的猜测是,因为.Net / C#不是实时框架,并且在模拟器运行24小时后,数据发送速率开始减慢,串口端口堵塞;重启会刷新所有内容,因此一切都恢复正常。这只是猜测。如果有人有更好的意见,请分享。注意,模拟器是由不同的.Net团队制作的。
注意:每种协议都有不同的数据速率,1 Hz,5 Hz,10 Hz。
有一个系统即使在重启后重新启动模拟器也不会恢复通信。该系统的端口配置为
SetPortConfiguration()
{
tcgetattr(Fd,&mOldtio);
mNewtio.c_cflag = B4800 | CS8 | CLOCAL | CREAD | CRTSCTS;
mNewtio.c_iflag = 0; //setting the input flag to icrnl causes a blank frame to be displayed after every frame.
mNewtio.c_oflag = 0;
mNewtio.c_lflag =ICANON;
mNewtio.c_cflag &=~PARENB;
mNewtio.c_cflag &= ~CSTOPB;
//mNewtio.c_cflag &= ~HUPCL; //added on 24/3/09
mNewtio.c_cc[VEOL]=0; //setting VEOL to '\r' or '\n' causes a blank frame to be displayed after every frame.
mNewtio.c_cc[VKILL] = 0; /* @ */
mNewtio.c_cc[VSTART] = 0; /* Ctrl-q */
mNewtio.c_cc[VSTOP] = 0; /* Ctrl-s */
mNewtio.c_cc[VMIN]=0;
mNewtio.c_cc[VTIME]=0;
tcflush(Fd, TCIFLUSH);
tcflow(Fd,TCION);
tcsetattr(Fd,TCSANOW,&mNewtio);
}
还有一个重置端口功能:
ResetPort()
{
tcflush(Fd, TCIFLUSH); //flush all data received but not read
tcflow(Fd,TCIOFF); //transmits a STOP character, which stops the terminal device from transmitting data to the system
tcsetattr(Fd, TCSANOW, &mOldtio);//set the old terminal settings
ClosePort(); //close port
OpenPort(mStrPortNo); //open the port specified by port number and in read mode
SetPortConfiguration();
}
如果通信中断,我会调用ResetPort函数关闭并重新打开端口。除了一个系统说XYZ之外,这解决了所有情况下的问题。 XYZ系统以NMEA格式发送数据,每个数据包作为以回车,LineFeed组合终止的数据串。
任何人都知道可能出现什么问题?
答案 0 :(得分:1)
“.Net实时”位是一个红色的鲱鱼。串口很慢,8086可以控制它们。任何现代CPU都可能有备用周期,即使是115200波特。即使没有,RS232缓冲区的深度通常以毫秒而非小时来度量。
串口的“堵塞”正在推动物理类比太过分了。
很难弄清楚究竟是什么导致了您的问题,因为您实际上并没有告诉我们这是什么。 “打破”不是我们可以解决的问题。字节丢失,写出时间 - 这是我们可以解决的具体行为。
答案 1 :(得分:0)
我已经解决了这个问题。如果我无法理解我的观点,我表示歉意。早些时候我们使用信号处理与连接到专用串行端口的每个系统进行串行接口,这种设计从一开始就存在缺陷,因为在我们的情况下信号处理程序过于复杂。理想情况下,信号处理程序应该只设置一些标志,它不应该涉及函数调用,因为可能存在要处理的同步问题,然后它会像我在我的应用程序中发现的那样陷入同步噩梦,很难调试。这种设计导致来自串行端口的数据包丢失。为了解决这种情况,我们使用了重置端口功能,这是一种解决丢包问题的粗略方法。 我放弃了信号处理程序并对单个系统使用了select调用。但是没有丢弃重置端口,这是早期设计的一部分。在调试时,我发现重置端口是一个虚假功能并丢弃它。瞧!现在一切都很完美。 记录在案,我建议任何在linux paltform上使用串行通信的人使用select系统调用。您无需处理串行通信的细节,只需专注于处理传入的数据包。
我希望这个解决方案能够帮助那些在linux / unix平台上进行串行通信的人。没有太多关于这个主题的文献,网上的所有搜索将引导你通过迈克和甜蜜的一些文件,虽然好在实际应用中没有太大帮助。我承认stackoverlow的所有成员提供的帮助给了我不可思议的观点来看待手头的问题。谢谢你们,欢呼!!!!!!