嗯,今天我们来结束boost的asio吧,如大家所想,既然asio是用来通信用的,那么自然也少不了关于串口的操作,对于串口,他比起网络来要简单得多,尤其又是在我们都明白asio的网络是怎么工作的情况下来理解串口基本都不需要理解的,同样的操作方式我们只是简单的换个 通信模式就完成了串口的操作。

关于boost的东西,我基本不会和大家说得很详细,因为关于这方面的细节网络上有不少资料,但是网上基本就是介绍里面怎么的组件功能和用法,却没有一个算是很完整的例子,所以我们这里基本就算是补全这个所谓的全面的例子而已,而这里也只是让大家知道,当我们想要使用这些东西的时候可以有的放矢的去查询资料,就比如,当我们想要通过网络来通信的时候,我们可能会想起boost里面好像有个组件是专门来用做这件事,于是我们就带着目的性的去查询这个组件的具体方式,想我们想要操作字符串的时候,我们会想起boost的里面的专门用来处理字符串的algorithm组件,而且还有功能更加强大的正则表达式,当我们想要操作操作系统相关例如文件系统那么我们则会想起boost的filesystem组件,当我们想要在我们程序中运用观察者模式的时候,可能我们会第一时间想起boost的signal组件等等,这些东西都很好用,我的程序基本就是STL和boost的东西组成的,因为这两者基本就可以满足我们基本的所有需求.

和前面的两讲一样,我们的框架都是基本如出一辙,所以关于串口的细节我也不多说,这里还是提供一个完整的类,大家如果工作中会用到串口操作的话,可以直接用他就行,当然如果自己想要重写一些定制的,那么在没有参考的情况下也可以参考。



//-----------------------------------------------------

#pragma once

#include <string>

#include <stdlib.h>

#include <iostream>

#include <memory>

#include <vector>

#include <boost/asio/serial_port.hpp>

#include <thread>

#include <Logger.h>

using namespace std;


typedef std::function<void(const std::string&)> SERIAL_FUN;


class HSerial_Port

{

public:


HSerial_Port();

virtual ~HSerial_Port();

void bindFun(SERIAL_FUN fun);

void Connect(const std::string &SerialName, unsigned port = 115200, bool isAsyni = true, int stopbit = 1);

//--------------------------------------

// 同步操作

//--------------------------------------

int Send(const std::string& send);

int Read(std::string& str, size_t size = 8192);


//------------------------------------

//同步操作,主要用于通信指令上的操作

//------------------------------------

int write(char* sendmsg, size_t size);

std::vector<char> readAll();



//-------------------------------

// 异步操作

//-------------------------------

void postSend(const std::string& sendmsg);

void postReceive();

bool IsConnected();

void close();

bool is_open(){

return m_serial->is_open();

}

protected:

void read_handle(const boost::system::error_code& e, std::shared_ptr<std::vector<char>> read_msg);

void send_handle(const boost::system::error_code& e, const std::string& send_msg);

private:

std::shared_ptr<boost::asio::serial_port> m_serial;

boost::asio::io_service m_ios;

bool b_IsConnect;

SERIAL_FUN m_recall_fun;

std::shared_ptr<boost::asio::io_service::work> m_work;

std::thread m_thread;

std::string m_com_port;

unsigned m_baud_rate;

unsigned m_stop_bit;

bool b_is_asyn;

bool b_is_first{ true };

Logger g_logger;

};


//------------------------------------

#include "HSerial_Port.h"

#include <utility>

#include <boost/algorithm/string.hpp>




HSerial_Port::HSerial_Port() :m_recall_fun(nullptr), m_time_fun(nullptr)

{

m_work = std::shared_ptr<boost::asio::io_service::work>(new boost::asio::io_service::work(m_ios));

m_thread = std::thread([&](){m_ios.run(); });

g_logger.EnableConsole(true);


}


HSerial_Port::~HSerial_Port(){

if (m_thread.joinable()){

m_thread.join();

}

}




void HSerial_Port::Connect(const std::string &SerialName, unsigned port, bool isAsyni,int stopbit)

{

try{

m_serial = std::shared_ptr<boost::asio::serial_port>(new boost::asio::serial_port(m_ios, SerialName));

}

catch (...){

g_logger.log("Create Serial port fail......");

return;

}

m_serial->set_option(boost::asio::serial_port::baud_rate(port));

m_serial->set_option(boost::asio::serial_port::character_size(8));

m_serial->set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none));

m_serial->set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none));

if (stopbit == 2){

m_serial->set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::two));

}

else if (stopbit == 1){

m_serial->set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one));

}

m_stop_bit = (stopbit;

m_com_port = SerialName;

m_baud_rate = port;

b_is_first = true;

b_is_asyn = isAsyni;

if (isAsyni){

postReceive();

}


}


void HSerial_Port::bindFun(SERIAL_FUN fun)

{


m_recall_fun = fun;

}



int HSerial_Port::Send(const std::string &send)

{

if(!IsConnected())

return false;

int size = m_serial->write_some(boost::asio::buffer(send, send.size()));

return size;

}


int HSerial_Port::Read(std::string &str, size_t size)

{

if(m_serial->is_open())

{

std::vector<char> v(size, 0); //8k

long long size = m_serial->read_some(boost::asio::buffer(v));

if (size == 0)

return 0;

str = std::string(&(v)[0]);

return size;

}

return 0;

}


int HSerial_Port::write(char* sendmsg, size_t size){

if (!IsConnected())

return false;

int n_size = m_serial->write_some(boost::asio::buffer(sendmsg,size));

return n_size;

}


std::vector<char> HSerial_Port::readAll(){

if (m_serial->is_open())

{

std::vector<char> v(8192, 0); //8k

long long size = m_serial->read_some(boost::asio::buffer(v));

if (size == 0)

return std::vector<char>();

return std::vector<char>(v.begin(),v.begin()+size);

}

}


bool HSerial_Port::IsConnected()

{


if (m_serial->is_open())

return true;

return false;

}


void HSerial_Port::close()

{

if (IsConnected())

m_serial->close();


}


void HSerial_Port::postSend(const std::string& sendmsg){

if (sendmsg.empty())

return;

if (!m_serial->is_open()){

g_logger.log("Com close.......");

Connect(m_com_port, m_baud_rate,b_is_asyn,m_stop_bit);

return;

}

m_serial->async_write_some(boost::asio::buffer(&sendmsg[0],sendmsg.size()), std::bind(&HSerial_Port::send_handle, this, std::placeholders::_1, sendmsg));

}


void HSerial_Port::postReceive(){


if (!m_serial->is_open()){

g_logger.log("Com unable open......");

Connect(m_com_port, m_baud_rate,b_is_asyn,m_stop_bit);

return;

}


std::shared_ptr<std::vector<char>> v(new std::vector<char>(8192, 0));


m_serial->async_read_some(boost::asio::buffer(*v), std::bind(&HSerial_Port::read_handle, this, std::placeholders::_1, v));


}


void HSerial_Port::read_handle(const boost::system::error_code& e, std::shared_ptr<std::vector<char>> read_msg){


if (e){

if (IsConnected()){

postReceive();

return;

}

else{

Connect(m_com_port, m_baud_rate,b_is_asyn,m_stop_bit);

g_logger.log("serial port close!!!!!");

return;

}

}

std::string data = &((*read_msg)[0]);

if(m_recall_fun)

m_recall_fun(data);

postReceive();

}


void HSerial_Port::send_handle(const boost::system::error_code& e, const std::string& send_msg){

if (e){

g_logger.log("serial port close!!!!!");

return;

}

}


//-------------------------------------

使用起来相当的简单,比网络还要简单得多,如下:

//-------------------------------------------

HSerial_Port serial;

serial.Connect("COM1",9600,true,1);

serial.bindFun([](std::string& str){std::cout<<str<<std::endl;});

serial.PostSend("Hello,this is serialport");

愉快的工作吧.......

//-------------------------------------------

在上面的例子中我们使用了异步通信,所以我们只管发送就行,给他注册一个回调函数,当收到信息就会调用该函数,然后将信息打印出来就ok。


关于boost的asio就算是结束了,当然我没有讲得很细,所以如果有同学想要了解得更多,可以去网上查询资料,当然也可以直接问我。