如何在C中读/写串口数据,打开功能问题

时间:2016-03-26 03:29:03

标签: c arduino serial-port

我尝试使用C来读取和写入串行端口的数据。我一直在使用我在网上找到的一个小测试程序。这个想法是让它向arduino发送一个字节,然后返回字符串" Hello",由程序读取。我正在使用open函数遇到打开串口的问题。我的代码在这一点上停滞不前,没有进一步。

  fd = open("/dev/tty.usbserial-AH02OC4V", O_RDWR | O_NOCTTY);
  printf("fd opened as %i\n", fd);
  printf("Serial Open Passed!\n");

谁能明白为什么?我在open函数后直接添加了一个printf函数来测试它是否正在完成。我正在使用Mac。完整的代码如下。

C:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <sys/ioctl.h>

#define DEBUG 1

int main(int argc, char *argv[])
{
  printf("start\n");
  int fd, n, i;
  char buf[64] = "temp text";
  struct termios toptions;
  printf("start\n");
  /* open serial port */
  fd = open("/dev/tty.usbserial-AH02OC4V", O_RDWR | O_NOCTTY);
  printf("fd opened as %i\n", fd);
  printf("Serial Open Passed!\n");
  /* wait for the Arduino to reboot */
  usleep(3500000);

  /* get current serial port settings */
  tcgetattr(fd, &toptions);
  /* set 9600 baud both ways */
  cfsetispeed(&toptions, B9600);
  cfsetospeed(&toptions, B9600);
  /* 8 bits, no parity, no stop bits */
  toptions.c_cflag &= ~PARENB;
  toptions.c_cflag &= ~CSTOPB;
  toptions.c_cflag &= ~CSIZE;
  toptions.c_cflag |= CS8;
  /* Canonical mode */
  toptions.c_lflag |= ICANON;
  /* commit the serial port settings */
  tcsetattr(fd, TCSANOW, &toptions);

  /* Send byte to trigger Arduino to send string back */
  write(fd, "0", 1);
  /* Receive string from Arduino */
  n = read(fd, buf, 64);
  /* insert terminating zero in the string */
  buf[n] = 0;

  printf("%i bytes read, buffer contains: %s\n", n, buf);

  if(DEBUG)
    {
      printf("Printing individual characters in buf as integers...\n\n");
      for(i=0; i<n; i++)
    {
      printf("Byte %i:%i, ",i+1, (int)buf[i]);
    }
      printf("\n");
    }

  return 0;
}

Arduino的:     void setup()     {       Serial.begin(9600);     }

void loop()
{
  if (Serial.available() > 0)
  {
    Serial.println("Hello");
    Serial.read();
  }
}

3 个答案:

答案 0 :(得分:0)

就open()而言,你的代码对我来说是正确的。

我相信open()会阻塞,直到另一端可用。它正在等待驾驶员承认可以进行通话,直到那时它耐心等待(固执地)。确保您连接的设备已启动并准备好进行通信。

你也可以尝试标记O_NONBLOCK,它可以设置errno来检查open()失败的原因。

答案 1 :(得分:0)

您可能已经找到了解决方法,但是,如果没有找到答案,则可以找到解决方法:

当连接打开时,@ t-johnson指出,open()函数将等待ACK字节。

我修改了您的Arduino代码:

void setup() {
    Serial.begin(9600);
    Serial.write(0x01); // I just send back 0x01 as a ACK byte
}
void loop() {
    if (Serial.available() > 0) {
        Serial.println("Hello");
        Serial.read();
    }
}

我还必须在打开函数中添加O_NONBLOCK标志。

我希望它能有所帮助!

答案 2 :(得分:0)

您需要添加O_NDELAY标志才能打开-在某些硬件平台(UART芯片)上,它可以防止在串行open()行未处于正常状态时“挂起” DCD调用。不幸的是,该标志会影响非规范模式下的read()行为,但是也有解决方案:特定的fcntl()调用。

因此,请尝试以下操作:

// use NDELAY flag
fd = open("/dev/tty.usbserial-AH02OC4V", O_RDWR | O_NOCTTY | NDELAY);
if (fd < 0) {
    // handle open error here
}

// fcntl() call to get read() working properly in non-canonical mode
fcntl(fd, F_SETFL, 0);