CSerialPort Tutorial 4.3.x (2) - Introduction to CSerialPort Source Code
foreword
The CSerialPort project is a lightweight open source cross-platform serial port class library based on C/C++, which can easily realize serial port reading and writing across platforms and multiple operating systems, and also supports C#, Java, Python, Node.js, etc.
The open source protocol of the CSerialPort project has adopted the GNU Lesser General Public License v3.0 since version V3.0.0.171216
In order to allow developers to better use CSerialPort for development, a CSerialPort tutorial series based on version 4.3.x is specially written.
CSerialPort project address:
This article CSerialPort 4.3.0
introduces the version source code.
1. CSerialPort source directory structure
CSerialPort # root
+--- .clang-format # code format 代码规范
├── bindings # 第三方语言接口
│ ├── c # c interface c接口
│ ├── csharp # csharp interface c#接口
│ ├── java # java interface java接口
│ ├── javascript # javascript interface javascript接口
│ └── python # python interface python接口
├── CHANGELOG.md # change log 修改日志
├── cmake # cross compile 交叉编译
├── CMakeLists.txt
├── doc # document 文档
├── examples # example 示例程序
│ ├── CommMFC # CSerialPort MFC Demo MFC程序示例
│ ├── CommNoGui # CSerialPort No Gui Demo 无界面程序示例
│ ├── CommQT # CSerialPort QT Demo QT程序示例
│ ├── CommTui # CSerialPort tui Demo 文本界面程序示例
│ ├── CommWXWidgets # CSerialPort wxwidgets Demo wxwidgets界面程序示例
├── include # headers 头文件
│ └── CSerialPort
│ ├── ibuffer.hpp # lightweight cross-platform buffer library 轻量级跨平台缓冲区类
│ ├── ithread.hpp # lightweight cross-platform thread library 轻量级跨平台线程类
│ ├── itimer.hpp # lightweight cross-platform timer library 轻量级跨平台定时器类
│ ├── iutils.hpp # lightweight cross-platform utils library 轻量级跨平台工具类
│ ├── SerialPortBase.h # CSerialPort Base class 串口基类
│ ├── SerialPort_global.h # Global difine of CSerialPort 串口全局定义
│ ├── SerialPort.h # lightweight cross-platform serial port library 轻量级跨平台串口类库
│ ├── SerialPortInfoBase.h # CSerialPortInfo Base class 串口信息辅助类基类
│ ├── SerialPortInfo.h # CSerialPortInfo class 串口信息辅助类
│ ├── SerialPortInfoUnixBase.h # CSerialPortInfo unix class unix串口信息辅助类基类
│ ├── SerialPortInfoWinBase.h # CSerialPortInfo windows class windows串口信息辅助类基类
│ ├── SerialPortListener.h # CSerialPortListener interface class 串口事件监听接口类
│ ├── SerialPortUnixBase.h # CSerialPort unix Base class unix串口基类
│ ├── SerialPort_version.h # CSerialPort version 版本定义
│ └── SerialPortWinBase.h # CSerialPort Windows Base class windows串口基类
├── lib # lib 库目录
├── LICENSE # LGPL3.0 license
├── pic # picture 图片
├── README.md
├── README_zh_CN.md
├── src # source 源代码
├── test # unit test 单元测试
└── VERSION # version 版本号
2. Common functions of CSerialPort
2.1 Serial port information related functions
2.1.1 Get serial port information list function availablePortInfos
This function obtains a list of serial port information, mainly including:
- Serial port name (such as COM2)
- Description information (such as USB-SERIAL CH340)
- Hardware id (such as USB\VID_1A86&PID_7523&REV_0264)
static vector<SerialPortInfo> itas109::CSerialPortInfo::availablePortInfos()
2.2 Serial port operation related functions
2.2.1 Serial port initialization function init
This function is used for serial port initialization.
void itas109::CSerialPort::init(const char *portName, // 串口名称 Windows:COM1 Linux:/dev/ttyS0
int baudRate = itas109::BaudRate9600, // 波特率
itas109::Parity parity = itas109::ParityNone, // 校验位
itas109::DataBits dataBits = itas109::DataBits8, // 数据位
itas109::StopBits stopbits = itas109::StopOne, // 停止位
itas109::FlowControl flowControl = itas109::FlowNone, // 流控制
unsigned int readBufferSize = 4096 // 读取缓冲区大小
)
Notice:
- 5 data bits cannot use 2 stop bits
- 1.5 stop bits cannot use 5 data bits
- The 8-bit data bit of the POSIX system cannot use 0 parity
- The range of windows data bits is 4 - 8
- 1.5 stop bits only valid for windows
- The stop bit number 1 means StopOneAndHalf, that is, 1.5 stop bits, not 1 stop bit
2.2.2 Open serial port function open
This function is used to open the serial port.
bool itas109::CSerialPort::open()
true indicates that the opening is successful, and false indicates that the opening fails.
Open failure can be used itas109::CSerialPort::getLastError()
to obtain the error code
2.2.3 Close the serial port function close
This function is used to close the serial port.
void itas109::CSerialPort::close()
2.2.4 Whether to open the serial port success function isOpen
This function is used to get whether the serial port is opened successfully.
bool itas109::CSerialPort::isOpen()
true indicates that the serial port is successfully opened, and false indicates that the serial port fails to be opened.
2.2.5 Write data function writeData to the serial port
This function is used to write data to the serial port.
int itas109::CSerialPort::writeData(const void *data, // 待写入数据
int maxSize // 写入长度
)
Returns the number of bytes written on success, and -1 on failure.
If writing fails, you can itas109::CSerialPort::getLastError()
get the error code.
2.2.6 Read the specified length data function readData from the serial port
This function is used to read specified length data from the serial port.
int readData(void *data, // 读取结果
int size // 读取长度
)
If it is normal, it will return the number of bytes read, and if it fails, it will return -1.
The error code can itas109::CSerialPort::getLastError()
be obtained if the reading fails.
Note:
In the asynchronous operation mode of CSerialPort, it needs to connectReadEvent
be used with the function. See the code example in Section 3 for details.
2.2.7 Read all data function readAllData from the serial port
This function is used to read all data from the serial port.
int itas109::CSerialPort::readAllData(void *data // 读取结果
)
If it is normal, it will return the number of bytes read, and if it fails, it will return -1.
The error code can itas109::CSerialPort::getLastError()
be obtained if the reading fails.
Note:
In the asynchronous operation mode of CSerialPort, it needs to connectReadEvent
be used with the function. See the code example in Section 3 for details.
2.2.8 Binding read event function connectReadEvent
This function is used in asynchronous mode (default) to bind the result of reading the response.
Need to inherit CSerialPortListener and implement the onReadEvent virtual function. See the code example in Section 3 for details.
class MyListener : public CSerialPortListener
{
public:
void onReadEvent(const char *portName, unsigned int readBufferLen)
{
}
}
2.2.9 Get CSerialPort version information function getVersion
This function is used to get CSerialPort version information.
std::string itas109::CSerialPort::getVersion()
Return CSerialPort version information, such ashttps://github.com/itas109/CSerialPort - V4.3.0.230215
2.2.10 Error code SerialPortError
error code value | Error code macro definition | Error Code Description |
---|---|---|
-1 | ErrorUnknown | unknown error unknown error |
0 | Error OK | ok success |
1 | ErrorFail | general error general error |
2 | ErrorNotImplemented | not implemented not implemented |
3 | ErrorInner | inner error Internal error (such as memory access exception, etc.) |
4 | ErrorNullPointer | null pointer error null pointer error |
5 | ErrorInvalidParam | invalid parameter error invalid parameter |
6 | ErrorAccessDenied | access denied error permission error |
7 | ErrorOutOfMemory | out of memory insufficient memory |
8 | ErrorTimeout | time out error time out |
9 | ErrorNotInit | not init not initialized |
10 | ErrorInitFailed | init failed initialization failed |
11 | ErrorAlreadyExist | already exist already exists |
12 | ErrorNotExist | not exist does not exist |
13 | ErrorAlreadyOpen | already open already open |
14 | ErrorNotOpen | not open not open |
15 | ErrorOpenFailed | open failed open failed |
16 | ErrorCloseFailed | close failed close failed |
17 | ErrorWriteFailed | write failed write failed |
18 | ErrorReadFailed | read failed read failed |
3. CSerialPort simple code example
- Steps
$ mkdir CSerialPortDemo
$ cd CSerialPortDemo
$ git clone https://github.com/itas109/CSerialPort
$ touch CSerialPortDemo.cpp
$ touch CMakeLists.txt
$ mkdir bin
$ cd bin
$ cmake ..
$ cmake --build .
- Directory Structure
$ tree
.
+--- CMakeLists.txt
+--- CSerialPort
| +--- include
| +--- src
| +--- ...
+--- CSerialPortDemo.cpp
- CSerialPortDemo.cpp
Note: The receiving function needs to inherit CSerialPortListener
#include <iostream>
#include "CSerialPort/SerialPort.h"
#include "CSerialPort/SerialPortInfo.h"
#include <vector>
using namespace itas109;
using namespace std;
class MyListener : public CSerialPortListener
{
public:
MyListener(CSerialPort *sp)
: p_sp(sp){};
void onReadEvent(const char *portName, unsigned int readBufferLen)
{
if (readBufferLen > 0)
{
char *data = new char[readBufferLen + 1]; // '\0'
if (data)
{
// read
int recLen = p_sp->readData(data, readBufferLen);
if (recLen > 0)
{
data[recLen] = '\0';
std::cout << portName << ", Length: " << recLen << ", Str: " << data << std::endl;
}
delete[] data;
data = NULL;
}
}
};
private:
CSerialPort *p_sp;
};
int main()
{
CSerialPort sp;
MyListener listener(&sp);
std::cout << "Version : " << sp.getVersion() << std::endl << std::endl;
vector<SerialPortInfo> m_availablePortsList = CSerialPortInfo::availablePortInfos();
std::cout << "availableFriendlyPorts: " << std::endl;
for (size_t i = 1; i <= m_availablePortsList.size(); ++i)
{
SerialPortInfo serialPortInfo = m_availablePortsList[i - 1];
std::cout << i << " - " << serialPortInfo.portName << " " << serialPortInfo.description << " " << serialPortInfo.hardwareId << std::endl;
}
if (m_availablePortsList.size() == 0)
{
std::cout << "No valid port" << std::endl;
}
else
{
std::cout << std::endl;
int input = -1;
do
{
std::cout << "Please Input The Index Of Port(1 - " << m_availablePortsList.size() << ")" << std::endl;
std::cin >> input;
if (input >= 1 && input <= m_availablePortsList.size())
{
break;
}
} while (true);
const char *portName = m_availablePortsList[input - 1].portName;
std::cout << "Port Name: " << portName << std::endl;
sp.init(portName, // windows:COM1 Linux:/dev/ttyS0
itas109::BaudRate9600, // baudrate
itas109::ParityNone, // parity
itas109::DataBits8, // data bit
itas109::StopOne, // stop bit
itas109::FlowNone, // flow
4096 // read buffer size
);
sp.setReadIntervalTimeout(0); // read interval timeout 0ms
// sp.setOperateMode(itas109::SynchronousOperate);
sp.open();
std::cout << "Open " << portName << (sp.isOpen() ? " Success. " : " Failed. ");
std::cout << "Code: " << sp.getLastError() << ", Message: " << sp.getLastErrorMsg() << std::endl;
// 绑定读取函数
sp.connectReadEvent(&listener);
// 写入数据
sp.writeData("itas109", 7);
for (;;)
{
}
}
return 0;
}
- CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(CSerialPortDemo)
if(APPLE)
find_library(IOKIT_LIBRARY IOKit)
find_library(FOUNDATION_LIBRARY Foundation)
endif()
include_directories(CSerialPort/include)
file(GLOB_RECURSE COMMON_SOURCES CSerialPort/src/SerialPort.cpp CSerialPort/src/SerialPortBase.cpp CSerialPort/src/SerialPortInfo.cpp CSerialPort/src/SerialPortInfoBase.cpp)
if (CMAKE_HOST_WIN32)
file(GLOB_RECURSE OS_ABOUT_SOURCES CSerialPort/src/SerialPortInfoWinBase.cpp CSerialPort/src/SerialPortWinBase.cpp)
elseif (CMAKE_HOST_UNIX)
file(GLOB_RECURSE OS_ABOUT_SOURCES CSerialPort/src/SerialPortInfoUnixBase.cpp CSerialPort/src/SerialPortUnixBase.cpp)
endif ()
add_executable( ${PROJECT_NAME} CSerialPortDemo.cpp ${COMMON_SOURCES} ${OS_ABOUT_SOURCES})
if (WIN32)
target_link_libraries( ${PROJECT_NAME} setupapi )
elseif (APPLE)
target_link_libraries( ${PROJECT_NAME} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY})
elseif (UNIX)
target_link_libraries( ${PROJECT_NAME} pthread )
endif ()
- Running result (loopback test under windows)
Version : https://github.com/itas109/CSerialPort - V4.3.0.230215
availableFriendlyPorts:
1 - COM1 USB-SERIAL CH340 USB\VID_1A86&PID_7523&REV_0264
Please Input The Index Of Port(1 - 1)
1
Port Name: COM1
Open COM1 Success. Code: 0, Message: success
COM1, Length: 7, Str: itas109
License
License under CC BY-NC-ND 4.0: Attribution-Noncommercial Use-No Derivatives
Reference:
- https://github.com/itas109/CSerialPort
- https://gitee.com/itas109/CSerialPort
- https://blog.csdn.net/itas109