C++串口编程

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 // _UNICODE

typedef 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()
{

}

// 打开串口成功,返回 true

bool CSerialPort::openComm()
{
#ifdef _UNICODE
	m_hComm = CreateFile(m_portNum,
		GENERIC_READ | GENERIC_WRITE, //允许读和写
		0,		//独占方式
		NULL, OPEN_EXISTING,   //打开而不是创建
		0,   //同步方式
		NULL
		);
#else
	m_hComm = CreateFileA(m_portNum.c_str(),
		GENERIC_READ | GENERIC_WRITE, //允许读和写
		0,		//独占方式
		NULL, OPEN_EXISTING,   //打开而不是创建
		0,   //同步方式
		NULL
		);
#endif

	if (m_hComm == INVALID_HANDLE_VALUE)
	{
#ifdef _UNICODE
		TCHAR szBuf[1024] = { 0 };
		wsprintf(szBuf, L"打开 %s 失败,代码: %d", m_portNum, GetLastError());
		MessageBox(NULL, szBuf, L"Warnning", MB_OK);
#else
		char szBuf[1024] = { 0 };
		sprintf_s(szBuf, "打开 %s 失败,代码: %d", m_portNum, GetLastError());
		MessageBox(NULL, szBuf, "Warnning", MB_OK);
#endif // _UNICODE

		return 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 _UNICODE
			TCHAR szBuf[1024] = { 0 };
			wsprintf(szBuf, L"串口设置失败,错误代码: %d", GetLastError());
			MessageBox(NULL, szBuf, TEXT("ERROR"), MB_OK);
#else
			char szBuf[1024] = { 0 };
			wsprintf(szBuf, "串口设置失败,错误代码: %d", GetLastError());
			MessageBox(NULL, szBuf, "ERROR", MB_OK);
#endif
			return 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 _DEBUG
	assert(m_bOpen == true || dwLength > 0);
	return false;
#endif // _DEBUG
	DWORD 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 _UNICODE
		TCHAR szBuf[1024] = { 0 };
		wsprintf(szBuf, _T("读取数据失败,错误代码: %d"), GetLastError());
		MessageBox(NULL, szBuf, L"ERROR", MB_OK);
#else
		char szBuf[1024] = { 0 };
		sprintf_s(szBuf, "读取数据失败, 错误代码: %d", GetLastError());
		MessageBox(NULL, szBuf, "Error", MB_OK);
#endif // _UNICODE

		return false;
	}

	return true;


}

// 从串口中读取数据

bool CSerialPort::readFromComm(char buffer[], DWORD dwLength)
{
#ifdef _DEBUG
	assert(m_bOpen == true || dwLength > 0);
	return false;
#endif // _DEBUG

	COMSTAT 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 _UNICODE
		TCHAR szBuf[1024] = { 0 };
		wsprintf(szBuf, _T("数据读取失败,错误代码: %d"), GetLastError());
		MessageBox(NULL, szBuf, L"Error", MB_OK);
#else
		char szBuf[1024] = { 0 };
		wsprintf(szBuf, "数据读取失败,错误代码: %d", GetLastError());
		MessageBox(NULL, szBuf, "Error", MB_OK);
#endif // _UNICODE

		return 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;
}


  • 20
    点赞
  • 145
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
C 串口通信编程是指在 C 语言中通过串口与外设进行通信的编程技术。串口通信是一种常用的数据传输方式,适用于各种嵌入式设备和外设之间的数据交互。 首先,要进行串口通信编程,需要先设置串口相关的参数,包括波特率、数据位、校验位和停止位等。这些参数可以通过相应的寄存器进行设置。然后,需要打开串口,使其处于可用状态。 在发送数据时,可以通过对应的寄存器将数据写入发送缓冲区,待数据发送完成后,可以进行下一步的操作。在接收数据时,可以通过查询接收缓冲区的状态,判断是否有数据到达,并从接收缓冲区中读取数据进行处理。 为了简化串口通信编程的操作,可以使用相关的函数和函数,比如在 Windows 系统下可以使用 WinAPI 中提供的函数进行串口通信编程,而在 Linux 系统下可以使用 termios 进行串口通信编程。这些函数提供了一系列的函数,可以方便地实现串口的配置、数据的发送与接收等操作。 例如,在 C 语言中使用 WinAPI 进行串口通信编程时,可以使用 CreateFile 函数打开串口设备,使用 SetCommState 函数设置串口参数,使用 WriteFile 函数向串口发送数据,使用 ReadFile 函数从串口接收数据。通过这些函数的组合调用,可以实现串口通信功能。 总结起来,C 串口通信编程是一种通过设置串口参数、发送和接收数据的程序设计技术。它需要了解串口相关的硬件知识和相关函数,将其应用于实际的嵌入式设备和外设之间的数据交互中。通过合理地选择函数和编写相应的代码,可以实现稳定、高效的串口通信功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值