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();