Трудности с обменом данными через последовательные порты в Linux

#c #linux #serial-port

#c #linux #последовательный порт

Вопрос:

Я успешно пишу код в Windows и выполняю обмен данными через последовательный порт. Но пока не в Linux.

Вот код, который я написал: я использовал Picocom для проверки того, что я могу обмениваться данными через последовательные порты через мой кабель (USB-модем с НУЛЬ-модемом на USB).

Установка кода на None blocking приводит к « errno: 11 Resource temporarily unavailable » как на клиенте, так и на сервере.»

Когда я устанавливаю блокировку, она зависает в коде при методе чтения файла. Если я прокомментирую эту строку, она запустится… но не получение данных.


 Server sends packets continuous. 
Client receives packets continuous. 

Problem seems to be bytes aren't received at the client.  They are sent, however at the server.

CLIENT:

RECV(1611912):  NumChars: 0    String: 
RECV(1611913):  NumChars: 0    String: 
RECV(1611918):  NumChars: 0    String: 
RECV(1611919):  NumChars: 0    String: 
RECV(1611920):  NumChars: 0    String: 
 

 SERVER:

SENT(106775):  NumChars: 10    String: 0123456789
SENT(106776):  NumChars: 10    String: 0123456789
SENT(106777):  NumChars: 10    String: 0123456789
SENT(106778):  NumChars: 10    String: 0123456789
SENT(106779):  NumChars: 10    String: 0123456789
 

 to run: 
g   -o sp serialport.cpp

client:  ./sp /dev/ttyS0 c
server:  ./sp /dev/ttyS4 s


#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
 
 class C_SerialPort
 {
  private:
    int  giFD;
    char gpcDevice[100] = {0};

  public:
  
    //------------------------------------------------
    //
    //------------------------------------------------
    int GetError(char* pcMessage = (char*)"")
    {
      char pcError[100] = {0};
      sprintf(pcError, "  (%s):   errno: %d    %sn", pcMessage, errno, strerror(errno));

      if(errno > 0)
      {
        printf("%s", pcError);
      }

      return errno;
    }


    //------------------------------------------------
    //
    //------------------------------------------------
    int Connect() 
    {
      return Connect((char*)"/dev/ttyS0");
      //return Connect((char*)"/dev/ttyUSB0");
    }
    

    //------------------------------------------------
    //
    //------------------------------------------------
    int Connect(char *pcDevice) 
    {
      strcpy(gpcDevice, pcDevice);

      struct termios s_TA;
      
      // Open the serial port
      giFD = open(gpcDevice, O_RDWR | O_NOCTTY | O_NDELAY | O_FSYNC );
      if(giFD < 0)
      {
        printf("open_port: Unable to open %sn%s", gpcDevice, strerror(errno));
        printf("EXITING...n");
        return 1;
      }
      else
      {
        printf("Connect Device: %sn", gpcDevice);
      }


      // get attributes
      if(tcgetattr(giFD, amp;s_TA) != 0) 
      {
        GetError((char*)"tcgetattr");
        printf("EXITING...n");
        return 1;
      }



      // clear terminalAttributes data
      //memset(amp;s_TA, 0, sizeof(struct termios));
      
      if(0)
      {
        // 57600 bauds; 8 bits per word; Ignore modem control lines; Enable receiver.
        s_TA.c_cflag = B57600 | CS8 | CLOCAL | CREAD;
        
        // Ignore framing errors and parity errors.
        s_TA.c_iflag = IGNPAR |  ONLCR;
        
        //Enable implementation-defined output processing.
        s_TA.c_oflag = OPOST;
        
        // min time; min bytes to read
        s_TA.c_cc[VTIME] = 1;
        s_TA.c_cc[VMIN] = 1;// none zero blocks
      }
      else
      {

        cfsetospeed(amp;s_TA, B9600);
        cfsetispeed(amp;s_TA, B9600);

        s_TA.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
        s_TA.c_cflag amp;= ~CSIZE;
        s_TA.c_cflag |= CS8;         /* 8-bit characters */
        s_TA.c_cflag amp;= ~PARENB;     /* no parity bit */
        s_TA.c_cflag amp;= ~CSTOPB;     /* only need 1 stop bit */
        s_TA.c_cflag amp;= ~CRTSCTS;    /* no hardware flowcontrol */

        /* setup for non-canonical mode */
        s_TA.c_iflag amp;= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
        s_TA.c_lflag amp;= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
        s_TA.c_oflag amp;= ~OPOST;


        /* fetch bytes as they become available */
        s_TA.c_cc[VMIN] = 1;  // 0   1
        s_TA.c_cc[VTIME] = 1; // 0   1
      }

      //int iVal = fcntl(giFD, F_SETFL, 0); // set blocking?
      //printf("file status = 0x%xn", iVal);
      //GetError((char*)"fcntl");

      // Set the port to our state
      if (tcsetattr(giFD, TCSANOW, amp;s_TA) != 0) 
      {
        GetError((char*)"tcsetattr");
        printf("EXITING...n");
        return 1;
      }

      // flushes data written but not transmitted.
      // flushes data received but not read.
      tcflush(giFD, TCOFLUSH);
      tcflush(giFD, TCIFLUSH);
      

      printf("CONNECTION OKn");

      //return giFD;
      return 0;
    }
    

    //------------------------------------------------
    //
    //------------------------------------------------
    void Disconnect(void)
    {
      close(giFD);
      printf("nPort 1 has been CLOSED and %d is the file descriptionn", giFD);

      GetError((char*)"Disconnect");
    }
    

    //------------------------------------------------
    //
    //------------------------------------------------
    int SendArray(unsigned char *buffer, int len) 
    {
      int n = write(giFD, buffer, len);

      // error catch
      if(n < 0)
        GetError((char*)"write");

      return n;
    }
    

    //------------------------------------------------
    //
    //------------------------------------------------
    int GetArray (unsigned char *buffer, int len)
    {
      int n = 0;

      int len2 = BytesToRead();
       n = read(giFD, buffer, len2); // this line is an issue? with settings?

      // error catch
      //if(n < 0)
       // GetError((char*)"read");

      return n;
    }
    

    //------------------------------------------------
    //
    //------------------------------------------------
    void Clear()
    {
      tcflush(giFD, TCIFLUSH);
      tcflush(giFD, TCOFLUSH);
    }
    

    //------------------------------------------------
    //
    //------------------------------------------------
    int BytesToRead()
    {
      int iBytes = 0;
      ioctl(giFD, FIONREAD, amp;iBytes);
      
      //printf("Byte2Read: %dn", iBytes);
      // error catch
      GetError((char*)"BytesToRead");

      return iBytes;
    }
 };



//------------------------------------------------
//
//------------------------------------------------
 int main(int argc, char const *argv[])
 {
  // device
  char *pcDevice = (char*)argv[1];
  printf("init:device:%sn", pcDevice);

  // connection type
  char cConnType = argv[2][0];
  printf("ConnectionType:%cn", cConnType);

  // instantiate SerialPort
  C_SerialPort c_SP;

  // connect
  int iReturn = c_SP.Connect(pcDevice);
  if(iReturn != 0)
  {
    printf("EXITING...n");
    return 1;
  }

  // clear buffer
  c_SP.Clear();
  printf("clearn");

  printf("prior...n");

  // main loop
  while(1)
  {
    int iSleep_ms = 200;
    usleep(iSleep_ms);

    char pcArray[100] = {0};
    int iNumChars = 0;

  
    if(cConnType == 's')
    {
      static long lCount = 0;
      
      // Send
      strcpy(pcArray, "0123456789");
      iNumChars = c_SP.SendArray((unsigned char*)pcArray, 10);
        
      if(iNumChars > 0)
      {
        printf("SENT(%ld):  NumChars: %d    String: %sn", lCount, iNumChars, pcArray);
      }

      lCount  ;
    }


    
    if(cConnType == 'c')
    {
      static long lCount = 0;

      // Receive
      iNumChars = c_SP.GetArray((unsigned char*)pcArray, sizeof(pcArray));

      if(iNumChars > 0)
      {
        printf("RECV(%ld):  NumChars: %d    String: %sn", lCount, iNumChars, pcArray);
      }
      else
      {
        //printf("RECV:  NumChars: %d    String: %sn", iNumChars, pcArray);
      }

      lCount  ;
    }

  }

  c_SP.Disconnect();

  return 0;
 }


 
 

Комментарии:

1. Проблема, похоже, в том, что байты не принимаются клиентом. Однако они отправляются на сервер.

2. Сколько данных вы хотите GetArray получать при каждом вызове?

3. Он получает то, что находится в буфере, и должен возвращать это количество.

4. А если буфер пуст?

5. результаты показаны выше

Ответ №1:

У вас есть четыре основные ошибки:

  1. Ваша GetArray функция игнорирует возвращаемое значение BytesToRead . Он должен считывать меньший размер буфера или количество доступных байтов.
  2. Ваш код не способен разумно обрабатывать случай, когда BytesToRead возвращает ноль.
  3. Вы игнорируете возвращаемое значение GetArray . При печати вы pcArray не указываете printf , сколько символов выводить. Итак, как он должен знать, что печатать?
  4. Вы перезаписываете возвращаемые значения с tcgetattr помощью вызова memset .

Комментарии:

1. Я удалил memset в tcgetattr. Хороший показатель количества байтов для чтения. Но NumberOfBytes2Read всегда равно 0… тем не менее.

2. @jdl В этом случае вам нужно сделать что-то разумное. Что вы хотите сделать, если нет байтов для чтения? (Это ошибка номер 2.)

3. Я решил проблему … спасибо за вашу помощь

Ответ №2:

Проблема заключается в последовательном порту для обмена данными.

/dev/ttyS0 И /dev/ttyS4 — это последовательные порты после подключения USB к НУЛЬ-модемному кабелю. Но для связи мне пришлось использовать /dev/ttyUSB0 и /dev/ttyUSB1