select()和read()在串行端口读取时超时,但是先前的write()成功吗?

时间:2019-12-08 20:50:35

标签: c linux serial-port pthreads

三个星期后,我无法摆脱这个问题。 我在Ubuntu 18.04.3上运行以下代码,该代码成功将字符串发送到另一台设备。 当远程设备接收到该字符串时……它又发送回一个字符串……但是下面的代码(即使设置为1秒)在select()上超时。

当我注释掉select()而只是read()...也看不到任何数据吗?

它已经在三周前开始工作了……但是最近的代码更改使它崩溃了……我不知道为什么。 文件描述符上的write()如何可以从串行口中退出,但是使用相同文件描述符的select()和read()却什么也没回来。 我有第三台设备(一台带腻子的PC),因此可以看到线路上的所有内容。 这三个都在RS-485总线上。

任何其他与代码有关的问题将不胜感激!

谢谢!

// 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 个答案:

答案 0 :(得分:0)

感谢木屑,我发现了问题,并更正了其他问题!

最初的SERmaster.c被select()和read()丢弃,并带有最终的select(),由于消息结束时,由于没有其他串行数据,最终的select()当然会超时。

我以为select()仅触发一次并超时。

已更正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);
}