1

我是 linux 编程的新手。我按照网络上的示例读取/写入控制台,例如“/dev/ttyS0”。每次我运行代码时,它都会退出而不提示用户编写输入。它还会扭曲终端提示符(换行符),我无法看到我正在输入的内容......这是我正在使用的代码:

int main(int argc, char** argv)
{
  struct termios tio;
  struct termios stdio;
  int tty_fd;
  /* fd_set rdset; */

  printf("Please start with %s /dev/ttyS0 (for example)\n",argv[0]);
  unsigned char mesg='D';

  memset(&stdio,0,sizeof(stdio));
  stdio.c_iflag=0;
  stdio.c_oflag=0;
  stdio.c_cflag=0;
  stdio.c_lflag=0;
  stdio.c_cc[VMIN]=1;
  stdio.c_cc[VTIME]=0;
  tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
  tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
  fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);       // make the reads non-blocking

  memset(&tio,0,sizeof(tio));
  tio.c_iflag=0;
  tio.c_oflag=0;
  tio.c_cflag=CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
  tio.c_lflag=0;
  tio.c_cc[VMIN]=1;
  tio.c_cc[VTIME]=5;

  tty_fd=open(argv[1], O_RDWR | O_NONBLOCK | O_NOCTTY);
  cfsetospeed(&tio,B115200);            // 115200 baud
  cfsetispeed(&tio,B115200);            // 115200 baud

  tcsetattr(tty_fd,TCSANOW,&tio);
  while (mesg != 'q') {
    if (read(tty_fd,&mesg,1)>0)        write(STDOUT_FILENO,&mesg,1);              // if new data is available on the serial port, print it out
    if (read(STDIN_FILENO,&mesg,1)>0)  write(tty_fd,&mesg,1);                     // if new data is available on the console, send it to the serial port
  }

  close(tty_fd);

  return(0);
}
4

1 回答 1

1

当您尝试使用更改 tty 参数的代码时,您应该使用保存和恢复参数的脚本来包装您对测试程序的调用,以防您的程序忽略这样做。

这可以这样做:

 $ SAVED_TTY=$(stty -g)          # save the good settings once
 $ ./a.out ; stty $SAVED_TTY     # restore than after each run of the program

-g选项stty使其将“腌制”的所有 tty 设置输出到字符串中,这可以作为将来调用的参数来stty恢复相同的设置。

(正确编写的 tty 操作程序在退出时会注意恢复终端设置,即使它们通过接收任何可以处理的致命信号而突然退出。)

至于如何回送写入到 tty 设备的内容的问题,tty 子系统本身并没有通用的功能。标准的 tty 行规则模块可以将输入的字符回显到输出,这样当用户使用面向行的程序时,他们可以看到自己的打字,但没有软件环回,tty 设备会假装接收到它拥有的某些字符刚发送。

但是,某些串行硬件能够进行硬件环回:本质上是将 UART TX 线连接到 RX 线以进行测试。

Linux tty 支持调制解调器控制 ioctl,如果硬件支持,可以使用它来打开和关闭它。这采用ioctlsTIOCMGET的形式。TIOCMSET这些 ioctl 使用的值是各种掩码的逻辑 OR,其中之一是TIOCM_LOOP.

所以,我相信设置硬件环回是这样的:

unsigned int modem_control_bits;

result = ioctl(tty_descriptor, TIOCMGET, &modem_control_bits);
/* check result for error, of course */

modem_control_bits |= TIOCM_LOOP; /* request loopback from serial port */

result = ioctl(tty_descriptor, TIOCMSET, &modem_control_bits);
/* check result for error */

不清楚是不是每个串口驱动被要求设置都会报错TIOCM_LOOP,但是硬件不支持。(我不认为仅仅因为结果为零,它就一定有效)。

还有其他一些TIOCM_*位,因此您可以执行标准操作,例如打开和关闭 DTR,或者检测振铃指示灯是否亮起等等。

于 2013-05-14T20:06:59.577 回答