简体   繁体   中英

How to read/write serial port data in C, issues with open function

I'm trying to use C to read and write data to the serial port. I've been working with a little test program I found online. The idea is for it to send a byte to an arduino, which will then return the string "Hello", which is read by the program. I'm running into issues opening the serial port, using the open function. My code is stalling at this point and not getting any further.

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

Can anyone see why? I added a printf function directly after the open function to test whether or not it is being completed. I am working on a Mac. Complete code is below.

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();
  }
}

Your code looks correct to me as far as the open() goes.

I believe that the open() will block until the other end is available. It is waiting for the driver to acknowledge that it is available to talk and until then it waits patiently (stubbornly). Make sure that the device you are connecting to is up and ready to communicate.

You can also try flag O_NONBLOCK which may set errno for you to check as to why the open() failed.

You might have found the answer to this already, but if you didn't I found a workaround:

When the connection opens, the open() function waits for an ACK byte as @t-johnson pointed out.

I modified your Arduino code to this:

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();
    }
}

I also had to add the O_NONBLOCK flag to the open function.

I hope it can help!

You need to add O_NDELAY flag to open - on some HW platforms (UART chips) it protects against "hanging" the open() call while serial DCD line is not in proper state. Unfortunately, this flag can affect read() behavior in non-canonical mode, but there is solution too: the specific fcntl() call.

So, try this:

// 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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM