select() and read() times out on serial port read yet previous write() succeeds?

六眼飞鱼酱① 提交于 2019-12-24 22:47:14

问题


After three weeks I can't get past this problem. I have the code below running on Ubuntu 18.04.3 which sends a string successfully to another device. When the remote device receives the string ... it sends another back ... but the code below (even with 1 sec set) times out on select().

When I comment out the select() and just do the read() ... fails to see any data as well?

It was working three weeks ago ... but recent code changes broke it ... and I cannot see why. How could a write() on a file descriptor go out the serial port ok ... but a select() and read() using the same file descriptor get nothing back. I have a third device (a PC with putty) so I can see everything on the wire. All three are on an RS-485 bus.

Any other issues with the code would be greatly appreciated!

Thanks!

// main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <term.h>
#include <signal.h>
#include <sys/time.h>

#include "SER.h"

static
struct  sigaction mySigActTerm;

volatile
int     terminate = 0;


void terminateHandler(int signum, siginfo_t *info, void *ptr)
{
  //------------------------------------------------------------
  // set a flag here and get out.
  terminate = 1;
}


int main()
{
  int       rtn;
  pthread_t serialThdID;
  SER*      mySER;

  //------------------------------------------------------------
  // setup terminate signal
  memset(&mySigActTerm, 0, sizeof(mySigActTerm));
  mySigActTerm.sa_sigaction = terminateHandler;
  mySigActTerm.sa_flags = SA_SIGINFO;

  sigaction(SIGTERM, &mySigActTerm, NULL);

  //------------------------------------------------------------
  // initialize the serial port.
  mySER = SERinit("/dev/ttyUSB0", 2);
  if (mySER == NULL)
  {
    fprintf(stderr, "main() - SERinit() returned NULL");
    exit(EXIT_FAILURE);
  }

  //------------------------------------------------------------
  // start the serial thread.
  rtn = pthread_create(&serialThdID, NULL, serialThread, mySER);
  if(rtn  == 0)
    fprintf(stderr, "starting serial thread.\n");
  else
  {
    fprintf(stderr, "main() - pthread_create() returned %d\n%s\n", rtn, strerror(errno));
    free(mySER);
    exit(EXIT_FAILURE);
  }

  //------------------------------------------------------------
  // wait till serialThread() indicates it is running.
  while (mySER->ThreadStatus != threadRuning)
  {
    fprintf(stderr, "waiting for thread running status.\n");
    sleep(1);
  }

  //------------------------------------------------------------
  // main loop here.
  while (terminate == 0)
  {
    // do stuff here.
  }

  //------------------------------------------------------------
  // tell the serial thread to stop.
  mySER->ThreadCtrl = threadCtrlKill;

  //------------------------------------------------------------
  // verify serial thread is dead!
  while (mySER->ThreadStatus != threadStopped)
  {

  }

  //------------------------------------------------------------
  // clean up.
  SERclose(mySER);
  free(mySER);
}


serialThread.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/time.h>
#include <term.h>
#include <inttypes.h>

#include "SER.h"



void*  serialThread(void* arg)
{
  char*   rtn;
  SER*  mySER = arg;

  mySER->tid = pthread_self();

  mySER->ThreadStatus = threadRuning;

  //  thread Loop!
  while(mySER->ThreadCtrl != threadCtrlKill)
  {
    rtn = SERwrapperFunc(mySER);
      // code to print the response here
    printf("%.*s\n", 8, rtn);
    sleep(30);
  }

  mySER->ThreadStatus = threadStopped;
  pthread_exit(NULL);
}

SERmaster.c

#define responseSize    4584

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
//#include <linux/serial.h>
//#include <aio.h>
#include <sys/time.h>

#include "SER.h"


// array used to get termios BAUD.
const
int       BAUDarray[9] = {  0,         // not used.
                            B4800,     // 208
                            B9600,     // 104
                            B19200,    //  52
                            B38400,    //  26
                            B57600,    //  17.363636
                            B115200,   //   8.727272
                            B230400,   //   4.363636
                            B460800    //   2.181818
                         };

// delay (in uS) per character transmitted.
//    1 start, Even parity, 7bits, 1 stop.
//    bit time (times 10 bits)
//    Plus one bit time between characters.
const
int       BAUDdelay[9] = {  0,         // not used.
                            2288,
                            1144,
                            572,
                            286,
                            191,
                            96,
                            48,
                            24
                         };

static    
char      response[4584];

static
unsigned  
int       respIndex;

static
struct    termios   newtio, oldtio;

extern
volatile
int       terminate;


static
int sendRecieve(SER* mySER, const char* msgBuffer, int msgCnt, int sendFlag, int receiveFlag)
{
  int       rtn;
  char      myChar;
  fd_set    myfds;

  struct
  timeval   tm_out;

  if (sendFlag == true)
  {
    while (1)
    {
      rtn = write(mySER->sfd, msgBuffer, msgCnt);
      if (rtn == -1)
      {
        if (errno == EINTR)
        {
          fprintf(stderr, "sendRecieve() - write() EINTR !\n");
          if (terminate == 1)
            break;                     // deal with SIGTERM !
          continue;                    // if not SIGTERM then retry.
        }
        else
        {
          fprintf(stderr, "sendRecieve() - write()\n%s\n", strerror(errno));
          return EXIT_FAILURE;
        }
      }
      else
      {
        if (rtn == msgCnt)
          break;
        else
        {
          fprintf(stderr, "sendRecieve() - write() returned less than msgCnt !\n");
          return EXIT_FAILURE;
        }
      }
    }
  }

  if (receiveFlag == true)
  {
    respIndex = 0;

    while (1)
    {
      tm_out.tv_sec  = 1;
      tm_out.tv_usec = mySER->BAUDmult * msgCnt;
      FD_ZERO(&myfds);
      FD_SET(mySER->sfd, &myfds);

      rtn = select(mySER->sfd + 1, &myfds, NULL, NULL, &tm_out);
      if (rtn == 0)
      {
        fprintf(stderr, "sendRecieve() - select() timeout!\n");
        return EXIT_FAILURE;
      }
      if (rtn == -1)
      {
        if (errno == EINTR)
        {
          fprintf(stderr, "sendRecieve() - select() EINTR !\n");
          if (terminate == 1)
            break;
          continue;
        }
        else
        {
          fprintf(stderr, "sendRecieve() - select()\n%s\n", strerror(errno));
          return EXIT_FAILURE;
        }
      }

      while (1)
      {
        rtn = read(mySER->sfd, &myChar, 1);
        if (rtn == -1)
        {
          if (errno == EINTR)
          {
            fprintf(stderr, "sendRecieve() - read() EINTR !\n");
            if (terminate == 1)
              break;
            continue;
          }
          else
          {
            fprintf(stderr, "sendRecieve() - read()\n%s\n", strerror(errno));
            return EXIT_FAILURE;
          }
        }
        else
          break;

        response[respIndex] = myChar;
        if (respIndex < responseSize - 1)
          respIndex++;
        else
          break;

        if (myChar == '\n')
          return EXIT_SUCCESS;
      }
    }
    fprintf(stderr, "sendRecieve() - select/read while loop Dumped (response frame too big)!!\n");
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}


char* SERwrapperFunc(SER* mySER)
{
  char  myCharArray[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
  int   myCharArrayCountToSend = sizeof(myCharArray);

  sendRecieve(mySER, myCharArray, myCharArrayCountToSend, true, true);
  return response;
}


void serPrint()
{
  printf("NCCS = %d            OLD:              NEW:\n", NCCS);
  printf("c_iflag -        %08x          %08x\n", oldtio.c_iflag, newtio.c_iflag);
  printf("c_oflag -        %08x          %08x\n", oldtio.c_oflag, newtio.c_oflag);
  printf("c_cflag -        %08x          %08x\n", oldtio.c_cflag, newtio.c_cflag);
  printf("c_lflag -        %08x          %08x\n", oldtio.c_lflag, newtio.c_lflag);
  printf("c_line -         %08x          %08x\n", oldtio.c_line, newtio.c_line);
  printf("c_ispeed -       %08x          %08x\n", oldtio.c_ispeed, newtio.c_ispeed);
  printf("c_ospeed -       %08x          %08x\n", oldtio.c_ospeed, newtio.c_ospeed);

  printf("\n");

  printf("VINTR -                %02x                %02x\n", oldtio.c_cc[VINTR], newtio.c_cc[VINTR]);
  printf("VQUIT -                %02x                %02x\n", oldtio.c_cc[VQUIT], newtio.c_cc[VQUIT]);
  printf("VERASE -               %02x                %02x\n", oldtio.c_cc[VERASE], newtio.c_cc[VERASE]);
  printf("VKILL -                %02x                %02x\n", oldtio.c_cc[VKILL], newtio.c_cc[VKILL]);
  printf("VEOF -                 %02x                %02x\n", oldtio.c_cc[VEOF], newtio.c_cc[VEOF]);
  printf("VTIME -                %02x                %02x\n", oldtio.c_cc[VTIME], newtio.c_cc[VTIME]);
  printf("VMIN -                 %02x                %02x\n", oldtio.c_cc[VMIN], newtio.c_cc[VMIN]);
  printf("VSWTC -                %02x                %02x\n", oldtio.c_cc[VSWTC], newtio.c_cc[VSWTC]);
  printf("VSTART -               %02x                %02x\n", oldtio.c_cc[VSTART], newtio.c_cc[VSTART]);
  printf("VSTOP -                %02x                %02x\n", oldtio.c_cc[VSTOP], newtio.c_cc[VSTOP]);
  printf("VSUSP -                %02x                %02x\n", oldtio.c_cc[VSUSP], newtio.c_cc[VSUSP]);
  printf("VEOL -                 %02x                %02x\n", oldtio.c_cc[VEOL], newtio.c_cc[VEOL]);
  printf("VREPRINT -             %02x                %02x\n", oldtio.c_cc[VREPRINT], newtio.c_cc[VREPRINT]);
  printf("VDISCARD -             %02x                %02x\n", oldtio.c_cc[VDISCARD], newtio.c_cc[VDISCARD]);
  printf("VWERASE -              %02x                %02x\n", oldtio.c_cc[VWERASE], newtio.c_cc[VWERASE]);
  printf("VLNEXT -               %02x                %02x\n", oldtio.c_cc[VLNEXT], newtio.c_cc[VLNEXT]);
  printf("VEOL2 -                %02x                %02x\n", oldtio.c_cc[VEOL2], newtio.c_cc[VEOL2]);

  printf("\n");
  printf("\n");
}


SER* SERinit(const char* strPort, int myBAUD)
{
  SER* mySER;

  //------------------------------------------------------------
  // create the global SER struct instance.
  if ((mySER = malloc(sizeof(SER))) == NULL)
  {
    fprintf(stderr, "SERinit() - mySER malloc()\n%s\n", strerror(errno));
    return NULL;
  }
  memset(mySER, 0, sizeof(SER));

  //------------------------------------------------------------
  // setup the BAUD.
  mySER->BAUDindex = myBAUD;
  mySER->BAUDvalue = BAUDarray[myBAUD];
  mySER->BAUDmult  = BAUDdelay[myBAUD];

  //------------------------------------------------------------
  // open the serial port.
  mySER->sfd = open(strPort, O_RDWR | O_NOCTTY);
  if (mySER->sfd < 0)
  {
    fprintf(stderr, "SERInit() - open()\n%s\n", strerror(errno));
    free(mySER);
    return NULL;
  }

  //------------------------------------------------------------
  // save old port settings for when we exit.
  tcgetattr(mySER->sfd, &oldtio);

  //------------------------------------------------------------
  // prepare the newtio struct with current settings.
  newtio = oldtio;

  //------------------------------------------------------------
  // set BAUD
  if (cfsetspeed(&newtio, B9600) != 0)//mySER->BAUDvalue
  {
    fprintf(stderr, "SERInit() - cfsetspeed()\n%s\n", strerror(errno));
    free(mySER);
    return NULL;
  }

  //------------------------------------------------------------
  // set for non-canonical (raw).
  cfmakeraw(&newtio);

  newtio.c_cflag |= (CLOCAL | CREAD);
  newtio.c_cflag &= ~(CRTSCTS | CSTOB)

  // read() blocks until one char or until 100 mS timeout.
  newtio.c_cc[VTIME]  = 1;
  newtio.c_cc[VMIN]   = 1;

  // flush the toilet.
  tcflush(mySER->sfd, TCIFLUSH);

  // write new port settings.
  tcsetattr(mySER->sfd, TCSANOW, &newtio);

  serPrint();

  return mySER;
}


void SERclose(SER* mySER)
{
  // restore old port settings.
  tcsetattr(mySER->sfd, TCSANOW, &oldtio);
  close(mySER->sfd);
}

SER.h


#ifndef SER_H_
#define SER_H_

#define threadInit        0x00
#define threadStarting    0x01
#define threadRuning      0x02
#define threadFailed      0x03
#define threadStopped     0x0f

#define threadCtrlRestart 0xFE
#define threadCtrlKill    0xFF

#include <stdint.h>
#include <pthread.h>


typedef struct SER
{
  int         BAUDindex;               // the BAUD rate.

  int         BAUDmult;                // uS per character ... plus one bite time between characters.
                                       //   used as a multiplier used to calculate sleep times after write().
                                       //   (bit time x 10 bits) 71E.

  int         BAUDvalue;               // array used to set termios BAUD and get BAUDmult.
                                       // 4800 = 1       2080 uS
                                       // 9600 = 2       1040
                                       // 19,200 = 3      520
                                       // 38,400 = 4      260
                                       // 76,800 = 5      130
                                       // 115,200 = 6      65
                                       // 230,400 = 7      32.5
                                       // 460,800 = 8      16.25

  pthread_t   tid;                     // Stores thread ID.

  uint8_t     ThreadStatus;            // written only by thread.

  uint8_t     ThreadCtrl;              // written only by main.

  int         sfd;                     // serial port file descriptor.
}SER;


char* SERwrapperFunc(SER* mySER);
SER* SERinit(const char* strPort, int myBAUD);
void SERclose(SER* mySER);
void* serialThread(void* arg);

#endif /* SER_H_ */


回答1:


Thanks to sawdust, I found the issue, and corrected some others!

The original SERmaster.c was select()'ing and read()'ing and discarding with a final select() which of course timed out due to no additional serial data when the message ended.

I had assumed select() only fired once and timed out.

Corrected SERmaster.c

#define responseSize    4584

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
//#include <linux/serial.h>
//#include <aio.h>
#include <sys/time.h>

#include "SER.h"


// array used to get termios BAUD.
const
int       BAUDarray[9] = {  0,         // not used.
                            B4800,     // 208
                            B9600,     // 104
                            B19200,    //  52
                            B38400,    //  26
                            B57600,    //  17.363636
                            B115200,   //   8.727272
                            B230400,   //   4.363636
                            B460800    //   2.181818
                         };

// delay (in uS) per character transmitted.
//    1 start, Even parity, 7bits, 1 stop.
//    bit time (times 10 bits)
//    Plus one bit time between characters.
const
int       BAUDdelay[9] = {  0,         // not used.
                            2288,
                            1144,
                            572,
                            286,
                            191,
                            96,
                            48,
                            24
                         };

static    
char      response[4584];

static
unsigned  
int       respIndex;

static
struct    termios   newtio, oldtio;

extern
volatile
int       terminate;


static
int sendRecieve(SER* mySER, const char* msgBuffer, int msgCnt, int sendFlag, int receiveFlag)
{
  int       rtn;
  char      myChar;
  fd_set    myfds;

  struct
  timeval   tm_out;

  if (sendFlag == true)
  {
    while (1)
    {
      rtn = write(mySER->sfd, msgBuffer, msgCnt);
      if (rtn == -1)
      {
        if (errno == EINTR)
        {
          fprintf(stderr, "sendRecieve() - write() EINTR !\n");
          if (terminate == 1)
            break;                     // deal with SIGTERM !
          continue;                    // if not SIGTERM then retry.
        }
        else
        {
          fprintf(stderr, "sendRecieve() - write()\n%s\n", strerror(errno));
          return EXIT_FAILURE;
        }
      }
      else
      {
        if (rtn == msgCnt)
          break;
        else
        {
          fprintf(stderr, "sendRecieve() - write() returned less than msgCnt !\n");
          return EXIT_FAILURE;
        }
      }
    }
  }

  if (receiveFlag == true)
  {
    for (int i = 0; i < responseSize; i++)
      response[i] = '\0';
    respIndex = 0;

    // set our first select() time out for (x + 2) char times where x is what we sent via write().
    tm_out.tv_sec  = 0;
    tm_out.tv_usec = mySER->BAUDmult * (msgCnt + 2);

    while (1)
    {
      FD_ZERO(&myfds);
      FD_SET(mySER->sfd, &myfds);

      rtn = select(mySER->sfd + 1, &myfds, NULL, NULL, &tm_out);
      if (rtn == 0)
      {
        fprintf(stderr, "sendRecieve() - select() timeout!\n");
        return EXIT_FAILURE;
      }
      if (rtn == -1)
      {
        if (errno == EINTR)
        {
          if (terminate == 1)
          {
            fprintf(stderr, "sendRecieve() - select() EINTR, terminating!\n");
            return EXIT_FAILURE;
          }
          fprintf(stderr, "sendRecieve() - select() EINTR, restarting, tm_out.tv_usec = %d, remaining = %ld\n", mySER->BAUDmult * msgCnt, tm_out.tv_usec);
          continue;
        }
        else
        {
          fprintf(stderr, "sendRecieve() - select()\n%s\n", strerror(errno));
          return EXIT_FAILURE;
        }
      }
      // select() indicates ready for reading !!

      while (1)
      {
        rtn = read(mySER->sfd, &myChar, 1);
        if (rtn == -1)
        {
          if (errno == EINTR)
          {
            fprintf(stderr, "sendRecieve() - read() EINTR !\n");
            if (terminate == 1)
              return EXIT_FAILURE;
            continue;
          }
          else
          {
            fprintf(stderr, "sendRecieve() - read()\n%s\n", strerror(errno));
            return EXIT_FAILURE;
          }
        }
        if (rtn == 0)
        {
          fprintf(stderr, "sendRecieve() - read() returned 0 yet select() reported ready for reading ??? should never see this !\n");
          return EXIT_FAILURE;
        }
        // break from read while() loop to process the char.
        break;
      }// end read() while loop

      // save the new char.
      response[respIndex] = myChar;
      // point to the nest storage location.
      respIndex++;

      if (myChar == '\n')
        return EXIT_SUCCESS;

      // are we pointing beyond max buffer size?
      if (respIndex == responseSize)
      {
        fprintf(stderr, "sendRecieve() - exceeded response buffer size ... before message termination char!!\n");
        return EXIT_FAILURE;
      }

      // set our next select() time out for 2 char times based on baud rate.
      tm_out.tv_sec  = 0;
      tm_out.tv_usec = mySER->BAUDmult * 2;

    }//end select() while loop

    fprintf(stderr, "sendRecieve() - select/read outer while loop Dumped, should not see this ever !!\n");
    return EXIT_FAILURE;

  }// end if (receiveFlag == true)

  return EXIT_SUCCESS;
}


char* SERwrapperFunc(SER* mySER)
{
  char  myCharArray[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
  int   myCharArrayCountToSend = sizeof(myCharArray);

  sendRecieve(mySER, myCharArray, myCharArrayCountToSend, true, true);
  return response;
}


void serPrint()
{
  printf("NCCS = %d            OLD:              NEW:\n", NCCS);
  printf("c_iflag -        %08x          %08x\n", oldtio.c_iflag, newtio.c_iflag);
  printf("c_oflag -        %08x          %08x\n", oldtio.c_oflag, newtio.c_oflag);
  printf("c_cflag -        %08x          %08x\n", oldtio.c_cflag, newtio.c_cflag);
  printf("c_lflag -        %08x          %08x\n", oldtio.c_lflag, newtio.c_lflag);
  printf("c_line -         %08x          %08x\n", oldtio.c_line, newtio.c_line);
  printf("c_ispeed -       %08x          %08x\n", oldtio.c_ispeed, newtio.c_ispeed);
  printf("c_ospeed -       %08x          %08x\n", oldtio.c_ospeed, newtio.c_ospeed);

  printf("\n");

  printf("VINTR -                %02x                %02x\n", oldtio.c_cc[VINTR], newtio.c_cc[VINTR]);
  printf("VQUIT -                %02x                %02x\n", oldtio.c_cc[VQUIT], newtio.c_cc[VQUIT]);
  printf("VERASE -               %02x                %02x\n", oldtio.c_cc[VERASE], newtio.c_cc[VERASE]);
  printf("VKILL -                %02x                %02x\n", oldtio.c_cc[VKILL], newtio.c_cc[VKILL]);
  printf("VEOF -                 %02x                %02x\n", oldtio.c_cc[VEOF], newtio.c_cc[VEOF]);
  printf("VTIME -                %02x                %02x\n", oldtio.c_cc[VTIME], newtio.c_cc[VTIME]);
  printf("VMIN -                 %02x                %02x\n", oldtio.c_cc[VMIN], newtio.c_cc[VMIN]);
  printf("VSWTC -                %02x                %02x\n", oldtio.c_cc[VSWTC], newtio.c_cc[VSWTC]);
  printf("VSTART -               %02x                %02x\n", oldtio.c_cc[VSTART], newtio.c_cc[VSTART]);
  printf("VSTOP -                %02x                %02x\n", oldtio.c_cc[VSTOP], newtio.c_cc[VSTOP]);
  printf("VSUSP -                %02x                %02x\n", oldtio.c_cc[VSUSP], newtio.c_cc[VSUSP]);
  printf("VEOL -                 %02x                %02x\n", oldtio.c_cc[VEOL], newtio.c_cc[VEOL]);
  printf("VREPRINT -             %02x                %02x\n", oldtio.c_cc[VREPRINT], newtio.c_cc[VREPRINT]);
  printf("VDISCARD -             %02x                %02x\n", oldtio.c_cc[VDISCARD], newtio.c_cc[VDISCARD]);
  printf("VWERASE -              %02x                %02x\n", oldtio.c_cc[VWERASE], newtio.c_cc[VWERASE]);
  printf("VLNEXT -               %02x                %02x\n", oldtio.c_cc[VLNEXT], newtio.c_cc[VLNEXT]);
  printf("VEOL2 -                %02x                %02x\n", oldtio.c_cc[VEOL2], newtio.c_cc[VEOL2]);

  printf("\n");
  printf("\n");
}


SER* SERinit(const char* strPort, int myBAUD)
{
  SER* mySER;

  //------------------------------------------------------------
  // create the global SER struct instance.
  if ((mySER = malloc(sizeof(SER))) == NULL)
  {
    fprintf(stderr, "SERinit() - mySER malloc()\n%s\n", strerror(errno));
    return NULL;
  }
  memset(mySER, 0, sizeof(SER));

  //------------------------------------------------------------
  // setup the BAUD.
  mySER->BAUDindex = myBAUD;
  mySER->BAUDvalue = BAUDarray[myBAUD];
  mySER->BAUDmult  = BAUDdelay[myBAUD];

  //------------------------------------------------------------
  // open the serial port.
  mySER->sfd = open(strPort, O_RDWR | O_NOCTTY);
  if (mySER->sfd < 0)
  {
    fprintf(stderr, "SERInit() - open()\n%s\n", strerror(errno));
    free(mySER);
    return NULL;
  }

  //------------------------------------------------------------
  // save old port settings for when we exit.
  tcgetattr(mySER->sfd, &oldtio);

  //------------------------------------------------------------
  // prepare the newtio struct with current settings.
  newtio = oldtio;

  //------------------------------------------------------------
  // set BAUD
  if (cfsetspeed(&newtio, B9600) != 0)//mySER->BAUDvalue
  {
    fprintf(stderr, "SERInit() - cfsetspeed()\n%s\n", strerror(errno));
    free(mySER);
    return NULL;
  }

  //------------------------------------------------------------
  // set for non-canonical (raw).
  cfmakeraw(&newtio);

  newtio.c_cflag |= (CLOCAL | CREAD);
  newtio.c_cflag &= ~(CRTSCTS | CSTOPB);

  // read() blocks until one char or until 100 mS timeout.
  newtio.c_cc[VTIME]  = 1;
  newtio.c_cc[VMIN]   = 1;

  // flush the toilet.
  tcflush(mySER->sfd, TCIFLUSH);

  // write new port settings.
  tcsetattr(mySER->sfd, TCSANOW, &newtio);

  serPrint();

  return mySER;
}


void SERclose(SER* mySER)
{
  // restore old port settings.
  tcsetattr(mySER->sfd, TCSANOW, &oldtio);
  close(mySER->sfd);
}


来源:https://stackoverflow.com/questions/59239782/select-and-read-times-out-on-serial-port-read-yet-previous-write-succeeds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!