如何在Linux上正确设置串行通信

我试图读写FPGA板上的数据。 电路板本身带有一个驱动程序,在电路板插入时创build一个名为ttyUSB0的terminal设备。在FPGA上实现了一个asynchronous接收器和发送器,它们似乎工作正常。

但是,在C方面似乎存在一个问题。 我一直在使用一些testing向量来testingFPGA是否输出正确的信息。 我发现了一些事情:

  1. 设备有时无法正确打开
  2. terminal属性有时无法被检索或设置。
  3. 读取有时是非阻塞的,不会检索正确的值。

以下是我如何设置terminal和文件描述符选项。 其中很多是从这里采取: http : //slackware.osuosl.org/slackware-3.3/docs/mini/Serial-Port-Programming

对于为什么程序可能失败的任何build议或意见将是非常有帮助的。

#include <stdio.h> // Standard input/output definitions #include <string.h> // String function definitions #include <unistd.h> // UNIX standard function definitions #include <fcntl.h> // File control definitions #include <errno.h> // Error number definitions #include <termios.h> // POSIX terminal control definitions int open_port(void){ int fd; // File descriptor for the port fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); if (fd == -1){ fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno)); exit(EXIT_FAILURE); } return (fd); } int main(void){ int fd = 0; // File descriptor struct termios options; // Terminal options fd = open_port(); // Open tty device for RD and WR fcntl(fd, F_SETFL); // Configure port reading tcgetattr(fd, &options); // Get the current options for the port cfsetispeed(&options, B230400); // Set the baud rates to 230400 cfsetospeed(&options, B230400); options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode options.c_cflag &= ~PARENB; // No parity bit options.c_cflag &= ~CSTOPB; // 1 stop bit options.c_cflag &= ~CSIZE; // Mask data size options.c_cflag |= CS8; // Select 8 data bits options.c_cflag &= ~CRTSCTS; // Disable hardware flow control // Enable data to be processed as raw input options.c_lflag &= ~(ICANON | ECHO | ISIG); // Set the new attributes tcsetattr(fd, TCSANOW, &options); //////////////////////////////////// // Simple read and write code here// //////////////////////////////////// // Close file descriptor & exit close(fd) return EXIT_SUCCESS } 

更新我已经修改了我的代码根据第一个答案。 这是我现在所拥有的:

 #include <errno.h> // Error number definitions #include <stdint.h> // C99 fixed data types #include <stdio.h> // Standard input/output definitions #include <stdlib.h> // C standard library #include <string.h> // String function definitions #include <unistd.h> // UNIX standard function definitions #include <fcntl.h> // File control definitions #include <termios.h> // POSIX terminal control definitions // Open usb-serial port for reading & writing int open_port(void){ int fd; // File descriptor for the port fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); if (fd == -1){ fprintf(stderr, "open_port: Unable to open /dev/ttyUSB0 %s\n",strerror(errno)); exit(EXIT_FAILURE); } return fd; } int main(void){ int fd = 0; // File descriptor struct termios options; // Terminal options int rc; // Return value fd = open_port(); // Open tty device for RD and WR // Get the current options for the port if((rc = tcgetattr(fd, &options)) < 0){ fprintf(stderr, "failed to get attr: %d, %s\n", fd, strerror(errno)); exit(EXIT_FAILURE); } // Set the baud rates to 230400 cfsetispeed(&options, B230400); // Set the baud rates to 230400 cfsetospeed(&options, B230400); cfmakeraw(&options); options.c_cflag |= (CLOCAL | CREAD); // Enable the receiver and set local mode options.c_cflag &= ~CSTOPB; // 1 stop bit options.c_cflag &= ~CRTSCTS; // Disable hardware flow control options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 2; // Set the new attributes if((rc = tcsetattr(fd, TCSANOW, &options)) < 0){ fprintf(stderr, "failed to set attr: %d, %s\n", fd, strerror(errno)); exit(EXIT_FAILURE); } //////////////////////////////// // Simple Read/Write Code Here// //////////////////////////////// // Close file descriptor & exit close(fd); return EXIT_SUCCESS; } 

为了澄清,接收器和发送器使用8个数据位,1个停止位,并且没有奇偶校验位。

Solutions Collecting From Web of "如何在Linux上正确设置串行通信"

我更喜欢POSIX操作系统的串行编程指南 。

您应该删除fcntl(mainfd, F_SETFL)语句,因为它不是必需的,并且执行不正确(F_GETFL没有事先完成并缺少第三个参数)。

尝试使用cfmakeraw来设置非规范模式,因为你的初始化代码是不完整的:

 options->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); options->c_oflag &= ~OPOST; 

对于非规范模式,您还需要定义

 options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 2; 

1和2只是建议的值。

所有系统调用之后添加对返回状态的测试。

 rc = tcgetattr(mainfd, &options); if (rc < 0) { printf("failed to get attr: %d, %s\n", mainfd, strerror(errno)); exit (-3); } 

尝试使用较慢的波特率(例如115200甚至9600)进行测试。