在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例Windows系统编程 → c++ 串口通信

c++ 串口通信

Windows系统编程

下载此实例
  • 开发语言:C/C++
  • 实例大小:12.55M
  • 下载次数:75
  • 浏览次数:307
  • 发布时间:2020-11-26
  • 实例类别:Windows系统编程
  • 发 布 人:Charming
  • 文件格式:.rar
  • 所需积分:2
 相关标签: 串口通信 通信 串口

实例介绍

【实例简介】
【实例截图】

【核心代码】

#include "StdAfx.h"
#include "SerialComm.h"


CSerialComm::CSerialComm(void)
{
	m_recvData = "";
	m_bConnected = FALSE;
	m_pThread = NULL;
}

CSerialComm::~CSerialComm(void)
{
	if(m_bConnected)             //程序结束时删除线程、关闭串口操作
		closeConnection();

	if(m_hPostMsgEvent)         //删除事件句柄
		CloseHandle(m_hPostMsgEvent);

	if(m_osRead.hEvent)
		CloseHandle(m_osRead.hEvent);

	if(m_osWrite.hEvent)
		CloseHandle(m_osWrite.hEvent);
}

BOOL CSerialComm::openConnection(CString commno, UINT8 baud, UINT8 datalen, UINT8 stopbit, UINT8 parity)
{
	if((baud > COMM_BAUD_115200) || 
	   (datalen > COMM_DATA_LEN_8) || 
	   (stopbit > COMM_STOP_BIT_2) || 
	   (parity > COMM_SPACE_PARITY))
	{
		m_bConnected = FALSE;
		AfxMessageBox(_T("串口参数设置错误"));

		return FALSE;
	}

	m_hPostMsgEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
	if(m_hPostMsgEvent == NULL)
		return FALSE;

	memset(&m_osRead, 0, sizeof(OVERLAPPED));
	memset(&m_osWrite, 0, sizeof(OVERLAPPED));

	m_osRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  //为重叠读创建事件对象,手工重置,初始化为无信号
	if(m_osRead.hEvent == NULL)
		return FALSE;

	m_osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //为重叠写创建事件对象,手工重置,初始化为无信号
	if(m_osWrite.hEvent == NULL)
		return FALSE;

	m_hComm = CreateFile(commno,                             //打开串口
		                 GENERIC_READ | GENERIC_WRITE,       //允许对设备进行读写访问
						 0,                                  //独占方式
						 NULL,                               //
						 OPEN_EXISTING,                      //打开而不是创建
						 FILE_FLAG_OVERLAPPED,               //使用异步通信
						 NULL);
	if(m_hComm == (HANDLE)-1)
	{
		m_bConnected = FALSE;
		AfxMessageBox(_T("打开串口失败"));
		
		return FALSE;
	} else
	{
		SetupComm(m_hComm, MAXBLOCK, MAXBLOCK);              //输入缓冲区和输出缓冲区的大小都是1024
		SetCommMask(m_hComm, EV_RXCHAR | EV_TXEMPTY );       //设置事件驱动的类型		
		
		COMMTIMEOUTS TimeOuts;
		TimeOuts.ReadIntervalTimeout = MAXDWORD;             //时间间隔设为最大,设为0会导致ReadFile立即返回并完成操作
		TimeOuts.ReadTotalTimeoutMultiplier = 0;
		TimeOuts.ReadTotalTimeoutConstant = 0;

		TimeOuts.WriteTotalTimeoutMultiplier = 50;           //设置写超时用于GetOverlapperResult函数的等待时间
		TimeOuts.WriteTotalTimeoutConstant = 2000;
		SetCommTimeouts(m_hComm, &TimeOuts);                 //设置超时

		//PurgeComm(m_hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ); //清干净输入、输出缓冲区

		if(!configureConnection(commno, baud, datalen, stopbit, parity))
		{
			CloseHandle(m_hComm);
			return FALSE;
		}

		return TRUE;
	}
}

BOOL CSerialComm::configureConnection(CString commno, UINT8 baud, UINT8 datalen, UINT8 stopbit, UINT8 parity)
{
	DCB dcb;
	if(!GetCommState(m_hComm, &dcb))           //读串口原来的参数设置
		return false;

	switch(baud)                               //波特率
	{
	case COMM_BAUD_2400:
		dcb.BaudRate = 2400;
		break;
	case COMM_BAUD_4800:
		dcb.BaudRate = 4800;
		break;
	case COMM_BAUD_9600:
		dcb.BaudRate = 9600;
		break;
	case COMM_BAUD_19200:
		dcb.BaudRate = 19200;
		break;
	case COMM_BAUD_38400:
		dcb.BaudRate = 38400;
		break;
	case COMM_BAUD_115200:
		dcb.BaudRate = 115200;
		break;
	default:
		break;
	}

	switch(datalen)                          //字节数
	{
	case COMM_DATA_LEN_5:
		dcb.ByteSize = 5;
		break;
	case COMM_DATA_LEN_6:
		dcb.ByteSize = 6;
		break;
	case COMM_DATA_LEN_7:
		dcb.ByteSize = 7;
		break;
	case COMM_DATA_LEN_8:
		dcb.ByteSize = 8;
		break;
	default:
		break;
	}

	switch(stopbit)                        //停止位
	{
	case COMM_STOP_BIT_1:
		dcb.StopBits = ONESTOPBIT;
		break;
	case COMM_STOP_BIT_1_5:
		dcb.StopBits = ONE5STOPBITS;
		break;
	case COMM_STOP_BIT_2:
		dcb.StopBits = TWOSTOPBITS;
		break;
	default:
		break;
	}

	switch(parity)                              //校验
	{
	case COMM_NONE_PARITY:
		dcb.Parity = NOPARITY;
		break;
	case COMM_ODD_PARITY:
		dcb.Parity = ODDPARITY;
		break;
	case COMM_EVEN_PARITY:
		dcb.Parity = EVENPARITY;
		break;
	case COMM_MARK_PARITY:
		dcb.Parity = MARKPARITY;
		break;
	case COMM_SPACE_PARITY:
		dcb.Parity = SPACEPARITY;
		break;
	default:
		break;
	}

	return SetCommState(m_hComm, &dcb);
}

void CSerialComm::closeConnection()
{
	if(!m_bConnected)
		return ;

	m_bConnected = FALSE;

	SetEvent(m_hPostMsgEvent);          //结束commProc线程中WaitSingleObject函数的等待
	SetCommMask(m_hComm, 0);            //结束commProc线程中WaitCommEvent的等待

	WaitForSingleObject(m_pThread->m_hThread, INFINITE);  //等待辅助线程终止
	m_pThread = NULL;

	CloseHandle(m_hComm);
}

DWORD CSerialComm::writeComm(char *buf, DWORD len)
{
	BOOL ret;
	DWORD length = len;
	DWORD errorflags;
	COMSTAT comstat;
	
	ClearCommError(m_hComm, &errorflags, &comstat);
	
	ret = WriteFile(m_hComm, buf, length, &length, &m_osWrite);
	if(!ret)
	{
		if(GetLastError() == ERROR_IO_PENDING)
		{
			GetOverlappedResult(m_hComm, &m_osWrite, &length, TRUE);    //等待
		} else
		{
			length = 0;
		}
	}

	return length;
}

DWORD CSerialComm::readComm(char *pbuf, DWORD len)
{
	DWORD length = 0;
	DWORD errorflags;
	COMSTAT comstat;

	ClearCommError(m_hComm, &errorflags, &comstat);

	length = min(len, comstat.cbInQue);
	ReadFile(m_hComm, pbuf, length, &length, &m_osRead);

	return length;
}

void CSerialComm::enumerateSerialPorts(CUIntArray& ports)
{
	//Make sure we clear out any elements which may already be in the array
	ports.RemoveAll();

	//Determine what OS we are running on
	OSVERSIONINFO osvi;
	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	BOOL bGetVer = GetVersionEx(&osvi);

	//On NT use the QueryDosDevice API
	if (bGetVer && (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT))
	{
		//Use QueryDosDevice to look for all devices of the form COMx. This is a better
		//solution as it means that no ports have to be opened at all.
		TCHAR szDevices[65535];
		DWORD dwChars = QueryDosDevice(NULL, szDevices, 65535);
		if (dwChars)
		{
			int i = 0;
			for ( ;; )
			{
				//Get the current device name
				TCHAR* pszCurrentDevice = &szDevices[i];
				//If it looks like "COMX" then
				//add it to the array which will be returned
				int nLen = _tcslen(pszCurrentDevice);
				if (nLen > 3 && _tcsnicmp(pszCurrentDevice, _T("COM"), 3) == 0)
				{
					//Work out the port number
					int nPort = _ttoi(&pszCurrentDevice[3]);
					ports.Add(nPort);
				}
				// Go to next NULL character
				while(szDevices[i] != _T('\0'))
					i  ;
				// Bump pointer to the next string
				i  ;
				// The list is double-NULL terminated, so if the character is
				// now NULL, we're at the end
				if (szDevices[i] == _T('\0'))
					break;
			}
		}
		else
			TRACE(_T("Failed in call to QueryDosDevice, GetLastError:%d\n"), GetLastError());
	}
	else
	{
		//On 95/98 open up each port to determine their existence
		//Up to 255 COM ports are supported so we iterate through all of them seeing
		//if we can open them or if we fail to open them, get an access denied or general error error.
		//Both of these cases indicate that there is a COM port at that number. 
		for (UINT i=1; i<256; i  )
		{
			//Form the Raw device name
			CString sPort;
			sPort.Format(_T("\\\\.\\COM%d"), i);

			//Try to open the port
			BOOL bSuccess = FALSE;
			HANDLE hPort = ::CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
			if (hPort == INVALID_HANDLE_VALUE)
			{
				DWORD dwError = GetLastError();
				//Check to see if the error was because some other app had the port open or a general failure
				if (dwError == ERROR_ACCESS_DENIED || dwError == ERROR_GEN_FAILURE)
					bSuccess = TRUE;
			}
			else
			{
				//The port was opened successfully
				bSuccess = TRUE;
				//Don't forget to close the port, since we are going to do nothing with it anyway
				CloseHandle(hPort);
			}
			//Add the port number to the array which will be returned
			if (bSuccess)
				ports.Add(i);
		}
	}
}

实例下载地址

c++ 串口通信

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警