serial_port.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * 文件功能:串口参数设置、数据读写等功能的实现
  3. * 创建人:yangshuai15
  4. * 日 期:2021/6/16
  5. */
  6. #include "serial_port.h"
  7. #include <dirent.h>
  8. #include <fcntl.h>
  9. #include <iostream>
  10. #include <stdlib.h>
  11. #include <termios.h>
  12. #include <unistd.h>
  13. namespace utils {
  14. SerialPort::SerialPort(const std::string& devpath, const OpenOptions& options, bool is_block)
  15. : _path(devpath)
  16. , _open_options(options)
  17. , _is_block(is_block)
  18. {
  19. }
  20. SerialPort::~SerialPort()
  21. {
  22. close(_tty_fd);
  23. }
  24. bool SerialPort::start()
  25. {
  26. return serial_port_init();
  27. }
  28. //::read(_tty_fd, data, length)
  29. int SerialPort::read(char* buffer, int buf_len)
  30. {
  31. return ::read(_tty_fd, buffer, buf_len);
  32. }
  33. // int SerialPort::write(char* buffer, int buf_len)
  34. // {
  35. // return ::write(_tty_fd, buffer, buf_len);
  36. // }
  37. int SerialPort::write(char* buffer, int buf_len)
  38. {
  39. int offset = 0, total = buf_len;
  40. ssize_t wcnt = 0;
  41. do {
  42. wcnt = ::write(_tty_fd, buffer + offset, total);
  43. if (wcnt > 0) {
  44. offset += wcnt;
  45. total -= wcnt;
  46. } else if (wcnt < 0 && errno == EINTR) {
  47. usleep(1000);
  48. continue;
  49. } else {
  50. printf("write data to serial failed. errno:%d \n", errno);
  51. break;
  52. }
  53. } while (total > 0);
  54. // std::cout << " wcnt " << wcnt << std::endl;
  55. return 0;
  56. // int wcnt = ::write(_tty_fd, buffer, buf_len);
  57. // std::cout << " 1wcnt2 " << wcnt << std::endl;
  58. // return wcnt;
  59. // return ::write(_tty_fd, buffer, buf_len);
  60. }
  61. int SerialPort::get_tty_fd()
  62. {
  63. if (_tty_fd > 0) {
  64. return _tty_fd;
  65. }
  66. return -1;
  67. }
  68. bool SerialPort::serial_port_init()
  69. {
  70. if (!_path.size()) {
  71. return false;
  72. }
  73. if (_is_block) {
  74. _tty_fd = open(_path.c_str(), O_RDWR | O_NOCTTY);
  75. } else {
  76. _tty_fd = open(_path.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
  77. }
  78. if (_tty_fd < 0) {
  79. std::cout << "open serial device " << _path << " failed!" << std::endl;
  80. return false;
  81. }
  82. struct termios tios;
  83. termios_options(tios, _open_options);
  84. tcsetattr(_tty_fd, TCSANOW, &tios);
  85. tcflush(_tty_fd, TCIOFLUSH);
  86. return true;
  87. }
  88. void SerialPort::termios_options(termios& tios, const OpenOptions& options)
  89. {
  90. tcgetattr(_tty_fd, &tios);
  91. cfmakeraw(&tios);
  92. tios.c_cflag &= ~(CSIZE | CRTSCTS);
  93. tios.c_iflag &= ~(IXON | IXOFF | IXANY | IGNPAR);
  94. tios.c_lflag &= ~(ECHOK | ECHOCTL | ECHOKE);
  95. tios.c_oflag &= ~(OPOST | ONLCR);
  96. cfsetispeed(&tios, options.baud_rate);
  97. cfsetospeed(&tios, options.baud_rate);
  98. tios.c_iflag |= (options.xon ? IXON : 0) | (options.xoff ? IXOFF : 0) | (options.xany ? IXANY : 0);
  99. // data bits
  100. int databits[] = { CS5, CS6, CS7, CS8 };
  101. tios.c_cflag &= ~0x30;
  102. tios.c_cflag |= databits[options.data_bits];
  103. // stop bits
  104. if (options.stop_bits == STOP_BITS_2) {
  105. tios.c_cflag |= CSTOPB;
  106. } else {
  107. tios.c_cflag &= ~CSTOPB;
  108. }
  109. // parity 奇偶校验
  110. if (options.parity == PARITY_NONE) {
  111. tios.c_cflag &= ~PARENB;
  112. } else {
  113. tios.c_cflag |= PARENB;
  114. if (options.parity == PARITY_MARK) {
  115. tios.c_cflag |= PARMRK;
  116. } else {
  117. tios.c_cflag &= ~PARMRK;
  118. }
  119. if (options.parity == PARITY_ODD) {
  120. tios.c_cflag |= PARODD;
  121. } else {
  122. tios.c_cflag &= ~PARODD;
  123. }
  124. }
  125. tios.c_cc[VMIN] = options.vmin;
  126. tios.c_cc[VTIME] = options.vtime;
  127. }
  128. } // namespace sensor