CSerialPort笔记

CSerialPort笔记

前面的博客讲了如何以第三库方式使用CSerialPort,下面将介绍如何通过cmake直接编译与使用CSerialPort。

我是比较推荐使用CSerialPort的,在大二的时候做过的多轴控制软件(基于VC++6.0 MFC)便是使用itas109作者写的串口助手改写的,串口功能流程稳定,API方便易懂。

前言

CSerialPort项目是基于C++的轻量级开源跨平台串口类库,用于实现跨平台多操作系统的串口读写。

CSerialPort项目的开源协议自 V3.0.0.171216 版本后采用GNU Lesser General Public License v3.0

CSerialPort项目地址:

https://github.com/itas109/CSerialPort

https://gitee.com/itas109/CSerialPort

CSerialPort设计原则

跨平台

简单易用

高效

CSerialPort平台支持

CSerialPort已经在以下平台做过测试:

DOS ( x86_64 )

Windows ( x86_64 )

Linux ( x86_64, aarch64, mips64el, s390x, ppc64le )

macOS ( x86_64 )

Raspberry Pi ( armv7l )

FreeBSD ( x86_64 )

cmake构建基于CSerialPort的项目

1 建立项目文件夹

新建一个文件夹,内容如下

CMakeLists.txt

main.cpp

CMakeLists.txt

cmake_minimum_required(VERSION 2.8.12)

project(UartTest LANGUAGES CXX)

# add by itas109

set(CSerialPortRootPath "${PROJECT_SOURCE_DIR}/CSerialPort")

include_directories(${CSerialPortRootPath}/include)

list(APPEND CSerialPortSourceFiles ${CSerialPortRootPath}/src/SerialPort.cpp ${CSerialPortRootPath}/src/SerialPortBase.cpp ${CSerialPortRootPath}/src/SerialPortInfo.cpp ${CSerialPortRootPath}/src/SerialPortInfoBase.cpp)

if (WIN32)

list(APPEND CSerialPortSourceFiles ${CSerialPortRootPath}/src/SerialPortInfoWinBase.cpp ${CSerialPortRootPath}/src/SerialPortWinBase.cpp)

else (UNIX)

list(APPEND CSerialPortSourceFiles ${CSerialPortRootPath}/src/SerialPortInfoUnixBase.cpp ${CSerialPortRootPath}/src/SerialPortUnixBase.cpp)

endif()

# end by itas109

add_executable(${PROJECT_NAME}

main.cpp

${CSerialPortSourceFiles} # add by itas109

)

# add by itas109

if (WIN32)

# for function availableFriendlyPorts

target_link_libraries( ${PROJECT_NAME} setupapi)

elseif(APPLE)

find_library(IOKIT_LIBRARY IOKit)

find_library(FOUNDATION_LIBRARY Foundation)

target_link_libraries( ${PROJECT_NAME} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY})

elseif(UNIX)

target_link_libraries( ${PROJECT_NAME} pthread)

endif ()

# end by itas109

命令解释

这段代码是一个CMakeLists.txt文件,用于配置CMake构建系统。以下逐行解释每个命令的含义:

cmake_minimum_required(VERSION 2.8.12):这个命令指定了最低的CMake版本要求。

project(UartTest LANGUAGES CXX):这个命令定义了项目的名称为"UartTest",并指定了项目使用的编程语言为C++(LANGUAGES CXX)。

set(CSerialPortRootPath "${PROJECT_SOURCE_DIR}/CSerialPort"):这个命令设置了一个变量CSerialPortRootPath,它表示"CSerialPort"项目的根目录路径,该路径被设置为当前项目的源代码目录下的"CSerialPort"文件夹。

include_directories(${CSerialPortRootPath}/include):这个命令将"CSerialPort"项目的include目录添加到编译器的头文件搜索路径中,以便在构建期间能够找到相关的头文件。

list(APPEND CSerialPortSourceFiles ...):这个命令将一系列源文件路径添加到变量CSerialPortSourceFiles中。这些源文件是"CSerialPort"项目的源代码文件。

if (WIN32) ... else (UNIX) ... endif():这个条件语句用于根据操作系统的不同选择不同的源文件。如果操作系统是Windows(WIN32),则添加Windows特定的源文件;否则(UNIX),添加Unix特定的源文件。

add_executable(${PROJECT_NAME} ...):这个命令将一个可执行文件的名称设置为${PROJECT_NAME},并指定了可执行文件的源代码文件。${PROJECT_NAME}是之前通过project()命令定义的项目名称。

target_link_libraries(...):这个命令用于指定可执行文件的链接库。根据操作系统的不同,选择不同的链接库。在Windows上,使用setupapi库;在苹果操作系统上,使用IOKit和Foundation库;在Unix系统上,使用pthread库。

通过执行这些命令,CMake将配置项目的构建过程,设置了编译器的头文件搜索路径,添加了项目的源代码文件,并指定了可执行文件的链接库。

main.cpp

#include

#ifdef _WIN32

#include

#define imsleep(microsecond) Sleep(microsecond) // ms

#else

#include

#define imsleep(microsecond) usleep(1000 * microsecond) // ms

#endif

#include

#include "CSerialPort/SerialPort.h"

#include "CSerialPort/SerialPortInfo.h"

using namespace itas109;

std::string char2hexstr(const char *str, int len)

{

static const char hexTable[17] = "0123456789ABCDEF";

std::string result;

for (int i = 0; i < len; ++i)

{

result += "0x";

result += hexTable[(unsigned char)str[i] / 16];

result += hexTable[(unsigned char)str[i] % 16];

result += " ";

}

return result;

}

int countRead = 0;

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 << " - Count: " << ++countRead << ", Length: " << recLen << ", Str: " << data << ", Hex: " << char2hexstr(data, recLen).c_str()

<< std::endl;

// return receive data

// p_sp->writeData(data, recLen);

}

delete[] data;

data = NULL;

}

}

};

private:

CSerialPort *p_sp;

};

int main()

{

CSerialPort sp;

std::cout << "Version: " << sp.getVersion() << std::endl

<< std::endl;

MyListener listener(&sp);

std::vector 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;

return 0;

}

std::cout << std::endl;

const char *portName = "COM10";

std::cout << "Port Name: " << portName << std::endl;

sp.init(portName, // windows:COM1 Linux:/dev/ttyS0

itas109::BaudRate115200, // 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.open();

std::cout << "Open " << portName << (sp.isOpen() ? " Success" : " Failed") << std::endl;

// 连接读取事件

sp.connectReadEvent(&listener);

// 第一次写入十六进制数据

char hex[5];

hex[0] = 0x31;

hex[1] = 0x32;

hex[2] = 0x33;

hex[3] = 0x34;

hex[4] = 0x35;

sp.writeData(hex, sizeof(hex));

// 写入字符串数据

sp.writeData("Dapenson", 8);

// 循环等待

for (;;)

{

// 延时1S

imsleep(1000);

// 写入字符串数据

const char *data_send = "Dapenson\n";

sp.writeData(data_send, strlen(data_send));

}

return 0;

}

程序功能思路解释

这段C++程序的功能是通过串口COM10与外部设备进行通信。下面是程序的主要功能和思路的简要解释:

程序包含了必要的头文件和库,并定义了一些辅助函数和变量。

声明了一个名为MyListener的自定义类,该类继承自CSerialPortListener,用于处理串口的读取事件。

在main函数中,首先创建了一个CSerialPort对象sp,并打印出其版本信息。

创建了一个MyListener对象listener,并使用CSerialPort对象的availablePortInfos方法获取可用串口的列表,并打印出相应的信息。

检查是否有可用串口,如果没有则退出程序。

使用指定的串口名称、波特率、校验位等参数对CSerialPort对象进行初始化,并设置读取超时时间。

打开串口,并输出打开状态。

连接读取事件,将MyListener对象的读取事件与CSerialPort对象进行关联。

写入一些数据到串口,包括一组十六进制数据和一个字符串。

进入无限循环,每隔1秒发送一个字符串数据到串口。

整体思路是:程序首先初始化CSerialPort对象,然后打开指定的串口。接着,将一个自定义的监听器对象与串口的读取事件进行关联,以便在有数据可读时触发相应的处理。程序在主循环中以一定的时间间隔不断地向串口发送数据。通过这样的方式,可以实现与外部设备的串口通信,并在控制台输出接收到的数据。

2 cmake构建

在项目文件夹下打开cmd,并使用以下命令进行构建

git clone https://github.com/itas109/CSerialPort

# 或使用国内码云地址

git clone https://gitee.com/itas109/CSerialPort.git

mkdir bin

cd bin

cmake .. -G "MinGW Makefiles"

make

cmake --build .

命令解释:

这些是一系列Bash命令,用于克隆GitHub或码云上的一个名为"CSerialPort"的项目,并在本地进行构建。让我一步步解释每个命令的含义:

git clone https://github.com/itas109/CSerialPort:这个命令会克隆GitHub上的"CSerialPort"项目到当前目录。git clone用于复制一个远程Git仓库到本地。

或者,如果你想使用码云上的地址,可以执行以下命令:

git clone https://gitee.com/itas109/CSerialPort.git:这个命令会克隆码云上的"CSerialPort"项目到当前目录。

mkdir bin:这个命令创建一个名为"bin"的目录。mkdir用于创建新目录。

cd bin:这个命令将当前工作目录切换到"bin"目录。cd用于改变当前工作目录。

cmake .. -G "MinGW Makefiles":这个命令使用CMake来配置项目的构建过程。cmake是一个跨平台的构建工具,它根据项目中的CMakeLists.txt文件生成适合特定构建系统(在这里是MinGW Makefiles)的构建文件。

make:这个命令用于执行构建过程,编译源代码并生成可执行文件。这是针对类Unix系统的命令。如果你正在Windows上使用MinGW,可以使用mingw32-make代替make。

或者,如果你已经使用了-G "MinGW Makefiles"选项进行了配置,也可以使用以下命令进行构建:

cmake --build .:这个命令使用预先配置的构建系统构建项目。

通过执行这些命令,你将克隆"CSerialPort"项目,创建一个名为"bin"的目录,配置构建过程,并使用Makefile(或MinGW Makefiles)构建项目。

打印信息

运行完成以后会在bin目录下生成一个以项目名称为名的exe可执行文件

可双击运行打开cmd窗口

以下是项目编译运行的最简环境

+--- CMakeLists.txt

+--- main.cpp

+--- CSerialPort

| +--- include

| | +--- CSerialPort

| | | +--- SerialPort.h

| | | +--- SerialPortInfo.h

| +--- src

| | +--- SerialPort.cpp

| | +--- SerialPortBase.cpp

| | +--- SerialPortInfo.cpp

| | +--- SerialPortInfoBase.cpp

| | +--- SerialPortInfoWinBase.cpp

| | +--- SerialPortWinBase.cpp

3 测试效果

程序功能是打开COM10,并向其每隔1s发送一次固定字符串,同时绑定的回调函数将COM10收到数据打印。

因此使用VSPD建立一组串口(COM10、COM11)用以测试,使用串口助手软件打开COM11用以与程序联调测试。

下面是正常运行的效果图,左边将右边发送的1234字符串打印

相关推荐

水晶流星碎片 - 护核纪元CoreKeeperWIKI
365bet官方网站是多少

水晶流星碎片 - 护核纪元CoreKeeperWIKI

📅 06-30 👁️ 9147
手机检测噪音分贝app排行榜TOP10推荐
365bet官方网站是多少

手机检测噪音分贝app排行榜TOP10推荐

📅 07-20 👁️ 1381
华为旗舰机型有哪些系列
365bet官方网站是多少

华为旗舰机型有哪些系列

📅 07-13 👁️ 2476