我正在使用 Cygwin 环境来构建我的程序。我还使用 termius 库。本质上,程序打开串口:
fuart = open(device, O_RDWR | O_NOCTTY | O_SYNC);
然后它的工作流程涉及以这种方式写入串行端口:
write(fuart, str, xlen);
以及从中阅读:
ln = read(fuart, buff, n);
最后:
tcflush(fuart,TCIOFLUSH);
close(fuart);
sleep(2); //just in case
当我第一次运行该程序时,它运行得很好,但是当随后使用相同的输入数据启动时,它将挂在读取上。如果我在 Windows 设备管理器中禁用 COM 端口并重新启用它,那么下次运行时一切都会正常。 我想也许我的程序由于兼容性问题而无法正确关闭端口,并且它仍然处于锁定状态,但是其他终端软件(例如
teraterm
)可以打开它,更有趣的是,如果我尝试第二次运行我的程序并且它挂起,通过任务管理器强行关闭并打开第3方终端软件后,我可以看到它写入串口的数据。所以看起来我的 C 程序无法正确处理 COM 端口的关闭(或者可能刷新/释放读取缓冲区,因为它挂在读取操作上),这不是操作系统或平台问题。请注意,在其工作过程中,我的程序成功地多次读取和写入端口(但仅在第一次运行期间再次运行,之后我必须禁用-启用设备或打开另一个终端软件)。
作为参考,我通信的设备是 USB 调制解调器。
我尝试寻找答案,但运气不佳,除了找到关闭端口的建议,我已经这样做了。我看到有人在同一条船上,他们使用了启用-禁用技巧,但就像我说的我的研究据透露,其他终端程序没有这个错误,它们甚至有助于释放COM端口。我什至找到了一个使用 Cygwin 运行时的软件,即 mobastorm,并且它不会遇到这个问题。
您遇到的问题可能是由于使用
termios
结构初始化和配置串行端口设置不当造成的。当您在类 Unix 环境(例如 Cygwin)中打开串行端口时,每次正确设置端口以确保一致的行为至关重要。如果不这样做,可能会使端口处于不一致的状态,导致程序的后续运行在 read()
操作上挂起。
在执行任何读取或写入操作之前,应使用
termios
结构设置串行端口。这涉及:
tcgetattr()
检索当前端口设置。tcsetattr()
应用新设置。根据您的需求配置控制模式、本地模式、输入模式和输出模式。例如,如果您想要带超时的非阻塞读取,则可以在
VMIN
结构的 VTIME
数组中设置 c_cc
和 termios
值。
使用
tcflush()
清除输入和输出缓冲区中的所有数据。这可确保过时数据不会干扰新的读取或写入操作。
完成后,确保使用
close()
关闭串行端口。这会释放文件描述符并允许其他程序毫无问题地访问该端口。
始终检查系统调用的返回值,例如
open()
、read()
、write()
、tcgetattr()
和 tcsetattr()
。正确的错误处理可以防止您的程序进入不一致的状态。
为什么其他程序在强制关闭你的程序后还能工作:
Tera Term 等其他终端程序可能会在打开端口时重新初始化串行端口设置。它们重置以前程序留下的所有配置,这就是它们可以毫无问题地与串行设备通信的原因。通过在程序中正确设置串行端口,您可以模仿此行为并防止程序退出后端口保持不良状态。