⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialcomm.cpp

📁 route
💻 CPP
字号:

#include <unistd.h>  // UNIX standard function definitions 
#include <termios.h> // POSIX terminal control definitions 
#include <fcntl.h>   // File control definitions
#include <string.h>
#include "SerialComm.h"

SerialComm::SerialComm()
{
  // Default setting 
  baud_rate = 9600;
  parity = 'N';
  character_size = 8;
  stop_bits = 1;
  flow_control = SerialComm::scommNO_FLOW_CONTROL;
  binary_mode = 1; 
  scomm_error = SerialComm::scomm_NO_ERROR;

  memset(&options, 0, sizeof(options));
}

SerialComm::~SerialComm()
{
  Close();
}

int SerialComm::OpenSerialPort(char *device_name)
// Open a serial device for read/write operations. 
{

  device_handle = open(device_name, O_RDWR | O_NOCTTY | O_NDELAY);

  if(device_handle < 0) 
    device_handle = open(device_name, O_RDONLY | O_NOCTTY | O_NDELAY);
  else 
    return scommREAD_WRITE;
  
  if(device_handle < 0) 
    device_handle = open(device_name, O_WRONLY | O_NOCTTY | O_NDELAY);
  else 
    return scommREAD_ONLY;
  
  if(device_handle < 0) {
    scomm_error = SerialComm::scomm_OPEN_ERROR;
    return -1;
  }
  else
    return scommWRITE_ONLY;

}

int SerialComm::InitSerialPort()
{
  // Reset the port options
  memset(&options, 0, sizeof(options));

  // Set the baud rates
  switch(baud_rate) {
    case 0: // 0 baud (drop DTR)
      cfsetispeed(&options, B0);
      cfsetospeed(&options, B0);
      break;
    case 50: 
      cfsetispeed(&options, B50);
      cfsetospeed(&options, B50);
      break;
    case 75: 
      cfsetispeed(&options, B75);
      cfsetospeed(&options, B75);
      break;
    case 110: 
      cfsetispeed(&options, B110);
      cfsetospeed(&options, B110);
      break;
    case 134: 
      cfsetispeed(&options, B134);
      cfsetospeed(&options, B134);
      break;
    case 150: 
      cfsetispeed(&options, B150);
      cfsetospeed(&options, B150);
      break;
    case 200: 
      cfsetispeed(&options, B200);
      cfsetospeed(&options, B200);
      break;
    case 300: 
      cfsetispeed(&options, B300);
      cfsetospeed(&options, B300);
      break;
    case 600: 
      cfsetispeed(&options, B600);
      cfsetospeed(&options, B600);
      break;
    case 1200: 
      cfsetispeed(&options, B1200);
      cfsetospeed(&options, B1200);
      break;
    case 1800: 
      cfsetispeed(&options, B1800);
      cfsetospeed(&options, B1800);
      break;
    case 2400: 
      cfsetispeed(&options, B2400);
      cfsetospeed(&options, B2400);
      break;
    case 4800: 
      cfsetispeed(&options, B4800);
      cfsetospeed(&options, B4800);
      break;
    case 9600: 
      cfsetispeed(&options, B9600);
      cfsetospeed(&options, B9600);
      break;
    case 19200: 
      cfsetispeed(&options, B19200);
      cfsetospeed(&options, B19200);
      break;
    case 57600: 
      cfsetispeed(&options, B57600);
      cfsetospeed(&options, B57600);
      break;
    case 115200: 
      cfsetispeed(&options, B115200);
      cfsetospeed(&options, B115200);
      break;
    default:
      scomm_error = SerialComm::scomm_BAUDRATE_ERROR;
      return -1; // Invalid baud rate
  }

  // Set the character size, parity and stop bits
  if((character_size == 8) && (parity == 'N') && (stop_bits == 1)) {
    // No parity (8N1) 
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    options.c_iflag = IGNPAR;
  }
  else if((character_size == 7) && (parity == 'E') && (stop_bits == 1)) {
    // Even parity (7E1) 
    options.c_cflag |= PARENB;
    options.c_cflag &= ~PARODD;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    options.c_iflag |= (INPCK | ISTRIP);
  }
  else if((character_size == 7) && (parity == 'O') && (stop_bits == 1)) {
    // Odd parity (7O1) 
    options.c_cflag |= PARENB;
    options.c_cflag |= PARODD;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    options.c_iflag |= (INPCK | ISTRIP);
  }
  else if((character_size == 7) && (parity == 'M') && (stop_bits == 1)) {
    // Mark parity is simulated by using 2 stop bits (7M1)
    options.c_cflag &= ~PARENB;
    options.c_cflag |= CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    options.c_iflag |= (INPCK | ISTRIP);
  }
  else if((character_size == 7) && (parity == 'S') && (stop_bits == 1)) {
    // Space parity is setup the same as no parity (7S1)
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    options.c_iflag |= (INPCK | ISTRIP);
  }
  else {
    scomm_error = SerialComm::scomm_INVALIDPARM;
    return -1; // Invalid character size, parity and stop bits combination
  }
  
  switch(flow_control) {
    case scommHARD_FLOW :
#if defined(CRTSCTS)
      options.c_cflag |= CRTSCTS;
      break;
#else
      break; // Hard flow control is not supported
#endif

    case scommXON_XOFF :
      options.c_iflag |= (IXON | IXOFF | IXANY);
#if defined(CRTSCTS)
      options.c_cflag &= ~CRTSCTS;
#endif
      break;

    case scommSOFT_FLOW :
#if defined(CRTSCTS)
      options.c_cflag &= ~CRTSCTS;
      break;
#else
      break; // Hard flow control is not supported
#endif

    case scommNO_FLOW_CONTROL :
#if defined(CRTSCTS)
      options.c_cflag &= ~CRTSCTS;
      break;
#else
      break; // Hard flow control is not supported
#endif

    default:
      scomm_error = SerialComm::scomm_FLOWCONTROL_ERROR;
      return -1; // Invalid flow control
  }

  if(!binary_mode) { // Set the port for canonical input (line-oriented) 
    // Input characters are put into a buffer until a CR (carriage return)
    // or LF (line feed) character is received.
    options.c_lflag |= (ICANON | ECHOE);

    // Postprocess the output.
    // The ONLCR flag will map NL (linefeeds) to CR-NL on output.
    // The OLCUC flag will map characters to upper case for tty output.
    options.c_oflag = OPOST | ONLCR | OLCUC;
  }
  else { // Use raw input/output
    // Input characters are passed through exactly as they are received,
    // when they are received.
    options.c_lflag = 0;
    options.c_oflag = 0;
  }
  
  // Enable the receiver and set local mode
  options.c_cflag |= (CLOCAL | CREAD);
  
  // Initialize control characters if needed.
  // Default values can be found in /usr/include/termios.h, and are given
  // in the comments.

  options.c_cc[VTIME]    = 0;     // inter-character timer unused 
  options.c_cc[VMIN]     = 1;     // blocking read until 1 character arrives 

 

  // Set the new options for the port. The TCSANOW constant specifies
  // that all changes should occur immediately without waiting for
  // output data to finish sending or input data to finish receiving. 
  tcflush(device_handle, TCIFLUSH); // Clean the serial line
  tcsetattr(device_handle, TCSANOW, &options);

return 1; // No errors reported
}

void SerialComm::Close()
{

  close(device_handle);

}

int SerialComm::RawRead(void *buf, int bytes)
// Read a specified number of bytes from the serial port
// and return whether or not the read was completed.
// Returns the number of bytes received or -1 if an
// error occurred.
{

  bytes_read = read(device_handle, (char *)buf, bytes);
  if(bytes_read < 0) {
    scomm_error = SerialComm::scomm_RECEIVE_ERROR;
    return -1;
  }
  return (int)bytes_read;
}

int SerialComm::RawWrite(const void *buf, int bytes)
// Write a specified number of bytes to a serial port
// and return whether or not the write was complete.
// Returns the total number of bytes moved or -1 if
// an error occurred.
{
  bytes_moved = write(device_handle, (char *)buf, bytes);
  if(bytes_moved < 0) {
    scomm_error = SerialComm::scomm_TRANSMIT_ERROR;
    return -1;
  }
  return (int)bytes_moved;
}

int SerialComm::Recv(void *buf, int bytes)
// Receive a specified number of bytes from a serial port
// and do not return until all the byte have been read.
// Returns the total number of bytes read or -1 if an
// error occurred.
{
  int br = 0;               // Byte counter
  int num_read = 0;         // Actual number of bytes read
  int num_req = (int)bytes; // Number of bytes requested 
  char *p = (char *)buf;    // Pointer to the buffer

  while(br < bytes) { // Loop unitl the buffer is full
    if((num_read = RawRead(p, num_req-br)) > 0) {
      br += num_read;   // Increment the byte counter
      p += num_read;    // Move the buffer pointer for the next read
    }
    if(num_read < 0) {
      scomm_error = SerialComm::scomm_RECEIVE_ERROR;
      return -1; // An error occurred during the read
    }
  }
  
  bytes_read = br; // Undate the object's byte counter
  return bytes_read;
}

int SerialComm::Send(const void *buf, int bytes)
// Write a specified number of bytes to a serial port and do
// not return until all the bytes have been written. Returns
// the total number of bytes written or -1 if an error occurred.
{
  int bm = 0;                // Byte counter
  int num_moved = 0;         // Actual number of bytes written
  int num_req = (int)bytes;  // Number of bytes requested 
  char *p = (char *)buf;     // Pointer to the buffer

  while(bm < bytes) { // Loop unitl the buffer is empty
    if((num_moved = RawWrite(p, num_req-bm)) > 0) {
      bm += num_moved;  // Increment the byte counter
      p += num_moved;   // Move the buffer pointer for the next read
    }
    if(num_moved < 0) {
      scomm_error = SerialComm::scomm_TRANSMIT_ERROR;
      return -1; // An error occurred during the read
    }
  }
  
  bytes_moved = bm; // Update the object's byte counter
  return bytes_moved;
}

int SerialComm::InitSerialPort(char *device_name, int sp, char pr, int cs,
				 int sb, int flow, int bin_mode)
// Initialize a serial device using the specified parameters. Returns
// -1 if an error occurred during initialization or the current access
// mode of the port (scommREAD_WRITE, scommREAD_ONLY, scommREAD_WRITE).
{
  int status = OpenSerialPort(device_name); 
  if(status < 0) return -1;

  SetBaudRate(sp);
  SetCharacterSize(cs);
  SetParity(pr);
  SetStopBits(sb);
  SetFlowControl(flow);
  if(bin_mode) BinaryMode(); else CharacterMode();

  if(InitSerialPort() < 0) return -1;
  
  return status;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -