This commit is contained in:
taynpg 2024-05-18 22:53:33 +08:00
commit 0133cc2920
9 changed files with 544 additions and 0 deletions

38
.clang-format Normal file
View File

@ -0,0 +1,38 @@
# .clang-format
# 风格格式化
BasedOnStyle: Google
# 4 空格缩进
IndentWidth: 4
# 连续对齐变量的声明
AlignConsecutiveDeclarations: true
# 指针左侧对齐
PointerAlignment: Left
# 访问说明符(public、private等)的偏移
AccessModifierOffset: -4
# 大括号
BreakBeforeBraces: Custom
BraceWrapping:
# 函数定义后面大括号在新行
AfterFunction: true
# class定义后面
AfterClass: true
# 去除C++11的列表初始化的大括号{后和}前的空格
Cpp11BracedListStyle: true
# 允许重新排版注释
ReflowComments: true
# 允许排序#include
SortIncludes: false
# 在尾随的评论前添加的空格数(只适用于//)
SpacesBeforeTrailingComments: 3
# tab宽度
TabWidth: 4
# 构造函数的初始化列表要么都在同一行,要么都各自一行
ConstructorInitializerAllOnOneLineOrOnePerLine: true
# 每行字符的限制,0表示没有限制
ColumnLimit: 100
# 允许短的块放在同一行
AllowShortBlocksOnASingleLine: false
# 是否允许短函数在一行
AllowShortFunctionsOnASingleLine: InlineOnly

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
build
.cache
*.user

122
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,122 @@
{
"files.autoSave": "onFocusChange",
"editor.fontSize": 16,
"editor.fontFamily": "'FiraCode Nerd Font Mono', 'FiraCode Nerd Font Mono', 'FiraCode Nerd Font Mono'",
"cmake.configureOnOpen": true,
"cmake.debugConfig": {
"console": "integratedTerminal",
"setupCommands": [
{
"description": "-gdb-set charset utf-8",
"text": "-gdb-set charset UTF-8"
},
{
"description": "Enable gdb pretty-printing",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
"cmake.environment": {
"PATH": "${env:PATH};C:/"
},
"cmake.options.statusBarVisibility": "visible",
"cmake.generator": "Ninja",
"C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json",
"C_Cpp.default.cppStandard": "c++14",
"editor.inlayHints.enabled": "off",
"editor.unicodeHighlight.allowedLocales": {
"ja": true,
"zh-hant": true,
"zh-hans": true
},
"files.associations": {
"xstring": "cpp",
"vector": "cpp",
"*.ipp": "cpp",
"algorithm": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"codecvt": "cpp",
"complex": "cpp",
"condition_variable": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"forward_list": "cpp",
"fstream": "cpp",
"functional": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"iterator": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"queue": "cpp",
"random": "cpp",
"ratio": "cpp",
"set": "cpp",
"shared_mutex": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"strstream": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"utility": "cpp",
"valarray": "cpp",
"variant": "cpp",
"xfacet": "cpp",
"xhash": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocbuf": "cpp",
"xlocinfo": "cpp",
"xlocmes": "cpp",
"xlocmon": "cpp",
"xlocnum": "cpp",
"xloctime": "cpp",
"xmemory": "cpp",
"xmemory0": "cpp",
"xstddef": "cpp",
"xtr1common": "cpp",
"xtree": "cpp",
"xutility": "cpp"
}
}

20
CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.5)
project(SerialOprTest LANGUAGES CXX)
set(CMAKE_PREFIX_PATH
${CMAKE_PREFIX_PATH}
"C:/dev/boost"
)
set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
if (MSVC)
add_compile_options(/source-charset:utf-8)
endif()
include_directories(libserial)
add_subdirectory(libserial)
add_executable(SerialOprTest main.cpp)
target_link_libraries(SerialOprTest PRIVATE SerialOpr)

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# 简介
封装的 asio 的串口读写库。

17
libserial/CMakeLists.txt Normal file
View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.5)
project(SerialOpr LANGUAGES CXX)
if (MSVC)
add_definitions(-D_WIN32_WINNT=0x0601)
add_compile_options(/source-charset:utf-8)
endif()
include_directories(${CMAKE_SOURCE_DIR}/3rd/asio-1.30.2/include)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost REQUIRED COMPONENTS system)
add_library(SerialOpr SHARED serial.h serial.cpp)
target_link_libraries(SerialOpr PRIVATE ${Boost_LIBRARIES})
target_compile_definitions(SerialOpr PRIVATE SERIALOPR_LIB DYNAMIC_DLL)

246
libserial/serial.cpp Normal file
View File

@ -0,0 +1,246 @@
#include "serial.h"
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
namespace cppbox {
using serial_port = boost::asio::serial_port;
class CSerialOprImp
{
public:
CSerialOprImp()
: timer_(io_),
baud_rate_(serial_port::baud_rate(19200)),
stop_bits_(serial_port::stop_bits::one),
parity_(serial_port::parity::none),
flow_control_(serial_port::flow_control::none)
{
port_ = new boost::asio::serial_port(io_);
error_ = new char[1024];
std::memset(error_, 0x0, 1024);
}
~CSerialOprImp() { delete[] error_; }
public:
void set_port(const char* port)
{
std::memset(port_name_, 0x0, sizeof(port_name_));
std::snprintf(port_name_, sizeof(port_name_), "%s", port);
}
int open()
{
port_->open(port_name_, ec_);
if (!port_->is_open()) {
std::memset(error_, 0x0, 1024);
std::snprintf(error_, 1024, "%s", ec_.what().c_str());
return ec_.value();
}
port_->set_option(baud_rate_, ec_);
port_->set_option(flow_control_, ec_);
port_->set_option(parity_, ec_);
port_->set_option(stop_bits_, ec_);
port_->set_option(character_size_, ec_);
return 0;
}
void close()
{
if (port_->is_open()) {
port_->close();
}
}
void write(const char* data, int len)
{
}
int read(char* data, int size)
{
bytes_transferred_ = 0;
io_.reset();
timer_.expires_from_now(boost::posix_time::milliseconds(time_out_));
timer_.async_wait(
boost::bind(&CSerialOprImp::time_out, this, boost::asio::placeholders::error));
port_->async_read_some(
boost::asio::buffer(buffer_),
boost::bind(&CSerialOprImp::handle_read, this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
io_.run();
if (size < bytes_transferred_) {
return -1;
}
if (bytes_transferred_ > 0) {
std::memcpy(data, buffer_, bytes_transferred_);
return static_cast<int>(bytes_transferred_);
}
return 0;
}
const char* get_last_error() const { return error_; }
void set_timeout(uint64_t timeout) { time_out_ = timeout; }
void set_baudrate(uint32_t baudrate) { baud_rate_ = serial_port::baud_rate(baudrate); }
void set_databits(serial_port::character_size size) { character_size_ = size; }
void set_parity(serial_port::parity parity) { parity_ = parity; }
void set_stopbits(serial_port::stop_bits stop_bits) { stop_bits_ = stop_bits; }
void set_flow_control(serial_port::flow_control flow_control) { flow_control_ = flow_control; }
private:
void time_out(const boost::system::error_code& code)
{
if (code) {
return;
}
port_->cancel();
}
void handle_read(const boost::system::error_code& error, std::size_t bytes_transferred)
{
if (!error) {
bytes_transferred_ = bytes_transferred;
timer_.cancel();
}
}
private:
char port_name_[128]{};
serial_port::baud_rate baud_rate_;
serial_port::character_size character_size_{8};
serial_port::stop_bits stop_bits_;
serial_port::parity parity_;
uint64_t time_out_{1000};
serial_port::flow_control flow_control_;
private:
std::size_t bytes_transferred_{};
boost::asio::io_context io_{};
boost::asio::serial_port* port_{};
boost::system::error_code ec_{};
char buffer_[512]{};
boost::asio::deadline_timer timer_;
char* error_{};
};
CSerialOpr::CSerialOpr()
{
imp_ = new CSerialOprImp();
}
CSerialOpr::~CSerialOpr()
{
delete imp_;
}
void CSerialOpr::set_port(const char* port)
{
imp_->set_port(port);
}
void CSerialOpr::set_baudrate(uint32_t baudrate)
{
imp_->set_baudrate(baudrate);
}
void CSerialOpr::set_data_bits(DataBits data_bits)
{
switch (data_bits) {
case D5:
imp_->set_databits(serial_port::character_size(5));
break;
case D6:
imp_->set_databits(serial_port::character_size(6));
break;
case D7:
imp_->set_databits(serial_port::character_size(7));
break;
case D8:
imp_->set_databits(serial_port::character_size(8));
break;
default:
imp_->set_databits(serial_port::character_size(5));
break;
}
}
void CSerialOpr::set_stop_bits(StopBits stop_bits)
{
switch (stop_bits) {
case OneStop:
imp_->set_stopbits(serial_port::stop_bits(serial_port::stop_bits::one));
break;
case OneAndHalfStop:
imp_->set_stopbits(serial_port::stop_bits(serial_port::stop_bits::onepointfive));
break;
case TwoStop:
imp_->set_stopbits(serial_port::stop_bits(serial_port::stop_bits::two));
break;
default:
imp_->set_stopbits(serial_port::stop_bits(serial_port::stop_bits::one));
break;
}
}
void CSerialOpr::set_parity(Parity parity)
{
switch (parity) {
case EvenParity:
imp_->set_parity(serial_port::parity(serial_port::parity::even));
break;
case OddParity:
imp_->set_parity(serial_port::parity(serial_port::parity::odd));
break;
default:
imp_->set_parity(serial_port::parity(serial_port::parity::none));
break;
}
}
void CSerialOpr::set_flow_control(FlowControl flow_control)
{
switch (flow_control) {
case NoFlowControl:
imp_->set_flow_control(serial_port::flow_control(serial_port::flow_control::none));
break;
case HardwareControl:
imp_->set_flow_control(serial_port::flow_control(serial_port::flow_control::hardware));
break;
case SoftwareControl:
imp_->set_flow_control(serial_port::flow_control(serial_port::flow_control::software));
break;
default:
imp_->set_flow_control(serial_port::flow_control(serial_port::flow_control::none));
break;
}
}
void CSerialOpr::set_timeout(uint64_t timeout)
{
imp_->set_timeout(timeout);
}
int CSerialOpr::open()
{
return imp_->open();
}
void CSerialOpr::close()
{
imp_->close();
}
int CSerialOpr::read(char* data, int size)
{
return imp_->read(data, size);
}
int CSerialOpr::write(const char* data)
{
return 0;
}
const char* CSerialOpr::get_last_error() const
{
return imp_->get_last_error();
}
} // namespace cppbox

67
libserial/serial.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef SERIAL_OPERATE
#define SERIAL_OPERATE
#if defined(DYNAMIC_DLL)
#if defined(_MSC_VER)
#define CPP_SERIALOPR_EXPORT __declspec(dllexport)
#define CPP_SERIALOPR_IMPORT __declspec(dllimport)
#else
#define CPP_SERIALOPR_EXPORT __attribute__((visibility("default")))
#define CPP_SERIALOPR_IMPORT __attribute__((visibility("default")))
#endif
#ifdef SERIALOPR_LIB
#define SERIALOPR_API CPP_SERIALOPR_EXPORT
#else
#define SERIALOPR_API CPP_SERIALOPR_IMPORT
#endif
#else
#define SERIALOPR_API
#endif
#include <cstdint>
namespace cppbox {
enum DataBits { D5 = 5, D6 = 6, D7 = 7, D8 = 8, UnKnowBits = -1 };
enum StopBits { OneStop = 1, OneAndHalfStop = 3, TwoStop = 2, UnknownStopBits = -1 };
enum Parity {
NoParity = 0,
EvenParity = 2,
OddParity = 1
};
enum FlowControl { NoFlowControl, HardwareControl, SoftwareControl, UnknownFlowControl = -1 };
class CSerialOprImp;
class SERIALOPR_API CSerialOpr
{
public:
CSerialOpr();
~CSerialOpr();
public:
void set_port(const char* port);
void set_baudrate(uint32_t baudrate);
void set_data_bits(DataBits data_bits);
void set_stop_bits(StopBits stop_bits);
void set_parity(Parity parity);
void set_flow_control(FlowControl flow_control);
void set_timeout(uint64_t timeout);
public:
int open();
void close();
int read(char* data, int size);
int write(const char* data);
const char* get_last_error() const;
private:
CSerialOprImp* imp_{};
};
} // namespace cppbox
#endif

28
main.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <iostream>
#include <serial.h>
using namespace cppbox;
int main()
{
char buffer[512]{};
CSerialOpr opr;
opr.set_baudrate(19200);
opr.set_data_bits(DataBits::D8);
opr.set_flow_control(FlowControl::NoFlowControl);
opr.set_parity(Parity::EvenParity);
opr.set_port("COM2");
opr.set_timeout(10 * 1000);
opr.set_stop_bits(StopBits::OneStop);
if (opr.open() != 0) {
return false;
}
int read_size = opr.read(buffer, sizeof(buffer));
return 0;
}