commit 0133cc2920740e0b932433bd097674c4420527e5 Author: taynpg Date: Sat May 18 22:53:33 2024 +0800 初始 diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..fdc4b08 --- /dev/null +++ b/.clang-format @@ -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 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd1c6a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +.cache +*.user \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..651b2fd --- /dev/null +++ b/.vscode/settings.json @@ -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" + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..bd8887c --- /dev/null +++ b/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c97fcce --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# 简介 + +封装的 asio 的串口读写库。 \ No newline at end of file diff --git a/libserial/CMakeLists.txt b/libserial/CMakeLists.txt new file mode 100644 index 0000000..99d76c8 --- /dev/null +++ b/libserial/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/libserial/serial.cpp b/libserial/serial.cpp new file mode 100644 index 0000000..a78d161 --- /dev/null +++ b/libserial/serial.cpp @@ -0,0 +1,246 @@ +#include "serial.h" + +#include +#include + +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(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 \ No newline at end of file diff --git a/libserial/serial.h b/libserial/serial.h new file mode 100644 index 0000000..e6fd3a6 --- /dev/null +++ b/libserial/serial.h @@ -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 + +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 \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..25d64b8 --- /dev/null +++ b/main.cpp @@ -0,0 +1,28 @@ +#include +#include + +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; +} \ No newline at end of file