STTY 偶校验串行端口设置不持久



>我有一个 netcore 应用程序,可以打开串行端口,一旦检测到奇偶校验错误,就会在控制台上写入"奇偶校验错误"。它在Windows 10中运行良好,但无法使其在Linux下工作。

我的假设是操作系统没有将奇偶校验错误传递给网络核心。

为了检查我运行的端口设置:

stty -D /dev/ttyS0 -ignpar inpck

然后我运行:

stty -D /dev/ttyS0 -a 

并且设置似乎按预期正确设置(-ignpar inpck)。

然后我运行我的 netcore 3 应用程序,但没有检测到奇偶校验错误。

所以我跑

stty -D /dev/ttyS0 -a 

用于验证设置,但这些设置似乎已重置(-ignpar -inpck)

如何强制我的应用在启用 inpck 属性的情况下运行?
有没有办法使 inpck 默认启用?

谢谢。

更新:netcore 3应用程序奇偶校验错误检测在Windows 10中工作正常,但在Linux下不起作用。我的假设是:

  • A) 网络核心运行时未将奇偶校验设置传递给驱动程序 (不太可能)
  • B) 操作系统忽略了这些说明。

stty命令只是 shell 中利用 termios API 的一种方法。
应用程序应使用termios API根据情况的确切要求配置串行终端(而不是依赖于启动时的预期配置)。
如果您使用的应用程序环境不允许访问 termios API,则您可能使用了不适当的方法。

你知道任何可以以某种方式对奇偶校验错误做出明确反应的 linux 应用程序吗?

以下 C 程序从串行终端读取行(即规范模式),并配置为检测 Mark(或 1)作为具有 8 位字符帧的奇偶校验位。

#define SERIALTERMINAL      "/dev/ttyS0"
#include <errno.h>
#include <fcntl.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
int set_interface_attribs(int fd, int speed)
{
struct termios tty;
if (tcgetattr(fd, &tty) < 0) {
printf("Error from tcgetattr: %sn", strerror(errno));
return -1;
}
cfsetospeed(&tty, (speed_t)speed);
cfsetispeed(&tty, (speed_t)speed);
tty.c_cflag |= CLOCAL | CREAD;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;         /* 8-bit characters */
tty.c_cflag |= PARENB;      /* enable parity */
tty.c_cflag &= ~PARODD;     /* Even parity */
tty.c_cflag |= CMSPAR;      /* force Even parity to SPACE */
tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */
tty.c_lflag |= ICANON | ISIG;  /* canonical input */
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | IEXTEN);
tty.c_iflag &= ~IGNCR;  /* preserve carriage return */
tty.c_iflag &= ~(INLCR | ICRNL | IUCLC | IMAXBEL);
tty.c_iflag &= ~(IXON | IXOFF | IXANY);   /* no SW flowcontrol */
tty.c_iflag |= IGNBRK;  /* ignore breaks */
tty.c_iflag &= ~ISTRIP;
tty.c_iflag &= ~IGNPAR; /* report error */
tty.c_iflag |= INPCK;   /* test parity */
tty.c_iflag |= PARMRK;  /* verbose parity err */
tty.c_oflag &= ~OPOST;
tty.c_cc[VEOL] = 0;
tty.c_cc[VEOL2] = 0;
tty.c_cc[VEOF] = 0x04;
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
printf("Error from tcsetattr: %sn", strerror(errno));
return -1;
}
return 0;
}

int main(void)
{
char *portname = SERIALTERMINAL;
int fd;
int wlen;
fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0) {
printf("Error opening %s: %sn", portname, strerror(errno));
return -1;
}
/*baudrate 115200, 8 bits, Space for parity, 1 stop bit */
set_interface_attribs(fd, B115200);
/* simple output */
wlen = write(fd, "Hello!n", 7);
if (wlen != 7) {
printf("Error from write: %d, %dn", wlen, errno);
}
tcdrain(fd);    /* delay for output */

/* simple canonical input, read lines */
do {
unsigned char buf[81];
unsigned char *p;
int rdlen;
rdlen = read(fd, buf, sizeof(buf) - 1);
if (rdlen > 0) {
buf[rdlen] = 0;
printf("Read %d:", rdlen);
/* first display as hex numbers then ASCII */
for (p = buf; rdlen-- > 0; p++) {
printf(" 0x%x", *p);
if (*p < ' ')
*p = '.';   /* replace any control chars */
}
printf("n    "%s"nn", buf);
} else if (rdlen < 0) {
printf("Error from read: %d: %sn", rdlen, strerror(errno));
} else {  /* rdlen == 0 */
printf("Nothing read. EOF?n");
}               
/* repeat read */
} while (1);
}

该程序是在具有内置16550A串行端口的旧Linux(Ubuntu 14.04.2 LTS)PC上执行的。

[    2.656593] 00:08: ttyS0 at I/O 0x3f8 (irq = 4, base_baud = 115200) is a 16550A

此串行端口似乎无法传输具有奇偶校验的 8 位(11 位帧),但似乎能够读取具有奇偶校验的 8 位。

串行数据从具有支持 9 位的 UART 的 SBC 生成。 使用示波器捕获帧,以确认 8S1 和 8E1 帧的长度为 11 位。
(FTDI USB 到 RS232 转换器在生成具有 8 位字符的所有奇偶校验配置时并不可靠。


当发送方配置为 8 位和奇偶校验空间(与程序匹配)时,PC 程序将"ABCDEFG"读取为:

Read 8: 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0xa
"ABCDEFG."

数据读取正确。


当发送方配置为 8 位和偶数奇偶校验时,PC 程序将"ABCDEFG"读取为:

Read 14: 0x41 0x42 0xff 0x0 0x43 0x44 0xff 0x0 0x45 0xff 0x0 0x46 0x47 0xa
"AB�.CD�.E�.FG."

读取(正确)标识三个字符,这些字符将标记而不是空格作为奇偶校验位。
每个带有"奇偶校验错误"的字符前面都有0xFF 0x00字节(即总共三个字节)。

请注意,当实际接收基准面0xFF(没有奇偶校验错误)时,termios 会将该基准面扩展到两个字节的0xFF 0xFF。 所以请注意,当下一个基准面0x00时,这不是错误指示。 IOW读数0xFF 0xFF 0x00转换为实际数据0xFF 0x00
但是,当实际接收基准面0xFF偶校验误差时,读取返回0xFF 0x00 0xFF(即没有扩展与误差指示相结合)。

最新更新