使用Linux和C读取串行端口时出现不一致问题。
我用来配置串行端口的代码是这样的:
serial = open("/dev/ttymxc1", O_RDWR | O_NOCTTY | O_SYNC); //Open in non blocking read/write mode
if (serial == -1)
{
//ERROR - CAN'T OPEN SERIAL PORT
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
}
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (serial, &tty) != 0)
{
printf("error from tcgetattr");
return -1;
}
cfsetospeed (&tty, B115200);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars
// disable IGNBRK for mismatched speed tests; otherwise receive break
// as \000 chars
//tty.c_iflag &= ~IGNBRK; // disable break processing
tty.c_lflag = 0; // no signaling chars, no echo,
// no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~(PARENB | PARODD); // shut off parity
tty.c_cflag |= 0;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
if (tcsetattr (serial, TCSANOW, &tty) != 0)
{
printf("error from tcsetattr");
return -1;
}
然后我使用以下代码(从配置串行端口的同一线程)轮询UART:
while(1)
{
if (serial != -1)
{
//memset(rx, 0, sizeof(rx));
int rx_length = read(serial, &rx, MAX_TXRX_BUF); //Filestream, buffer to store in, number of bytes to read (max)
if(rx_length > 0){
//Bytes received
//rx[rx_length] = '\0';
printf("1) %i bytes read : %s\n", rx_length, rx);
//forward_data(rx, rx_length);
printf("2) %i bytes read : %s\n", rx_length, rx);
//tcflush(serial, TCIOFLUSH);
}
// else: NO DATA
}
else{
fprintf(stderr, "TEST: %s SERIAL FAIL\n", __func__);
releaseUart();
}
}
问题在于此打印:
printf("1) %i bytes read : %s\n", rx_length, rx);
始终工作并打印从串行读取的正确数据。 在第二次打印时:
printf("2) %i bytes read : %s\n", rx_length, rx);
位于第一个字符的正下方,有时可以工作,而其他项目只是打印一个未知字符。
下面,我向您展示输出,但在这种情况下有效,在无效的情况下:
正确:
1) 2 bytes read : gv
2) 2 bytes read gv
错误:
1) 2 bytes read : gv
2) 2 bytes read: �
为什么即使两张照片都比另一张照片低,有时在打印SAME缓冲区时也会出现这种不一致的情况?
非常感谢您的帮助。
最好的问候, 马可
答案 0 :(得分:1)
我无法解释为什么输出在第一个printf
和第二个之间变化。但是,read
不会NUL终止其缓冲区,这意味着在您这样做之后
int rx_length = read(serial, &rx, MAX_TXRX_BUF);
您没有在rx
中没有有效的C字符串。您需要执行以下操作:
char rx[MAX_TXRX_BUF + 1]; // extra space for terminator
ssize_t rx_length = read(serial, rx, MAX_TXRX_BUF);
if (rx_length >= 0) {
rx[rx_length] = '\0';
// use rx here
// if rx_length == 0, handle EOF
} else {
// read error
}
即使我不知道为什么输出会发生变化,但我预计如果将两个printf
放在我有// use rx here
的位置,它们将始终打印相同的内容。
像使用&rx
一样,获取整个数组的地址几乎总是一个错误。在大多数情况下,为了引用C中的数组,您真正想要的是第一个元素的地址,这就是您仅用rx
获得的地址。 (由于过于繁琐和切线的原因,read
不在乎您提供它的两个之一,但是在其他情况下,它可能导致细微的错误。因此,C的最佳实践是使用即使没有关系的情况下,第一个元素的地址也要保留;在特殊情况下确实需要整个数组的地址的情况下,请保留&rx
。)