Linux 奇偶校验的stty串行端口设置不持久

Linux 奇偶校验的stty串行端口设置不持久,linux,serial-port,stty,9-bit-serial,Linux,Serial Port,Stty,9 Bit Serial,我有一个netcore应用程序,它打开串行端口,一旦检测到奇偶校验错误,就会在控制台上写入“奇偶校验错误”。它在Windows10中运行良好,但无法在Linux下运行 我的假设是操作系统没有将奇偶校验错误传递给netcore 要检查我运行的端口设置,请执行以下操作: stty -D /dev/ttyS0 -ignpar inpck 然后我跑: stty -D /dev/ttyS0 -a 并且设置似乎如预期的那样正确设置(-ignpar inpck) 然后我运行netcore 3应用程序,但

我有一个netcore应用程序,它打开串行端口,一旦检测到奇偶校验错误,就会在控制台上写入“奇偶校验错误”。它在Windows10中运行良好,但无法在Linux下运行

我的假设是操作系统没有将奇偶校验错误传递给netcore

要检查我运行的端口设置,请执行以下操作:

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) netcore运行时未将奇偶校验设置传递给驱动程序 (不太可能)
  • B) 操作系统正在忽略这些指令

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

      你知道有哪款linux应用程序可以对奇偶校验错误做出明确的反应吗

      以下C程序从串行终端读取行(即规范模式),并配置为检测标记(或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: %s\n", 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: %s\n", 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: %s\n", 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, %d\n", 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\"\n\n", buf);
              } else if (rdlen < 0) {
                  printf("Error from read: %d: %s\n", rdlen, strerror(errno));
              } else {  /* rdlen == 0 */
                  printf("Nothing read. EOF?\n");
              }               
              /* repeat read */
          } while (1);
      }
      
      该串行端口似乎不能传输奇偶校验的8位数据(11位帧),但似乎能够读取奇偶校验的8位数据

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


      当发送器配置为8位和奇偶校验空间(与程序匹配)时,PC程序读取“ABCDEFG\n”为:

      数据读取正确


      当发送器配置为8位偶数奇偶校验时,PC程序读取“ABCDEFG\n”为:

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

      请注意,当实际接收的数据为
      0xFF
      (无奇偶校验错误)时,termios会将该数据扩展为两个字节的
      0xFF 0xFF
      。因此,请注意,当下一个数据为
      0x00
      时,这不是错误指示。低读数
      0xFF 0xFF 0x00
      转换为实际数据
      0xFF 0x00


      但是当实际接收的数据是带有奇偶校验错误的
      0xFF
      时,read返回
      0xFF 0x00 0xFF
      (即没有与错误指示相结合的扩展)。

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

      你知道有哪款linux应用程序可以对奇偶校验错误做出明确的反应吗

      以下C程序从串行终端读取行(即规范模式),并配置为检测标记(或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: %s\n", 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: %s\n", 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: %s\n", 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, %d\n", 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\"\n\n", buf);
              } else if (rdlen < 0) {
                  printf("Error from read: %d: %s\n", rdlen, strerror(errno));
              } else {  /* rdlen == 0 */
                  printf("Nothing read. EOF?\n");
              }               
              /* repeat read */
          } while (1);
      }
      
      该串行端口似乎不能传输奇偶校验的8位数据(11位帧),但似乎能够读取奇偶校验的8位数据

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


      当发送器配置为8位和奇偶校验空间(与程序匹配)时,PC程序读取“ABCDEFG\n”为:

      数据读取正确


      当发送器配置为8位偶数奇偶校验时,PC程序读取“ABCDEFG\n”为:

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

      请注意,当实际接收的数据为
      0xFF
      (无奇偶校验错误)时,termios会将该数据扩展为两个字节的
      0xFF 0xFF
      。因此,请注意,当下一个数据为
      0x00
      时,这不是错误指示。低读数
      0xFF 0xFF 0x00
      转换为实际数据
      0xFF 0x00

      但是,当实际接收的数据是带有奇偶校验错误的
      0xFF
      时,read返回
      0xFF 0x00 0xFF
      (即,没有与错误指示相结合的扩展)。

      “我如何强制我的应用程序使用inpck fuse运行…”——它不是“fuse”,通常只可编程一次。termios手册页将INPCK及其种类称为“常量”、“标志”和“属性”。因此,请使用适当的术语,并选择这三种术语中的任意一种,而不是“fuse”。stty命令只是shell中利用termios API的一种方法。应用程序应使用termios API根据sit的确切要求配置串行终端
      Read 8: 0x41 0x42 0x43 0x44 0x45 0x46 0x47 0xa
          "ABCDEFG."
      
      Read 14: 0x41 0x42 0xff 0x0 0x43 0x44 0xff 0x0 0x45 0xff 0x0 0x46 0x47 0xa
          "AB�.CD�.E�.FG."