当前位置: 首页 > news >正文

C++ 之 串口通讯封装类

背景

最近在做一个动态库,涉及到硬件linux通讯,通讯方式使用串口tcp/ip,故将相关通讯方式封装成了类。这里记录下,方便后续查找,有用的可以直接拿走。

环境

Linux 64位
g++ 4.8.5

串口

头文件

#pragma onceclass CSerial
{
public:CSerial(void);~CSerial(void);bool OpenSerialPort(const char* port, int BaudRate = 115200, int databits = 8, int stopbit = 0, int parity = 0, int timeOut = 10);bool ReadData(char* data, int len, int& readLen, int isDebug = 0);bool SendData(const char* data, int len, int isDebug = 0);bool CloseSerialPort();public:int m_fd; // Linux 下用文件描述符
};

源文件

#include "serial.h"
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <fstream>
#include <cstring>
#include <cstdio>
#include <cerrno>
#include <iostream>using namespace std;CSerial::CSerial(void)
{m_fd = -1;
}CSerial::~CSerial(void)
{CloseSerialPort();
}/******************************************************************************************** 功能     :	打开串口* port     :	串口号, 如("/dev/ttyS0")* baud_rate:	波特率* date_bits:	数据位(有效范围4~8)* stop_bit :	停止位* parity   :	奇偶校验。默认为无校验。NOPARITY 0; ODDPARITY 1;EVENPARITY 2;********************************************************************************************/
bool CSerial::OpenSerialPort(const char* port, int BaudRate, int databits, int stopbit, int parity, int timeOut)
{//打开串口m_fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);if (m_fd == -1) {trace_log(ERROR_LOG, 0, "open %s is fail, check the com is available!", port);return false;}// 设置为阻塞fcntl(m_fd, F_SETFL, 0);//获取串口默认配置struct termios options;if (tcgetattr(m_fd, &options) == -1) {trace_log(ERROR_LOG, 0, "tcgetattr error: %s\n", strerror(errno));CloseSerialPort();return false;}// 设置波特率speed_t speed;switch (BaudRate) {case 9600: speed = B9600; break;case 19200: speed = B19200; break;case 38400: speed = B38400; break;case 57600: speed = B57600; break;case 115200: speed = B115200; break;default: speed = B115200; break;}cfsetispeed(&options, speed);cfsetospeed(&options, speed);// 设置数据位options.c_cflag &= ~CSIZE;switch (databits) {case 5: options.c_cflag |= CS5; break;case 6: options.c_cflag |= CS6; break;case 7: options.c_cflag |= CS7; break;case 8: default: options.c_cflag |= CS8; break;}// 设置校验位switch (parity) {case 0: // 无校验options.c_cflag &= ~PARENB;options.c_iflag &= ~INPCK;break;case 1: // 奇校验options.c_cflag |= PARENB;options.c_cflag |= PARODD;options.c_iflag |= INPCK;break;case 2: // 偶校验options.c_cflag |= PARENB;options.c_cflag &= ~PARODD;options.c_iflag |= INPCK;break;default:options.c_cflag &= ~PARENB;options.c_iflag &= ~INPCK;break;}// 设置停止位if (stopbit == 2)options.c_cflag |= CSTOPB; // 2位停止位elseoptions.c_cflag &= ~CSTOPB; // 1位停止位// 其他设置options.c_cflag |= (CLOCAL | CREAD);options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始模式options.c_oflag &= ~OPOST; // 原始输出options.c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控// 设置超时options.c_cc[VTIME] = 10 * timeOut; // 读超时10*0.1s=1soptions.c_cc[VMIN] = 0;   // 最小读取字符数tcflush(m_fd, TCIFLUSH);if (tcsetattr(m_fd, TCSANOW, &options) != 0) {trace_log(ERROR_LOG, 0, "tcsetattr error: %s\n", strerror(errno));CloseSerialPort();return false;}return true;
}/********************************************************************************************* 功能    :	通过串口发送一条数据********************************************************************************************/
bool CSerial::SendData(const char* data, int len, int isDebug) {if (m_fd == -1) {trace_log(ERROR_LOG, 0, "Serial port is not available!  try to open first.");return false;}trace_log(DEBUG_LOG, 0, "starting sending data");//写串口int sendLen = write(m_fd, data, len);if (sendLen < 0) {trace_log(ERROR_LOG, 0, "Send Data is wrong! error [%s]", strerror(errno));return false;}if (isDebug != 0){trace_log(DEBUG_LOG, 0, "Send data:");trace_log(DEBUG_LOG, sendLen, data);}trace_log(DEBUG_LOG, 0, "Send Data is successfully!");return len == sendLen;
}bool CSerial::CloseSerialPort()
{if (m_fd != -1) {close(m_fd);m_fd = -1;}return true;
}bool CSerial::ReadData(char* data, int len, int& readLen, int isDebug)
{trace_log(DEBUG_LOG, 0, "Starting reading data");if (m_fd == -1) {trace_log(ERROR_LOG, 0, "Serial port is not available!  try to open first.");return false;}int tmpLen = read(m_fd, data, len);if (tmpLen < 0) {trace_log(ERROR_LOG, 0, "Read Data is wrong! error [%s]", strerror(errno));readLen = 0;return false;}data[tmpLen] = '\0';readLen = tmpLen;if (isDebug != 0 && tmpLen > 0) {trace_log(DEBUG_LOG, 0, "Read data:");trace_log(DEBUG_LOG, tmpLen, data);}trace_log(DEBUG_LOG, 0, "Receive data successfully, Byte read: %d", tmpLen);return true;
}

socket

头文件

#pragma onceclass MySocket
{
public:MySocket();~MySocket();int ConnectToServer(const char* ip, int port, int timeOut);int SendDataToServer(const char* inData, int inLen);int RecvDataFromServer(char* recvData, int recvLen);void CloseSocket();private:int m_socket;bool m_socket_exist;
};

源文件

#include "MySocket.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>#include <iostream>
using namespace std;MySocket::MySocket()
{m_socket = -1;m_socket_exist = false;
}MySocket::~MySocket()
{if (m_socket != -1){close(m_socket);}
}
/************************************************************************/
/* 建立socket链接                                                    */
/************************************************************************/
int MySocket::ConnectToServer(const char* ip, int port, int timeOut)
{if (!m_socket_exist){m_socket = socket(AF_INET, SOCK_STREAM, 0);if (m_socket == -1) {trace_log(ERROR_LOG, 0, "Create socket failed: %s", strerror(errno));return -220;}// 设置接收超时1秒struct timeval timeout;timeout.tv_sec = timeOut;timeout.tv_usec = 0;if (setsockopt(m_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) {trace_log(ERROR_LOG, 0, "setsockopt failed: %s", strerror(errno));close(m_socket);m_socket = -1;return 1;}// 填充服务器地址struct sockaddr_in server_addr;memset(&server_addr, 0, sizeof(server_addr));server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);if (inet_pton(AF_INET, ip, &server_addr.sin_addr) <= 0) {trace_log(ERROR_LOG, 0, "Invalid IP address: %s", ip);close(m_socket);m_socket = -1;return -221;}// 连接if (connect(m_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {trace_log(ERROR_LOG, 0, "Connect to server [%s], port:[%d] failed: %s", ip, port, strerror(errno));close(m_socket);m_socket = -1;return -221;}trace_log(INFO_LOG, 0, "Server connect successfully.");m_socket_exist = true;}return 0;
}/************************************************************************/
/* 向socket发送数据,成功返回实际发送的字节数; 失败返回错误码    */
/************************************************************************/
int MySocket::SendDataToServer(const char* inData, int inLen)
{int ret = -1;if (inData == NULL || inLen <= 0){trace_log(ERROR_LOG, 0, "SendDataToServer invalid parameter");return -201;}if (m_socket_exist && m_socket != -1){trace_log(DEBUG_LOG, 0, "Start sending data");ret = send(m_socket, inData, inLen, 0);trace_log(DEBUG_LOG, 0, "Send data, return value [%d]", ret);if (ret == -1){trace_log(ERROR_LOG, 0, "Send data to server failed, error: %s", strerror(errno));return -222;}}else {trace_log(ERROR_LOG, 0, "Socket is invalid");ret = -224;}return ret;
}/************************************************************************/
/* 从socket接收数据                                                     */
/************************************************************************/
int MySocket::RecvDataFromServer(char* recvData, int recvLen)
{int ret = -1;if (recvData == NULL || recvLen <= 0){trace_log(ERROR_LOG, 0, "RecvDataToServer invalid parameter");return -201;}if (m_socket_exist && m_socket != -1){trace_log(DEBUG_LOG, 0, "Start reading data");ret = recv(m_socket, recvData, recvLen, 0);trace_log(DEBUG_LOG, 0, "Receive data, return value [%d]", ret);if (ret == -1){trace_log(ERROR_LOG, 0, "Receive data from server failed, error: %s", strerror(errno));return -223;}}else {trace_log(ERROR_LOG, 0, "Socket is invalid");ret = -224;}return ret;
}void MySocket::CloseSocket()
{if (m_socket_exist && m_socket != -1){close(m_socket);m_socket = -1;m_socket_exist = false;trace_log(INFO_LOG, 0, "Close socket.....");}
}

说明

上述函数中,用到的日志记录函数trace_log 就是简单日志写入到文件,可以删除也可以替换成你自己的。

http://www.dtcms.com/a/483377.html

相关文章:

  • WHAT - 前端性能指标(网络相关指标)
  • 阿里云服务器怎么建网站常德市网络科技有限公司
  • 工程记录:使用tello edu无人机进行计算机视觉工作(手势识别,yolo3搭载)
  • 河北seo网站设计网站视频放优酷里面怎么做
  • 频偏估计方法--快速傅里叶变换(FFT)估计法
  • Flutter---Container
  • 揭阳专业做网站公司深圳做网站价格
  • 整站优化 快速排名学做网站要学什么
  • 在 MSYS2(MINGW64)中安装 Python 和 pip 完全指南
  • 小语种网站建设 cover做网站需要报备什么
  • Windows共享的一些设置点
  • 有后台的网站模版wordpress音乐源码
  • 羊城杯 2025
  • 长沙低价网站建设长沙网站seo优化公司
  • 凡科做的手机网站可以导出来贵州省城乡建设厅网站
  • 连续小波变换(CWT)+时间序列预测!融合时频分析与深度学习的预测新思路
  • 网站开发微盘网站建设怎么找客源
  • 是用cms还是直接用语言写网站游乐园网站建设
  • 扫雷游戏的设计与实现:扫雷游戏3.0
  • 网站建设找哪家公司建筑二级建造师培训机构
  • SpringBoot 集成 LangChain4j RAG Redis 搜索
  • 宿迁市住房城乡建设局网站网站建设基础策划书
  • 3.5 JSON Schema回顾
  • 艺术学校示范校建设专题网站wordpress 评论模板制作
  • 图像分类项目:Fashion-MNIST 分类(SimpleCNN )
  • 【BIO、NIO、AIO】——原理、优缺点、使用场景
  • 金坛网站建设报价庆阳网站建设报价
  • 广州手表网站大学生职业生涯规划ppt
  • 学校安全教育网站建设上海浦东新区
  • OpenAI智能体框架_Num1