用于串口通信的serial

1 介绍

This is a cross-platform library for interfacing with rs-232 serial like ports written in C++. It provides a modern C++ interface with a workflow designed to look and feel like PySerial, but with the speed and control provided by C++.

This library is in use in several robotics related projects and can be built and installed to the OS like most unix libraries with make and then sudo make install, but because it is a catkin project it can also be built along side other catkin projects in a catkin workspace.

Serial is a class that provides the basic interface common to serial libraries (open, close, read, write, etc…) and requires no extra dependencies. It also provides tight control over timeouts and control over handshaking lines.

相关资料:

  • Github:https://github.com/wjwwood/serial
  • 网站:http://wjwwood.github.com/serial/
  • API:http://wjwwood.github.com/serial/doc/1.1.0/index.html

2 安转serail

git clone https://github.com/wjwwood/serial.git
make
sudo make install

默认安装在/tmp/usr/local/目录下,/tmp下的文件每次重启后会清空,因此我们把安装文件拷贝到usr/local

sudo cp -r /tmp/usr/local/* /usr/local
source ~/.bashrc

3 使用serial

这里举两个栗子:

  • 第一个是serial包中提供的例程
  • 第二个是网上的资料:使用serial和ROS读写编码器

3.1 serial中的例程

3.1.1 代码

代码路径为serial/examples/serial_example.cc

/***
 * This example expects the serial port has a loopback on it.
 *
 * Alternatively, you could use an Arduino:
 *
 * <pre>
 *  void setup() {
 *    Serial.begin(<insert your baudrate here>);
 *  }
 *
 *  void loop() {
 *    if (Serial.available()) {
 *      Serial.write(Serial.read());
 *    }
 *  }
 * </pre>
 */

#include <string>
#include <iostream>
#include <cstdio>

// OS Specific sleep
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

#include "serial/serial.h"

using std::string;
using std::exception;
using std::cout;
using std::cerr;
using std::endl;
using std::vector;

void my_sleep(unsigned long milliseconds) {
#ifdef _WIN32
      Sleep(milliseconds); // 100 ms
#else
      usleep(milliseconds*1000); // 100 ms
#endif
}

void enumerate_ports()
{
	vector<serial::PortInfo> devices_found = serial::list_ports();

	vector<serial::PortInfo>::iterator iter = devices_found.begin();

	while( iter != devices_found.end() )
	{
		serial::PortInfo device = *iter++;

		printf( "(%s, %s, %s)\n", device.port.c_str(), device.description.c_str(),
     device.hardware_id.c_str() );
	}
}

void print_usage()
{
	cerr << "Usage: test_serial {-e|<serial port address>} ";
    cerr << "<baudrate> [test string]" << endl;
}

int run(int argc, char **argv)
{
  if(argc < 2) {
	  print_usage();
    return 0;
  }

  // Argument 1 is the serial port or enumerate flag
  string port(argv[1]);

  if( port == "-e" ) {
	  enumerate_ports();
	  return 0;
  }
  else if( argc < 3 ) {
	  print_usage();
	  return 1;
  }

  // Argument 2 is the baudrate
  unsigned long baud = 0;
#if defined(WIN32) && !defined(__MINGW32__)
  sscanf_s(argv[2], "%lu", &baud);
#else
  sscanf(argv[2], "%lu", &baud);
#endif

  // port, baudrate, timeout in milliseconds
  serial::Serial my_serial(port, baud, serial::Timeout::simpleTimeout(1000));

  cout << "Is the serial port open?";
  if(my_serial.isOpen())
    cout << " Yes." << endl;
  else
    cout << " No." << endl;

  // Get the Test string
  int count = 0;
  string test_string;
  if (argc == 4) {
    test_string = argv[3];
  } else {
    test_string = "Testing.";
  }

  // Test the timeout, there should be 1 second between prints
  cout << "Timeout == 1000ms, asking for 1 more byte than written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length()+1);

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  // Test the timeout at 250ms
  my_serial.setTimeout(serial::Timeout::max(), 250, 0, 250, 0);
  count = 0;
  cout << "Timeout == 250ms, asking for 1 more byte than written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length()+1);

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  // Test the timeout at 250ms, but asking exactly for what was written
  count = 0;
  cout << "Timeout == 250ms, asking for exactly what was written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length());

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  // Test the timeout at 250ms, but asking for 1 less than what was written
  count = 0;
  cout << "Timeout == 250ms, asking for 1 less than was written." << endl;
  while (count < 10) {
    size_t bytes_wrote = my_serial.write(test_string);

    string result = my_serial.read(test_string.length()-1);

    cout << "Iteration: " << count << ", Bytes written: ";
    cout << bytes_wrote << ", Bytes read: ";
    cout << result.length() << ", String read: " << result << endl;

    count += 1;
  }

  return 0;
}

int main(int argc, char **argv) {
  try {
    return run(argc, argv);
  } catch (exception &e) {
    cerr << "Unhandled Exception: " << e.what() << endl;
  }
}

3.1.2 使用

列出可用的端口号:

cd ~/serial/build/devel/lib/serial
./serial_example -e

输出:

(/dev/ttyS0, ttyS0, n/a)
(/dev/ttyS1, ttyS1, n/a)
(/dev/ttyS10, ttyS10, n/a)
(/dev/ttyS11, ttyS11, n/a)
(/dev/ttyS12, ttyS12, n/a)
(/dev/ttyS13, ttyS13, n/a)
(/dev/ttyS14, ttyS14, n/a)
(/dev/ttyS15, ttyS15, n/a)
(/dev/ttyS16, ttyS16, n/a)
(/dev/ttyS17, ttyS17, n/a)
(/dev/ttyS18, ttyS18, n/a)
(/dev/ttyS19, ttyS19, n/a)
(/dev/ttyS2, ttyS2, n/a)
(/dev/ttyS20, ttyS20, n/a)
(/dev/ttyS21, ttyS21, n/a)
(/dev/ttyS22, ttyS22, n/a)
(/dev/ttyS23, ttyS23, n/a)
(/dev/ttyS24, ttyS24, n/a)
(/dev/ttyS25, ttyS25, n/a)
(/dev/ttyS26, ttyS26, n/a)
(/dev/ttyS27, ttyS27, n/a)
(/dev/ttyS28, ttyS28, n/a)
(/dev/ttyS29, ttyS29, n/a)
(/dev/ttyS3, ttyS3, n/a)
(/dev/ttyS30, ttyS30, n/a)
(/dev/ttyS31, ttyS31, n/a)
(/dev/ttyS4, ttyS4, n/a)
(/dev/ttyS5, ttyS5, n/a)
(/dev/ttyS6, ttyS6, n/a)
(/dev/ttyS7, ttyS7, n/a)
(/dev/ttyS8, ttyS8, n/a)
(/dev/ttyS9, ttyS9, n/a)
(/dev/ttyUSB0, Silicon Labs CP2102N USB to UART Bridge Controller 0001, USB VID:PID=10c4:ea60 SNR=0001)

可以看出,/dev/ttyUSB0是我们插入设备所对应的端口。

使用serial进行端口打开,读和写的测试,分两种情况:

(1)如果没有给定发送的内容,则默认为:Testing.,8个字节。

./serial_example /dev/ttyUSB0 115200

输出:

Is the serial port open? Yes.
Timeout == 1000ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 8, Bytes read: 9, String read: 05,-0.000
Iteration: 1, Bytes written: 8, Bytes read: 1, String read: 6
Iteration: 2, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 3, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 4, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 5, Bytes written: 8, Bytes read: 0, String read: 
Iteration: 6, Bytes written: 8, Bytes read: 9, String read: $6.112709
Iteration: 7, Bytes written: 8, Bytes read: 9, String read: ,-7.33860
Iteration: 8, Bytes written: 8, Bytes read: 9, String read: 2,-1.2211
Iteration: 9, Bytes written: 8, Bytes read: 9, String read: 05,0.0014
Timeout == 250ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 8, Bytes read: 9, String read: 13,-0.000
Iteration: 1, Bytes written: 8, Bytes read: 9, String read: 220,-0.00
Iteration: 2, Bytes written: 8, Bytes read: 9, String read: 1162,-98.
Iteration: 3, Bytes written: 8, Bytes read: 9, String read: 086143,-3
Iteration: 4, Bytes written: 8, Bytes read: 9, String read: 9.784908,
Iteration: 5, Bytes written: 8, Bytes read: 9, String read: 224.96165
Iteration: 6, Bytes written: 8, Bytes read: 9, String read: 4*
$6.10
Iteration: 7, Bytes written: 8, Bytes read: 9, String read: 3131,-7.3
Iteration: 8, Bytes written: 8, Bytes read: 9, String read: 19447,-1.
Iteration: 9, Bytes written: 8, Bytes read: 9, String read: 221105,0.
Timeout == 250ms, asking for exactly what was written.
Iteration: 0, Bytes written: 8, Bytes read: 8, String read: 000081,0
Iteration: 1, Bytes written: 8, Bytes read: 8, String read: .000047,
Iteration: 2, Bytes written: 8, Bytes read: 8, String read: 0.000169
Iteration: 3, Bytes written: 8, Bytes read: 8, String read: ,-98.093
Iteration: 4, Bytes written: 8, Bytes read: 8, String read: 002,-39.
Iteration: 5, Bytes written: 8, Bytes read: 8, String read: 782791,2
Iteration: 6, Bytes written: 8, Bytes read: 8, String read: 24.96600
Iteration: 7, Bytes written: 8, Bytes read: 8, String read: 3*
$6.1
Iteration: 8, Bytes written: 8, Bytes read: 8, String read: 03131,-7
Iteration: 9, Bytes written: 8, Bytes read: 8, String read: .319447,
Timeout == 250ms, asking for 1 less than was written.
Iteration: 0, Bytes written: 8, Bytes read: 7, String read: -1.2211
Iteration: 1, Bytes written: 8, Bytes read: 7, String read: 05,0.00
Iteration: 2, Bytes written: 8, Bytes read: 7, String read: 0081,0.
Iteration: 3, Bytes written: 8, Bytes read: 7, String read: 000047,
Iteration: 4, Bytes written: 8, Bytes read: 7, String read: 0.00016
Iteration: 5, Bytes written: 8, Bytes read: 7, String read: 9,-98.1
Iteration: 6, Bytes written: 8, Bytes read: 7, String read: 00227,-
Iteration: 7, Bytes written: 8, Bytes read: 7, String read: 39.7808
Iteration: 8, Bytes written: 8, Bytes read: 7, String read: 95,224.
Iteration: 9, Bytes written: 8, Bytes read: 7, String read: 970626*

(2)也可以指定发送内容,比如:haha,4个字节。

./serial_example /dev/ttyUSB0 115200  haha
Is the serial port open? Yes.
Timeout == 1000ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 4, Bytes read: 5, String read: 0097,
Iteration: 1, Bytes written: 4, Bytes read: 4, String read: -99�
Iteration: 2, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 3, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 4, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 5, Bytes written: 4, Bytes read: 0, String read: 
Iteration: 6, Bytes written: 4, Bytes read: 5, String read: $6.10
Iteration: 7, Bytes written: 4, Bytes read: 5, String read: 3131,
Iteration: 8, Bytes written: 4, Bytes read: 5, String read: -7.35
Iteration: 9, Bytes written: 4, Bytes read: 5, String read: 2968,
Timeout == 250ms, asking for 1 more byte than written.
Iteration: 0, Bytes written: 4, Bytes read: 5, String read: -1.27
Iteration: 1, Bytes written: 4, Bytes read: 5, String read: 1386,
Iteration: 2, Bytes written: 4, Bytes read: 5, String read: 0.000
Iteration: 3, Bytes written: 4, Bytes read: 5, String read: 087,0
Iteration: 4, Bytes written: 4, Bytes read: 5, String read: .0000
Iteration: 5, Bytes written: 4, Bytes read: 5, String read: 07,0.
Iteration: 6, Bytes written: 4, Bytes read: 5, String read: 00032
Iteration: 7, Bytes written: 4, Bytes read: 5, String read: 1,-98
Iteration: 8, Bytes written: 4, Bytes read: 5, String read: .1223
Iteration: 9, Bytes written: 4, Bytes read: 5, String read: 29,-3
Timeout == 250ms, asking for exactly what was written.
Iteration: 0, Bytes written: 4, Bytes read: 4, String read: 9.37
Iteration: 1, Bytes written: 4, Bytes read: 4, String read: 4092
Iteration: 2, Bytes written: 4, Bytes read: 4, String read: ,224
Iteration: 3, Bytes written: 4, Bytes read: 4, String read: .914
Iteration: 4, Bytes written: 4, Bytes read: 4, String read: 001*
Iteration: 5, Bytes written: 4, Bytes read: 4, String read: 
$6
Iteration: 6, Bytes written: 4, Bytes read: 4, String read: .098
Iteration: 7, Bytes written: 4, Bytes read: 4, String read: 342,
Iteration: 8, Bytes written: 4, Bytes read: 4, String read: -7.3
Iteration: 9, Bytes written: 4, Bytes read: 4, String read: 4817
Timeout == 250ms, asking for 1 less than was written.
Iteration: 0, Bytes written: 4, Bytes read: 3, String read: 9,-
Iteration: 1, Bytes written: 4, Bytes read: 3, String read: 1.2
Iteration: 2, Bytes written: 4, Bytes read: 3, String read: 258
Iteration: 3, Bytes written: 4, Bytes read: 3, String read: 94,
Iteration: 4, Bytes written: 4, Bytes read: 3, String read: 0.0
Iteration: 5, Bytes written: 4, Bytes read: 3, String read: 008
Iteration: 6, Bytes written: 4, Bytes read: 3, String read: 86,
Iteration: 7, Bytes written: 4, Bytes read: 3, String read: -0.
Iteration: 8, Bytes written: 4, Bytes read: 3, String read: 000
Iteration: 9, Bytes written: 4, Bytes read: 3, String read: 260

4 使用serial和ROS读写编码器

这部分内容参考网上的资料:

  • 博客:https://blog.csdn.net/SimileciWH/article/details/84975951
  • Github:https://github.com/SimileciWH/get_odomData_usbSerial

可以先看博客,再看代码,但博客写得不是很完善,很多细节在代码里。

代码涉及了serial的C++和Python使用方法,还结合了ROS,值得学习。

编译工程时,如果遇到找不到serial的问题,可以尝试:

安装ROS serial package

sudo apt-get install ros-kinetic-serial

CMakeLists.txt中添加:

set(serial_DIR /usr/local)

参考:http://forums.trossenrobotics.com/archive/index.php/t-7938.html?s=ab912dc757e6846eabeaa40bafd7fd88

通过看两个代码,发现下面两段代码作用应该是相同的,都是设置端口,波特率和延迟时间,然后打开端口。

// port, baudrate, timeout in milliseconds
serial::Serial my_serial(port, baud, serial::Timeout::simpleTimeout(1000));
serial::Serial ros_ser;
ros_ser.setPort("/dev/ttyUSB0");
ros_ser.setBaudrate(115200);
serial::Timeout to = serial::Timeout::simpleTimeout(1000);
ros_ser.setTimeout(to);
ros_ser.open();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章