我正在尝试通过串口(/ dev / ttyS0)从我的Ubuntu机器重复发送数据到RS232-CAN适配器。该消息包含19个字节的数据,每秒发送约4次。在运行的前5-20分钟内,一切都表现正常,但突然发送停止并且write()调用将继续填充输出缓冲区,直到它超过4096字节,此时write()调用开始失败。
仅当通过属性标志CRTSCTS启用硬件流控制时才会出现此问题。起初我认为问题是CTS线路发出停止信号,但在程序运行时检查此标志始终显示为ON。事实上,在发送停止发生的那一点上,没有一个调制解调器控制标志会发生变化。
数据发送停止是突然的,一旦发生,在重新启动程序之前不会再发送任何数据。我尝试在write()之后使用select()(在发送停止后总是超时)和tcdrain()(发送停止后永远阻塞)。数据内容也无关紧要。我已经尝试发送格式正确的CAN消息和随机垃圾,但问题出现了。
另一端的设备配置为使用硬件流量控制,我尝试使用115200和57600的波特率。我不知道还有什么可以检查可能导致问题。在启用RTS / CTS时是否还有其他步骤或配置设置?打开RTS / CTS会增加我不考虑的额外检查吗?
代码
int SetAttributes (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tcgetattr", errno);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_iflag &= ~IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 5;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag |= (CLOCAL | CREAD);
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag |= parity;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag |= CRTSCTS;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf ("error %d from tcsetattr", errno);
return -1;
}
return 0;
}
void SetBlocking (int fd, int block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf ("error %d from tggetattr", errno);
return;
}
tty.c_cc[VMIN] = block ? 1 : 0;
tty.c_cc[VTIME] = 5;
if (tcsetattr (fd, TCSANOW, &tty) != 0)
{
printf ("error %d from tcsetattr", errno);
}
}
int main(int argc, char** argv)
{
char *portname = "/dev/ttyS0";
int bytesInBuffer = 0;
int bytesWritten = 0;
int modemControlBits = 0;
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
printf ("error %d opening %s: %s", errno, portname, strerror (errno));
return -1;
}
SetAttributes (fd, B57600, 0);
SetBlocking (fd, 0);
if (tcflush(fd, TCIOFLUSH) == -1)
{
printf("error %d flushing: %s\n", errno, strerror(errno));
return -1;
}
while (true)
{
bytesWritten = write (fd, "NineteenCharacters!", 19);
printf("TX: NineteenCharacters!\n");
ioctl(fd, TIOCOUTQ, &bytesInBuffer);
printf("Bytes Written: %d --- Bytes Left in Buffer: %d\n", bytesWritten, bytesInBuffer);
ioctl(fd, TIOCMGET, &modemControlBits);
printf("Serial Control Bits - LE:%02x - DTR:%02x - RTS:%02x - ST:%02x - SR:%02x- CTS:%02x - DCD:%02x - RNG:%02x - DSR:%02x\n",
(TIOCM_LE & modemControlBits), (TIOCM_DTR & modemControlBits), (TIOCM_RTS & modemControlBits), (TIOCM_ST & modemControlBits),
(TIOCM_SR & modemControlBits), (TIOCM_CTS & modemControlBits), (TIOCM_CAR & modemControlBits), (TIOCM_RNG & modemControlBits),
(TIOCM_DSR & modemControlBits));
usleep (250000);
}
return 0;
}
问题开始时的控制台输出
Bytes Written: 19 --- Bytes Left in Buffer: 19
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 19
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 19
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 22
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 41
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 60
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 79
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100
TX: NineteenCharacters!
Bytes Written: 19 --- Bytes Left in Buffer: 98
Serial Control Bits - LE:00 - DTR:02 - RTS:04 - ST:00 - SR:00- CTS:20 - DCD:40 - RNG:00 - DSR:100