我正在尝试用C编写一个小程序,它将使用select命令从串口读取,以便它阻塞并等待输入。 它正在工作,除了它不断分裂线,我不知道为什么。 该设备的编程不会破坏线路,并且可以与实际的终端程序一起使用。 我之前从未在C中进行过串口通信,而且我在Mac上,所以这对我来说都是新手。 我真的不知道在哪里可以找到出错的地方。
我有一些代码可以找到并列出串口。 为了简单起见,我会把它留下来,所以如果有一个没有意义的变量,那可能就是原因。 以下是打开端口,设置属性并尝试从中读取的代码,以及来自Apple网站的复制注释(对不起):
/* this is based on a combination of https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c * and https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html */ static int OpenSerialPort(const char *deviceFilePath, int speed) { int fileDescriptor = -1; struct termios options; memset(&options, 0, sizeof(options)); // init it // Open the serial port read/write, with no controlling terminal, // and don't wait for a connection. // The O_NONBLOCK flag also causes subsequent I/O on the device to // be non-blocking. // See open(2) ("man 2 open") for details. fileDescriptor = open(deviceFilePath, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fileDescriptor == -1) { printf("Error opening serial port %s - %s(%d).n", deviceFilePath, strerror(errno), errno); goto error; } // Note that open() follows POSIX semantics: multiple open() calls to // the same file will succeed unless the TIOCEXCL ioctl is issued. // This will prevent additional opens except by root-owned processes. // See options(4) ("man 4 options") and ioctl(2) ("man 2 ioctl") for details. if (ioctl(fileDescriptor, TIOCEXCL) == kMyErrReturn) { printf("Error setting TIOCEXCL on %s - %s(%d).n", deviceFilePath, strerror(errno), errno); goto error; } // Set raw input (non-canonical) mode, with reads blocking until either // a single character has been received or a one second timeout expires. // See tcsetattr(4) ("man 4 tcsetattr") and termios(4) ("man 4 termios") // for details. cfmakeraw(&options); options.c_cc[VMIN] = 1; options.c_cc[VTIME] = 5; // The baud rate, word length, and handshake options can be set as follows: cfsetspeed(&options, speed); // Set 19200 baud options.c_cflag = (options.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as 00 chars options.c_iflag &= ~IGNBRK; // disable break processing options.c_lflag = 0; // no signaling chars, no echo, // no canonical processing options.c_oflag = 0; // no remapping, no delays options.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl options.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading options.c_cflag &= ~(PARENB | PARODD); // shut off parity options.c_cflag |= false; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CRTSCTS; // Cause the new options to take effect immediately. if (tcsetattr(fileDescriptor, TCSANOW, &options) == kMyErrReturn) { printf("Error setting options attributes %s - %s(%d).n", deviceFilePath, strerror(errno), errno); goto error; } // turn on blocking if (fcntl(fileDescriptor, F_SETFL, 0) == kMyErrReturn) { printf("Error clearing O_NONBLOCK %s - %s(%d).n", deviceFilePath, strerror(errno), errno); goto error; } // Success: return fileDescriptor; // Failure: error: if (fileDescriptor != kMyErrReturn) { close(fileDescriptor); } return -1; } int main(void) { int fileDescriptor; kern_return_t kernResult; // these are Apple-specific io_iterator_t serialPortIterator; // Apple char deviceFilePath[MAXPATHLEN]; fd_set fdset; // make a file descriptor set FD_ZERO (&fdset); // init it char buf[1000]; // some strings are big kernResult = GetDevices(&serialPortIterator); printf("Devices on this system:n"); kernResult = ListDevicePaths(serialPortIterator, deviceFilePath, sizeof(deviceFilePath)); IOObjectRelease(serialPortIterator); // Release the iterator. // Open the modem port, initialize the modem, then close it. if (!deviceFilePath[0]) { printf("No modem port found.n"); return EX_UNAVAILABLE; } fileDescriptor = OpenSerialPort("/dev/cu.usbmodem1d1111", B230400); FD_SET (fileDescriptor, &fdset); // add to file descriptor set // now we're going to use select to only read from the file handle when there's data available while (1) { if (select (FD_SETSIZE, &fdset, NULL, NULL, NULL) < 0) // this will block the program until something is on the line { printf("select errorn"); } read(fileDescriptor, buf, 1000); printf("%sn", buf); memset(buf, '