|
@@ -0,0 +1,132 @@
|
|
|
+#include "serial_com.hpp"
|
|
|
+
|
|
|
+#include <cstddef>
|
|
|
+#include <cstring>
|
|
|
+
|
|
|
+#include "log.hpp"
|
|
|
+
|
|
|
+namespace CommunicationStuff {
|
|
|
+static int transform_baud(int baud_speed);
|
|
|
+static int transform_data_bits(int data_bits);
|
|
|
+
|
|
|
+Serial::Serial(const char* device) : fd_(-1)
|
|
|
+{
|
|
|
+ fd_ = ::open(device, O_RDWR | O_NOCTTY | O_NDELAY);
|
|
|
+ if (fd_ == -1) {
|
|
|
+ LOGE("Fail to open serial port");
|
|
|
+ } else {
|
|
|
+ LOGI("Success to open serial port");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Serial::~Serial()
|
|
|
+{
|
|
|
+ if (fd_ >= 0) {
|
|
|
+ ::close(fd_);
|
|
|
+ LOGI("Success to close serial port");
|
|
|
+ fd_ = -1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Status Serial::setup(const int baud_speed, const int data_bits,
|
|
|
+ const int parity_mode, const int stop_bits)
|
|
|
+{
|
|
|
+ memset(&options_, 0, sizeof(options_));
|
|
|
+
|
|
|
+ int baud_speed_tmp = transform_baud(baud_speed);
|
|
|
+ if (baud_speed_tmp == -1) {
|
|
|
+ LOGE("Failed to set baud speed");
|
|
|
+ return BAUD_NOT_SUPPORT;
|
|
|
+ }
|
|
|
+ cfsetispeed(&options_, baud_speed_tmp);
|
|
|
+ cfsetospeed(&options_, baud_speed_tmp);
|
|
|
+
|
|
|
+ int data_bits_tmp = transform_data_bits(data_bits);
|
|
|
+ if (data_bits_tmp == -1) {
|
|
|
+ LOGE("Failed to set data bits");
|
|
|
+ return DATABITS_NOT_SUPPORT;
|
|
|
+ }
|
|
|
+ options_.c_cflag |= data_bits_tmp;
|
|
|
+
|
|
|
+ if (parity_mode == PARITY_ODD) {
|
|
|
+ options_.c_cflag |= PARENB;
|
|
|
+ options_.c_cflag |= PARODD;
|
|
|
+ } else if (parity_mode == PARITY_EVEN) {
|
|
|
+ options_.c_cflag &= ~PARODD;
|
|
|
+ } else if (parity_mode == PARITY_NONE) {
|
|
|
+ options_.c_cflag &= ~PARENB;
|
|
|
+
|
|
|
+ } else {
|
|
|
+ return PARITYMODE_NOT_SUPPORT;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (stop_bits == TWO) {
|
|
|
+ options_.c_cflag |= CSTOPB;
|
|
|
+ } else if (stop_bits == ONE) {
|
|
|
+ options_.c_cflag &= ~CSTOPB;
|
|
|
+ } else {
|
|
|
+ return STOPBITS_NOT_SUPPORT;
|
|
|
+ }
|
|
|
+ // 修改控制模式,保证程序不会占用串口
|
|
|
+ options_.c_cflag |= CLOCAL;
|
|
|
+ // 修改控制模式,使得能够从串口中读取输入数据
|
|
|
+ options_.c_cflag |= CREAD;
|
|
|
+
|
|
|
+ options_.c_cc[VMIN] = 1;
|
|
|
+ options_.c_cc[VTIME] = 10;
|
|
|
+ tcflush(fd_, TCIFLUSH);
|
|
|
+ tcsetattr(fd_, TCSANOW, &options_);
|
|
|
+
|
|
|
+ if (tcgetattr(fd_, &options_) != 0) {
|
|
|
+ LOGE("Failed to set serial port");
|
|
|
+ return CONFIG_FAIL;
|
|
|
+ }
|
|
|
+ LOGI("Success to set config.");
|
|
|
+
|
|
|
+ return OK;
|
|
|
+}
|
|
|
+
|
|
|
+Status Serial::change_baud(const int baud_speed) {
|
|
|
+ int baud_speed_tmp = transform_baud(baud_speed);
|
|
|
+ if (baud_speed_tmp == -1) {
|
|
|
+ LOGE("Failed to set baud speed");
|
|
|
+ return BAUD_NOT_SUPPORT;
|
|
|
+ }
|
|
|
+ cfsetispeed(&options_, baud_speed_tmp);
|
|
|
+ cfsetospeed(&options_, baud_speed_tmp);
|
|
|
+
|
|
|
+ return OK;
|
|
|
+}
|
|
|
+
|
|
|
+int Serial::write(const unsigned char* buffer, int length)
|
|
|
+{
|
|
|
+ return ::write(fd_, buffer, length);
|
|
|
+}
|
|
|
+
|
|
|
+int Serial::read(unsigned char* buffer, int length)
|
|
|
+{
|
|
|
+ return ::read(fd_, buffer, length);
|
|
|
+}
|
|
|
+
|
|
|
+static int transform_baud(int baud_speed)
|
|
|
+{
|
|
|
+ int baud_map[][2] = {{2400, B2400}, {4800, B4800}, {9600, B9600},
|
|
|
+ {19200, B19200}, {38400, B38400}, {57600, B57600},
|
|
|
+ {115200, B115200}};
|
|
|
+ for (size_t i = 0; i < sizeof(baud_map) / sizeof(int) / 2; i++) {
|
|
|
+ if (baud_map[i][0] == baud_speed) {
|
|
|
+ return baud_map[i][1];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+static int transform_data_bits(int data_bits)
|
|
|
+{
|
|
|
+ int map[][2] = {{5, CS5}, {6, CS6}, {7, CS7}, {8, CS8}};
|
|
|
+ for (size_t i = 0; i < sizeof(map) / sizeof(int) / 2; i++)
|
|
|
+ if (map[i][0] == data_bits)
|
|
|
+ return map[i][1];
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+} // namespace CommunicationStuff
|