• 基于ROS的串口底层写法


    serial_device.cpp

    #include "serial_device.h"
    
    namespace roborts_sdk {
    SerialDevice::SerialDevice(std::string port_name,
                               int baudrate) :
        port_name_(port_name),
        baudrate_(baudrate),
        data_bits_(8),
        parity_bits_('N'),
        stop_bits_(1) {}
    
    SerialDevice::~SerialDevice() {
      CloseDevice();
    }
    
    bool SerialDevice::Init() {
    
      DLOG_INFO << "Attempting to open device " << port_name_ << " with baudrate " << baudrate_;
      if (port_name_.c_str() == nullptr) {
        port_name_ = "/dev/ttyUSB0";
      }
      if (OpenDevice() && ConfigDevice()) {
        FD_ZERO(&serial_fd_set_);
        FD_SET(serial_fd_, &serial_fd_set_);
        DLOG_INFO << "...Serial started successfully.";
        return true;
      } else {
        DLOG_ERROR << "...Failed to start serial "<<port_name_;
        CloseDevice();
        return false;
      }
    }
    
    bool SerialDevice::OpenDevice() {
    
      serial_fd_ = open(port_name_.c_str(), O_RDWR | O_NOCTTY);
      if (serial_fd_ < 0) {
        DLOG_ERROR << "cannot open device " << serial_fd_ << " " << port_name_;
        return false;
      }
    
      return true;
    }
    
    bool SerialDevice::CloseDevice() {
      close(serial_fd_);
      serial_fd_ = -1;
      return true;
    }
    
    bool SerialDevice::ConfigDevice() {
      int st_baud[] = {B4800, B9600, B19200, B38400,
                       B57600, B115200, B230400, B921600};
      int std_rate[] = {4800, 9600, 19200, 38400, 57600, 115200,
                        230400, 921600, 1000000, 1152000, 3000000};
      int i, j;
      /* save current port parameter */
      if (tcgetattr(serial_fd_, &old_termios_) != 0) {
        DLOG_ERROR << "fail to save current port";
        return false;
      }
      memset(&new_termios_, 0, sizeof(new_termios_));
    
      /* config the size of char */
      new_termios_.c_cflag |= CLOCAL | CREAD;
      new_termios_.c_cflag &= ~CSIZE;
    
      /* config data bit */
      switch (data_bits_) {
        case 7:new_termios_.c_cflag |= CS7;
          break;
        case 8:new_termios_.c_cflag |= CS8;
          break;
        default:new_termios_.c_cflag |= CS8;
          break; //8N1 default config
      }
      /* config the parity bit */
      switch (parity_bits_) {
        /* odd */
        case 'O':
        case 'o':new_termios_.c_cflag |= PARENB;
          new_termios_.c_cflag |= PARODD;
          break;
          /* even */
        case 'E':
        case 'e':new_termios_.c_cflag |= PARENB;
          new_termios_.c_cflag &= ~PARODD;
          break;
          /* none */
        case 'N':
        case 'n':new_termios_.c_cflag &= ~PARENB;
          break;
        default:new_termios_.c_cflag &= ~PARENB;
          break; //8N1 default config
      }
      /* config baudrate */
      j = sizeof(std_rate) / 4;
      for (i = 0; i < j; ++i) {
        if (std_rate[i] == baudrate_) {
          /* set standard baudrate */
          cfsetispeed(&new_termios_, st_baud[i]);
          cfsetospeed(&new_termios_, st_baud[i]);
          break;
        }
      }
      /* config stop bit */
      if (stop_bits_ == 1)
        new_termios_.c_cflag &= ~CSTOPB;
      else if (stop_bits_ == 2)
        new_termios_.c_cflag |= CSTOPB;
      else
        new_termios_.c_cflag &= ~CSTOPB; //8N1 default config
    
    /* config waiting time & min number of char */
      new_termios_.c_cc[VTIME] = 1;
      new_termios_.c_cc[VMIN] = 18;
    
      /* using the raw data mode */
      new_termios_.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
      new_termios_.c_oflag &= ~OPOST;
    
      /* flush the hardware fifo */
      tcflush(serial_fd_, TCIFLUSH);
    
      /* activite the configuration */
      if ((tcsetattr(serial_fd_, TCSANOW, &new_termios_)) != 0) {
        DLOG_ERROR << "failed to activate serial configuration";
        return false;
      }
      return true;
    
    }
    
    int SerialDevice::Read(uint8_t *buf, int len) {
      int ret = -1;
    
      if (NULL == buf) {
        return -1;
      } else {
        ret = read(serial_fd_, buf, len);
        DLOG_INFO<<"Read once length: "<<ret;
        while (ret == 0) {
          LOG_ERROR << "Connection closed, try to reconnect.";
          while (!Init()) {
            usleep(500000);
          }
          LOG_INFO << "Reconnect Success.";
          ret = read(serial_fd_, buf, len);
        }
        return ret;
      }
    }
    
    int SerialDevice::Write(const uint8_t *buf, int len) {
      return write(serial_fd_, buf, len);
    }
    }
    
    

    serial_device.h

    #ifndef ROBORTS_SDK_SERIAL_DEVICE_H
    #define ROBORTS_SDK_SERIAL_DEVICE_H
    #include <string>
    #include <cstring>
    
    #include <termios.h>
    #include <fcntl.h>
    #include <unistd.h>
    
    #include "../utilities/log.h"
    #include "hardware_interface.h"
    
    namespace roborts_sdk {
    /**
     * @brief serial device class inherited from hardware interface
     */
    class SerialDevice: public HardwareInterface {
     public:
      /**
       * @brief Constructor of serial device
       * @param port_name port name, i.e. /dev/ttyUSB0
       * @param baudrate serial baudrate
       */
      SerialDevice(std::string port_name, int baudrate);
      /**
       * @brief Destructor of serial device to close the device
       */
      ~SerialDevice();
      /**
       * @brief Initialization of serial device to config and open the device
       * @return True if success
       */
      virtual bool Init() override ;
      /**
       * @brief Serial device read function
       * @param buf Given buffer to be updated by reading
       * @param len Read data length
       * @return -1 if failed, else the read length
       */
      virtual int Read(uint8_t *buf, int len) override ;
      /**
       * @brief Write the buffer data into device to send the data
       * @param buf Given buffer to be sent
       * @param len Send data length
       * @return < 0 if failed, else the send length
       */
      virtual int Write(const uint8_t *buf, int len) override ;
    
     private:
      /**
       * @brief Open the serial device
       * @return True if open successfully
       */
      bool OpenDevice();
      /**
       * @brief Close the serial device
       * @return True if close successfully
       */
      bool CloseDevice();
    
      /**
       * @brief Configure the device
       * @return True if configure successfully
       */
      bool ConfigDevice();
    
      //! port name of the serial device
      std::string port_name_;
      //! baudrate of the serial device
      int baudrate_;
      //! stop bits of the serial device, as default
      int stop_bits_;
      //! data bits of the serial device, as default
      int data_bits_;
      //! parity bits of the serial device, as default
      char parity_bits_;
      //! serial handler
      int serial_fd_;
      //! set flag of serial handler
      fd_set serial_fd_set_;
      //! termios config for serial handler
      struct termios new_termios_, old_termios_;
    };
    }
    #endif //ROBORTS_SDK_SERIAL_DEVICE_H
    
    
    //简单初始化
    device_ = std::make_shared<SerialDevice>("/dev/ttyUSB0", 921600);
    device_ ->Init();
    
  • 相关阅读:
    【CodeForces】[366A]Dima and Guards
    Linux将程序前台转后台执行
    Storm在Mesos上跑与不在的运行命令区别
    去掉SSH KEY密码
    git 退回到倒数第二次提交
    浅析UGC、PGC和OGC
    linux主机名与IP地址配置文件
    wget ERROR 404: Not Found.
    cpuacct (CPU Accounting Controller)
    Ansible的安装与使用
  • 原文地址:https://www.cnblogs.com/penuel/p/13157335.html
Copyright © 2020-2023  润新知