【问题标题】:serial communication anomaly in Linux?Linux中的串行通信异常?
【发布时间】:2012-10-03 04:17:48
【问题描述】:

我正在使用选择调用与使用串行端口 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 格式发送数据,每个数据包作为以回车、换行组合结尾的数据字符串。

任何想法的家伙可能是什么问题?

【问题讨论】:

  • 你需要更清楚;我不清楚接收系统是否连接到同一端口上的所有五个子系统,或者它们是否都有一个专用的串行端口。我会假设后者,因为串行端口是点对点的并且不容易共享,但是在问题中明确说明会很好。

标签: c++ qt serial-port


【解决方案1】:

“.Net 实时”位是红鲱鱼。串行端口非常慢,以至于 8086 可以控制它们。任何现代 CPU 都可能有空闲周期,即使是 115200 波特。即使没有,RS232 缓冲区的深度通常以毫秒而不是小时为单位测量。

串行端口的“堵塞”将物理类比推得太远了。

由于您实际上并没有告诉我们是什么原因,因此很难确切地弄清楚是什么导致了您的问题。 “崩溃”不是我们能解决的。字节丢失,写入超时 - 这是我们可以解决的具体行为。

【讨论】:

    【解决方案2】:

    我已经解决了这个问题。如果我无法理解我的观点,我深表歉意。早些时候,我们使用信号处理与连接到专用串行端口的每个系统进行串行接口,这种设计从一开始就存在缺陷,因为在我们的案例中信号处理程序太复杂了。理想情况下,信号处理程序应该只设置一些标志,它不应该涉及函数调用,因为可能存在要处理的同步问题,然后它会滚雪球进入同步噩梦,正如我在我的应用程序中发现的那样,这很难调试。这种设计会导致来自串行端口的数据包丢失。为了处理这种情况,我们使用了重置端口功能,这是一种纠正丢包问题的粗略方法。 我放弃了信号处理程序并为单个系统使用了选择调用。但没有放弃早期设计中的重置端口。在调试时,我发现resetport 是一个虚假函数并删除了它。瞧!!现在一切都很完美。 记录在案,我建议任何在 linux 平台上使用串行通信的人使用 select 系统调用。您无需处理串行通信的细节,只需专注于处理传入的数据包。

    我希望这个解决方案能够帮助所有在 linux/unix 平台上进行串行通信的人。关于这个主题的文献不多,网上的所有搜索都会引导您找到一些 mike 和 sweet 的文档,虽然这些文档很好,但在实际应用中并没有多大帮助。我感谢 stackoverlow 的所有成员提供的帮助,这给了我无法想象的视角来看待手头的问题。谢谢大家,干杯!!!!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-12
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2017-08-13
      相关资源
      最近更新 更多