VirtualBox 中 linux 上的串口从数据流中过滤掉 0x11
Serial port on linux in VirtualBox filters out 0x11 from data stream
不知道这个问题是VirtualBox的问题还是串口配置的问题。我正在测试一个通过串行端口与特定硬件交互的程序。一切正常,但在从设备接收的数据流中,某些字节未正确接收。特别是 0x11、0x13 丢失,0x0d 被接收为 0x0a。我有一个监视串行端口的串行嗅探器程序,在那里可以看到字节,但是在我的程序中没有看到它是 运行 在 VirtualBox linux 机器中。我需要查看所有没有流量控制的二进制字节。这是我打开串口的方式:
int openPort( char* portname )
{
int fd;
fd = open( portname, O_RDWR | O_NOCTTY | O_NDELAY );
if ( fd == -1 )
{
perror( "openPort():" );
printf( "Unable to open %s\n", portname );
}
else
{
fcntl( fd, F_SETFL, FASYNC );
struct termios my_termios;
struct termios new_termios;
tcgetattr( fd, &termios_save );
tcgetattr( fd, &my_termios );
cfsetispeed( &my_termios, B9600 );
cfsetospeed( &my_termios, B9600 );
my_termios.c_cflag &= ~( PARENB | CSTOPB | CSIZE );
my_termios.c_cflag |= ( CS8 | CREAD );
my_termios.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG );
my_termios.c_oflag &= ~OPOST;
my_termios.c_cc[VMIN] = 1;
my_termios.c_cc[VTIME] = 100; // wait 10 seconds for a character
tcsetattr( fd, TCSANOW, &my_termios );
tcgetattr( fd, &new_termios );
if ( memcmp( &my_termios, &new_termios, sizeof( my_termios ) ) != 0 )
{
printf( "Error setting serial port options, aborting\n" );
close( fd );
fd = -1;
}
}
return fd;
}
我已经看过各种使用串行端口的指南,包括 Serial Programming Guide for POSIX Operating Systems,这就是我想出的。
0x11
和 0x13
是 ASCII XON (DC1, Ctrl-Q)
和 XOFF (DC3, Ctrl-S)
的十六进制值,用于在性能有限的应用程序中提供数据流的步调。
主机串行端口或 VirtualBox 正在解释这些(或只是过滤它们以避免后续解释)。在主机中将端口设置为原始模式。你不说,但如果它是 *nix 的某种风格,那么 stty
可能会有所帮助。
显然我错过了指南中的一个部分。我最初是从一些我现在找不到的示例程序中复制我的初始化代码的,所以我不知道他们是否也遗漏了它,或者我是否在我的副本中遗漏了它。不管怎样,问题出在 c_iflag 的设置上,我最初并没有更改它。添加行:
my_termios.c_iflag &= ~( IXON | IXOFF | IXANY | ICRNL | INLCR | IGNCR );
处理问题。显然软件流控制和 CR->NL 映射是默认启用的。
不知道这个问题是VirtualBox的问题还是串口配置的问题。我正在测试一个通过串行端口与特定硬件交互的程序。一切正常,但在从设备接收的数据流中,某些字节未正确接收。特别是 0x11、0x13 丢失,0x0d 被接收为 0x0a。我有一个监视串行端口的串行嗅探器程序,在那里可以看到字节,但是在我的程序中没有看到它是 运行 在 VirtualBox linux 机器中。我需要查看所有没有流量控制的二进制字节。这是我打开串口的方式:
int openPort( char* portname )
{
int fd;
fd = open( portname, O_RDWR | O_NOCTTY | O_NDELAY );
if ( fd == -1 )
{
perror( "openPort():" );
printf( "Unable to open %s\n", portname );
}
else
{
fcntl( fd, F_SETFL, FASYNC );
struct termios my_termios;
struct termios new_termios;
tcgetattr( fd, &termios_save );
tcgetattr( fd, &my_termios );
cfsetispeed( &my_termios, B9600 );
cfsetospeed( &my_termios, B9600 );
my_termios.c_cflag &= ~( PARENB | CSTOPB | CSIZE );
my_termios.c_cflag |= ( CS8 | CREAD );
my_termios.c_lflag &= ~( ICANON | ECHO | ECHOE | ISIG );
my_termios.c_oflag &= ~OPOST;
my_termios.c_cc[VMIN] = 1;
my_termios.c_cc[VTIME] = 100; // wait 10 seconds for a character
tcsetattr( fd, TCSANOW, &my_termios );
tcgetattr( fd, &new_termios );
if ( memcmp( &my_termios, &new_termios, sizeof( my_termios ) ) != 0 )
{
printf( "Error setting serial port options, aborting\n" );
close( fd );
fd = -1;
}
}
return fd;
}
我已经看过各种使用串行端口的指南,包括 Serial Programming Guide for POSIX Operating Systems,这就是我想出的。
0x11
和 0x13
是 ASCII XON (DC1, Ctrl-Q)
和 XOFF (DC3, Ctrl-S)
的十六进制值,用于在性能有限的应用程序中提供数据流的步调。
主机串行端口或 VirtualBox 正在解释这些(或只是过滤它们以避免后续解释)。在主机中将端口设置为原始模式。你不说,但如果它是 *nix 的某种风格,那么 stty
可能会有所帮助。
显然我错过了指南中的一个部分。我最初是从一些我现在找不到的示例程序中复制我的初始化代码的,所以我不知道他们是否也遗漏了它,或者我是否在我的副本中遗漏了它。不管怎样,问题出在 c_iflag 的设置上,我最初并没有更改它。添加行:
my_termios.c_iflag &= ~( IXON | IXOFF | IXANY | ICRNL | INLCR | IGNCR );
处理问题。显然软件流控制和 CR->NL 映射是默认启用的。