C++串口编程

news/2024/11/25 14:49:04/

CSerialPort 类,头文件: SerialPort.h

#ifndef _SERIAL_H
#define _SERIAL_H#include <string>
#include <Windows.h>
#include <cstddef>
#include <cstdlib>
#include <cassert>// 定义串口类型
#ifdef _UNICODE
typedef CString porttype;
#else
typedef std::string porttype;
#endif // _UNICODEtypedef unsigned long ulong;
typedef unsigned char uchar;class CSerialPort
{
public:CSerialPort(const porttype & portNum,		// 串口号DWORD baudRate = 9600,			// 波特率BYTE  byteSize = 8,				// 数据位BYTE  parityBit = NOPARITY,		// 检验位BYTE  stopBit = ONESTOPBIT		// 停止位);~CSerialPort();public:bool openComm();										// 打开串口void closeComm();										// 关闭串口bool writeToComm(BYTE data[], DWORD dwLegnth);			// 发送数据bool readFromComm(char buffer[], DWORD dwLength);		// 读取数据private:HANDLE m_hComm;		// 通信设备porttype m_portNum; // 串口号DWORD m_dwBaudRate; // 波特率BYTE  m_byteSize;	// 数据位BYTE  m_parityBit;  // 校验位BYTE  m_stopBit;	// 停止位bool  m_bOpen;		// 串口开关标志
private:enum BufferSize{MIN_BUFFER_SIZE = 256,BUFFER_SIZE = 512,MAX_BUFFER_SIZE = 1024};// 设置串口号void setPortNum(const porttype &portNum){this->m_portNum = portNum;}// 设置波特率void setBaudRate(const ulong baudRate){this->m_dwBaudRate = baudRate;}// 设置数据位void setByteSize(const uchar byteSize){this->m_byteSize = byteSize;}// 设置检验位void setParityBit(const uchar parityBit){this->m_parityBit = parityBit;}// 设置停止位void setStopBit(const uchar stopBit){this->m_stopBit = stopBit;}// 获取串口号porttype getPortNum() { return m_portNum; }// 获取波特率ulong getBaudRate() { return m_dwBaudRate; }// 获取数据位uchar getByteSize() { return m_byteSize; }// 获取检验位uchar getParityBit() { return m_parityBit; }// 获取停止位uchar getStopBit() { return m_stopBit; }
};#endif		// _SERIAL_H

SerialPort 类实现文件 .cpp:

#include "stdafx.h"
#include "Serial.h"CSerialPort::CSerialPort(const porttype & portNum,DWORD baudRate /* = 9600 */,BYTE byteSize /* = 8 */,BYTE parityBit /* = NOPARITY */,BYTE stopBit /* = ONESTOPBIT */) : m_portNum(portNum),m_dwBaudRate(baudRate),m_byteSize(byteSize),m_parityBit(parityBit),m_stopBit(stopBit),m_bOpen(false)
{}CSerialPort::~CSerialPort()
{}// 打开串口成功,返回 truebool CSerialPort::openComm()
{
#ifdef _UNICODEm_hComm = CreateFile(m_portNum,GENERIC_READ | GENERIC_WRITE, //允许读和写0,		//独占方式NULL, OPEN_EXISTING,   //打开而不是创建0,   //同步方式NULL);
#elsem_hComm = CreateFileA(m_portNum.c_str(),GENERIC_READ | GENERIC_WRITE, //允许读和写0,		//独占方式NULL, OPEN_EXISTING,   //打开而不是创建0,   //同步方式NULL);
#endifif (m_hComm == INVALID_HANDLE_VALUE){
#ifdef _UNICODETCHAR szBuf[1024] = { 0 };wsprintf(szBuf, L"打开 %s 失败,代码: %d", m_portNum, GetLastError());MessageBox(NULL, szBuf, L"Warnning", MB_OK);
#elsechar szBuf[1024] = { 0 };sprintf_s(szBuf, "打开 %s 失败,代码: %d", m_portNum, GetLastError());MessageBox(NULL, szBuf, "Warnning", MB_OK);
#endif // _UNICODEreturn false;}else{DCB dcb;SetupComm(m_hComm, MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);	// 设置读写缓冲区大小GetCommState(m_hComm, &dcb);dcb.BaudRate = m_dwBaudRate;dcb.ByteSize = m_byteSize;dcb.Parity = m_parityBit;dcb.StopBits = m_stopBit;if (!SetCommState(m_hComm, &dcb)){
#ifdef _UNICODETCHAR szBuf[1024] = { 0 };wsprintf(szBuf, L"串口设置失败,错误代码: %d", GetLastError());MessageBox(NULL, szBuf, TEXT("ERROR"), MB_OK);
#elsechar szBuf[1024] = { 0 };wsprintf(szBuf, "串口设置失败,错误代码: %d", GetLastError());MessageBox(NULL, szBuf, "ERROR", MB_OK);
#endifreturn false;}}//在读写串口前,用 PurgeComm 函数清空缓冲区PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_TXABORT);m_bOpen = true;return true;}// 关闭串口void CSerialPort::closeComm()
{CloseHandle(m_hComm);
}// 向串口发送数据
bool CSerialPort::writeToComm(BYTE data[], DWORD dwLength)
{
#ifdef _DEBUGassert(m_bOpen == true || dwLength > 0);return false;
#endif // _DEBUGDWORD dwError = 0;if (ClearCommError(m_hComm, &dwError, NULL) && dwError > 0){PurgeComm(m_hComm, PURGE_TXABORT | PURGE_TXCLEAR);}DWORD dwTx = 0;BOOL ret = FALSE;ret = WriteFile(m_hComm, data, dwLength, &dwTx, NULL);if (ret == FALSE){
#ifdef _UNICODETCHAR szBuf[1024] = { 0 };wsprintf(szBuf, _T("读取数据失败,错误代码: %d"), GetLastError());MessageBox(NULL, szBuf, L"ERROR", MB_OK);
#elsechar szBuf[1024] = { 0 };sprintf_s(szBuf, "读取数据失败, 错误代码: %d", GetLastError());MessageBox(NULL, szBuf, "Error", MB_OK);
#endif // _UNICODEreturn false;}return true;}// 从串口中读取数据bool CSerialPort::readFromComm(char buffer[], DWORD dwLength)
{
#ifdef _DEBUGassert(m_bOpen == true || dwLength > 0);return false;
#endif // _DEBUGCOMSTAT comStat;DWORD dwError = 0;if (ClearCommError(m_hComm, &dwError, &comStat) && dwError > 0){PurgeComm(m_hComm, PURGE_RXABORT | PURGE_RXCLEAR);}DWORD dwRx = 0;		// 读入的字节数BOOL ret = FALSE;BYTE* byReadData = new BYTE[dwLength];char szTmp[4] = { 0 };int sizeOfBytes = sizeof(szTmp);ret = ReadFile(m_hComm, byReadData, dwLength, &dwRx, NULL);	// 读入数据if (ret == TRUE){for (int i = 0; i < dwRx; ++i){sprintf_s(szTmp, "%02x", byReadData[i]);strcat_s(buffer, sizeOfBytes*dwLength, szTmp);}// 释放内存delete byReadData;return true;}else{
#ifdef _UNICODETCHAR szBuf[1024] = { 0 };wsprintf(szBuf, _T("数据读取失败,错误代码: %d"), GetLastError());MessageBox(NULL, szBuf, L"Error", MB_OK);
#elsechar szBuf[1024] = { 0 };wsprintf(szBuf, "数据读取失败,错误代码: %d", GetLastError());MessageBox(NULL, szBuf, "Error", MB_OK);
#endif // _UNICODEreturn false;}return true;
}

#include <iostream>
#include <cassert>
#include "Serial.h"
using namespace std;int main()
{CSerialPort serialPort("COM3");BYTE sendData = 0x01;char recvBuf[1024] = { 0 };serialPort.openComm();serialPort.writeToComm(&sendData, 1);serialPort.readFromComm(recvBuf, 1);serialPort.closeComm();system("pause");return 0;
}



http://www.ppmy.cn/news/370662.html

相关文章

串口卡住问题分析与解决

对于消息类系统而言任何阻塞都会导致整个系统的消息被卡住造成系统假死的问题。今天来说说串口导致系统卡死的问题 1.问题说明&#xff1a; 路由器在挂机过程中&#xff0c;偶现串口卡住&#xff0c;web页面进不去&#xff0c;有限终端拿不到地址的现象。 2.问题分析&#xff1…

STM32串口卡死问题

本次遇到的问题是USART串口发送函数卡死程序&#xff0c;究其原因原来是串口发送函数中的发送空寄存器没有置位&#xff0c;且超时时间设置的太大导致程序死循环&#xff0c;直到发送超时退出。 在调用CUBE的串口发送函数时一定要注意写的方式。关于传送完毕&#xff0c;有人用…

【啃】《Java核心卷 一》 | 第一,二章

文章目录 《Java核心技术卷 一》第一章 概述第二章 Java编程环境 图书推荐 《Java核心技术卷 一》 第一章 概述 前言&#xff1a;本书与一些”0基础入门“的书定位感觉是不太一样的&#xff0c;可能就像书名所说&#xff0c;是”核心技术“叭。书中经常将Java语言与 c 进行对比…

TypeScrip-03(接口和对象类型)

目录 interface 重名 、重合 任意属性 [propName: string] 可选 ? 操作符、 readonly 只读 interface 接口继承 interface 定义函数类型 在 ts 中&#xff0c;定义对象的方式要用关键字 interface&#xff08;接口&#xff09;&#xff0c;我的理解是使用interface来定义…

读书笔记:《德鲁克管理思想精要》- 6

《德鲁克管理思想精要》 美 . 彼复 . 德鲁克 著 李维安 王世权 刘金岩 译 《The Essential Drucker》The Best of Sixty Years of Peter Druckers Essential Writings on Management - 18&#xff0c;19&#xff0c;20&#xff0c;21&#xff0c;22 - 发挥沟通作用 …

想了解会计软件吗?来看看Zoho Books的功能和特点

Zoho Books 是一款功能强大的在线会计软件&#xff0c;为企业提供多合一解决方案&#xff0c;该解决方案可定制、可扩展&#xff0c;并使始终保持合规。 轻松生成电子发票 在Zoho Books中&#xff0c;您可以通过包含电子发票架构中提到的所有必填字段来创建电子发票格式的发票。…

STM32中重映射的功能和机理

在STM32系列微控制器中&#xff0c;GPIO端口具有多种功能&#xff0c;如输入、输出、模拟输入/输出等。为了提高GPIO的灵活性和可用性&#xff0c;STM32系列微控制器提供了重映射&#xff08;Remap&#xff09;功能。 重映射功能允许将一个GPIO端口重新映射到另一个GPIO端口上…

SSR渲染-初识Nuxt-01

SSR服务端渲染 SSR服务端渲染&#xff1a;在后端将html页面处理好&#xff0c;前端直接展示&#xff08;可以解决为后端给你传了一个html脚本&#xff0c;全段渲染&#xff09; 为什么要有SSR服务端渲染&#xff1f; 可以解决单页面首屏加载慢的问题&#xff0c;同时有利于用…