CSerialPort教程4.3.x (2) - CSerialPort源码简介
前言
CSerialPort项目是一个基于C/C++的轻量级开源跨平台串口类库,可以轻松实现跨平台多操作系统的串口读写,同时还支持C#, Java, Python, Node.js等。
CSerialPort项目的开源协议自 V3.0.0.171216 版本后采用GNU Lesser General Public License v3.0
为了让开发者更好的使用CSerialPort进行开发,特编写基于4.3.x版本的CSerialPort教程系列。
CSerialPort项目地址:
本文对CSerialPort 4.3.0
版本源码进行简介。
1. CSerialPort源码目录结构
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. CSerialPort常用函数
2.1 串口信息相关函数
2.1.1 获取串口信息列表函数 availablePortInfos
该函数获取串口信息列表,主要包括:
- 串口名称 (如COM2)
- 描述信息 (如USB-SERIAL CH340)
- 硬件id (如USB\VID_1A86&PID_7523&REV_0264)
static vector<SerialPortInfo> itas109::CSerialPortInfo::availablePortInfos()
2.2 串口操作相关函数
2.2.1 串口初始化函数 init
该函数用于串口初始化。
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 // 读取缓冲区大小
)
注意:
- 5位数据位不能使用2位停止位
- 1.5位停止位不能使用5位数据位
- POSIX系统8位数据位不能使用0校验
- windows数据位范围为4 - 8
- 1.5位停止位仅对windows有效
- 停止位数字1表示StopOneAndHalf,即1.5位停止位,并非1位停止位
2.2.2 打开串口函数 open
该函数用于打开串口。
bool itas109::CSerialPort::open()
true表示打开成功,false表示打开失败。
打开失败可用itas109::CSerialPort::getLastError()
获取错误码
2.2.3 关闭串口函数 close
该函数用于关闭串口。
void itas109::CSerialPort::close()
2.2.4 是否打开串口成功函数 isOpen
该函数用于获取是否打开串口成功。
bool itas109::CSerialPort::isOpen()
true表示串口打开成功,false表示串口打开失败。
2.2.5 向串口写入数据函数 writeData
该函数用于向串口写入数据。
int itas109::CSerialPort::writeData(const void *data, // 待写入数据
int maxSize // 写入长度
)
成功则返回写入字节数,失败则返回-1。
写入失败可用itas109::CSerialPort::getLastError()
获取错误码。
2.2.6 从串口读取指定长度数据函数 readData
该函数用于从串口读取指定长度数据。
int readData(void *data, // 读取结果
int size // 读取长度
)
正常则返回读取字节数,失败则返回-1。
读取失败可用itas109::CSerialPort::getLastError()
获取错误码。
注意:
CSerialPort异步操作模式下,需要配合connectReadEvent
函数使用。详见第三节的代码示例。
2.2.7 从串口读取所有数据函数 readAllData
该函数用于从串口读取所有数据。
int itas109::CSerialPort::readAllData(void *data // 读取结果
)
正常则返回读取字节数,失败则返回-1。
读取失败可用itas109::CSerialPort::getLastError()
获取错误码。
注意:
CSerialPort异步操作模式下,需要配合connectReadEvent
函数使用。详见第三节的代码示例。
2.2.8 绑定读取事件函数 connectReadEvent
该函数用于异步模式(默认)下,绑定读取响应的结果。
需要继承CSerialPortListener,并实现onReadEvent虚函数。详见第三节的代码示例。
class MyListener : public CSerialPortListener
{
public:
void onReadEvent(const char *portName, unsigned int readBufferLen)
{
}
}
2.2.9 获取CSerialPort版本信息函数 getVersion
该函数用于获取CSerialPort版本信息。
std::string itas109::CSerialPort::getVersion()
返回CSerialPort版本信息,如https://github.com/itas109/CSerialPort - V4.3.0.230215
2.2.10 错误码 SerialPortError
错误码数值 | 错误码宏定义 | 错误码说明 |
---|---|---|
-1 | ErrorUnknown | unknown error 未知错误 |
0 | ErrorOK | ok 成功 |
1 | ErrorFail | general error一般性错误 |
2 | ErrorNotImplemented | not implemented 未实现 |
3 | ErrorInner | inner error 内部错误(如内存访问异常等) |
4 | ErrorNullPointer | null pointer error 空指针错误 |
5 | ErrorInvalidParam | invalid parameter error 无效的参数 |
6 | ErrorAccessDenied | access denied error 权限错误 |
7 | ErrorOutOfMemory | out of memory 内存不足 |
8 | ErrorTimeout | time out error 超时 |
9 | ErrorNotInit | not init 未初始化 |
10 | ErrorInitFailed | init failed 初始化失败 |
11 | ErrorAlreadyExist | already exist 已经存在 |
12 | ErrorNotExist | not exist 不存在 |
13 | ErrorAlreadyOpen | already open 已经打开 |
14 | ErrorNotOpen | not open 未打开 |
15 | ErrorOpenFailed | open failed 打开失败 |
16 | ErrorCloseFailed | close failed 关闭失败 |
17 | ErrorWriteFailed | write failed 写入失败 |
18 | ErrorReadFailed | read failed 读取失败 |
3. CSerialPort简单代码示例
- 操作步骤
$ mkdir CSerialPortDemo
$ cd CSerialPortDemo
$ git clone https://github.com/itas109/CSerialPort
$ touch CSerialPortDemo.cpp
$ touch CMakeLists.txt
$ mkdir bin
$ cd bin
$ cmake ..
$ cmake --build .
- 目录结构
$ tree
.
+--- CMakeLists.txt
+--- CSerialPort
| +--- include
| +--- src
| +--- ...
+--- CSerialPortDemo.cpp
- CSerialPortDemo.cpp
注意:接收函数需要继承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 ()
- 运行结果(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: 署名-非商业使用-禁止演绎
Reference:
- https://github.com/itas109/CSerialPort
- https://gitee.com/itas109/CSerialPort
- https://blog.csdn.net/itas109