⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rs485读写源程序 vc++代码 .cpp

📁 === === === ===== RS485读写源程序 VC++代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//Author:horse_b

#include "stdafx.h"
#include "SerialPort.h"
#include \<stdlib.h\>
#include \<stdio.h\>
#include \<time.h\>


#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

extern CRoadSvrDlg* pRoadSvrDlg;
//LARGE_INTEGER lia, lib, lif, lis;
//int lin;

//串口类的初始化
CSerialPort::CSerialPort()
{
	m_blIdle = false;

	m_hCom = INVALID_HANDLE_VALUE;
	m_hCommWatchThread = NULL;
	m_fConnected = false;
	memset(&m_osRead, 0, sizeof(OVERLAPPED));
	memset(&m_osWrite, 0, sizeof(OVERLAPPED));
	m_osRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL);
	m_osWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL);
	m_pEye = NULL;
	mReceive = 1024000;
	pReceive = new BYTE[mReceive];
	m_bClearUntillEmpty = false;
	/*#ifdef LPR_DOHERELARGE
	memset(m_pEmptyID, 0, e_nIDLength);
	m_nImageState = 0;
	#endif*/
}

CSerialPort::~CSerialPort()
{
	Disconnect();
	if (m_osRead.hEvent)
		CloseHandle(m_osRead.hEvent);
	if (m_osWrite.hEvent)
		CloseHandle(m_osWrite.hEvent);
	delete pReceive;
}

/****************************************************************************************
* 函数名 : CSerialPort::Connect
* 说 明 : 连接一个串口,非Overlap方式
* 返回值 : BOOL - 是否连接成功
* 参 数 : HWND hWnd - 接收到数据之后,通知的窗口
* 参 数 : CString szCom - 串口名称 "Com1" or "Com2"
* 参 数 : DWORD BaudRate - 波特率 2400 9600 etc.
* 参 数 : BYTE ByteSize - 数据位 8
* 参 数 : BYTE StopBits - 停止位 0,1,2 = 1, 1.5, 2 stop bits
* 参 数 : BYTE Parity - 奇偶校验 0-4=no,odd,even,mark,space
****************************************************************************************/
BOOL CSerialPort::Connect(CString szCom, DWORD BaudRate, BYTE ByteSize, BYTE StopBits, BYTE Parity)
{
	if (m_osRead.hEvent == NULL || m_osWrite.hEvent == NULL)
	{
		m_fConnected = false;
		return false;
	}

	m_hCom = CreateFile(szCom, GENERIC_READ | GENERIC_WRITE,
		0, // exclusive access
		NULL, // no security attrs
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/O
		NULL);

	if (m_hCom == INVALID_HANDLE_VALUE)
	{
		m_fConnected = false;
		return FALSE;
	}

	SetCommMask(m_hCom, EV_RXCHAR|EV_CTS);

	//SetupComm(m_hCom, 20480, 20480);
	SetupComm(m_hCom, 512000, 512000);

	PurgeComm(m_hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

	DCB dcb;
	GetCommState(&dcb);
	dcb.BaudRate = BaudRate;
	dcb.ByteSize = ByteSize;
	dcb.Parity = Parity;
	dcb.StopBits = StopBits;

	dcb.fBinary = TRUE;
	dcb.fParity = TRUE;
	dcb.fOutxDsrFlow = false;
	dcb.fDtrControl = DTR_CONTROL_DISABLE;
	dcb.fOutxCtsFlow = false;

	//#ifdef LPR_DOHERELARGE
	// dcb.fRtsControl = RTS_CONTROL_ENABLE;
	//#else
	dcb.fRtsControl = RTS_CONTROL_DISABLE;
	//#endif

	dcb.fInX = false;
	dcb.fOutX = false;
	dcb.XonChar = ASCII_XON;
	dcb.XoffChar = ASCII_XOFF;
	dcb.XonLim = 100;
	dcb.XoffLim = 100;

	m_fConnected = SetCommState(&dcb);

	if (!m_fConnected)
		return false;

	COMMTIMEOUTS CommTimeOuts;

	CommTimeOuts.ReadIntervalTimeout = 0;
	CommTimeOuts.ReadTotalTimeoutMultiplier = __max(1, 2 * CBR_9600 / BaudRate);
	CommTimeOuts.ReadTotalTimeoutConstant = 10;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 0 ;
	m_fConnected = ::SetCommTimeouts(m_hCom, &CommTimeOuts) ;

	if (!m_fConnected)
		return false;

	m_hCommWatchThread = CreateThread((LPSECURITY_ATTRIBUTES) NULL,
		0,
		(LPTHREAD_START_ROUTINE)CommWatchProc,
		(LPVOID) this,
		0,
		&m_dwThreadID);

	if (m_hCommWatchThread == NULL)
		m_fConnected = false;

	SetThreadPriority(m_hCommWatchThread, THREAD_PRIORITY_ABOVE_NORMAL);//THREAD_PRIORITY_TIME_CRITICAL);//THREAD_PRIORITY_HIGHEST);//);

	return m_fConnected;
}

BOOL CSerialPort::GetCommState(DCB* pDCB)
{
	if (m_hCom == INVALID_HANDLE_VALUE)
		return false;

	return ::GetCommState(m_hCom, pDCB) ;
}

BOOL CSerialPort::SetCommState(DCB* pDCB)
{
	if (m_hCom == INVALID_HANDLE_VALUE)
		return false;

	return ::SetCommState(m_hCom, pDCB);
}

DWORD FAR PASCAL CommWatchProc(LPVOID lpData)
{
	CSerialPort* pSerial = (CSerialPort*)lpData;

	DWORD dwEvtMask;
	DWORD nLength;
	DWORD dwBlockSize = 128;
	LARGE_INTEGER freq, begin, end;
	::QueryPerformanceFrequency(&freq);

	COMSTAT ComStat ;
	DWORD dwErrorFlags = 0;
	memset(&ComStat, 0, sizeof(ComStat));

#ifdef LPR_DOHERELARGE
	BOOL blTriggered = false;
#endif

	pSerial->m_blIdle = false;

	while (pSerial->m_fConnected)
	{
		dwEvtMask = 0 ;

		if (pRoadSvrDlg->e_nIO == 0 && !pRoadSvrDlg->e_bWithToll)
			pRoadSvrDlg->SetWindowText("RoadSvr - Idle");
		else
			pRoadSvrDlg->PostMessage(WM_NOTIFYSERIALSTATE, 0, (LPARAM)pSerial); //Idle

		if (pRoadSvrDlg->m_bl485 && pSerial == &(pSerial->m_pEye->m_Serial1))
		{
			while(pSerial->m_fConnected)
			{
				::QueryPerformanceCounter(&begin);
				::QueryPerformanceCounter(&end);
				while((end.QuadPart - begin.QuadPart) * 1000 / freq.QuadPart < pRoadSvrDlg->m_n485Interval)
				{
					Sleep(0);
					ClearCommError(pSerial->m_hCom, &dwErrorFlags, &ComStat);
					//在等候的时间内,若有数据上来,则继续
					if (ComStat.cbInQue > 0)
						break;
					::QueryPerformanceCounter(&end);
				}
				if (ComStat.cbInQue == 0)
				{
					//如果数据没有接受完,则最多等1秒钟
					// while (pRoadSvrDlg->e_btEyeData != 0 &&
					// (end.QuadPart - begin.QuadPart) * 1000 / freq.QuadPart < 1000)
					// {
					// ::QueryPerformanceCounter(&end);
					// }
					//若有需要查找的汉王眼,则查找
					if (pRoadSvrDlg->m_nAddressList > 0)
					{
						pRoadSvrDlg->m_nAddress ++;
						if (pRoadSvrDlg->m_nAddress >= pRoadSvrDlg->m_nAddressList)
							pRoadSvrDlg->m_nAddress = 0;
						pSerial->Write(&(pRoadSvrDlg->m_pAddressList[pRoadSvrDlg->m_nAddress]), 1);
					}
					//继续,等待是否有结果上来
					continue;
				}
				//若有结果上来,则继续执行下面的接受部分
				break;
			}
		}
		else
		{ //等待10m,若没有数据,则认为已经空闲,可以下发数据,及进入Wait状态
			::QueryPerformanceCounter(&begin);
			::QueryPerformanceCounter(&end);
			while((end.QuadPart - begin.QuadPart) * 1000 / freq.QuadPart < 5) //5ms
			{
				ClearCommError(pSerial->m_hCom, &dwErrorFlags, &ComStat);
				if (ComStat.cbInQue > 0)
					break;
				Sleep(0);
				::QueryPerformanceCounter(&end);
			}
			if (ComStat.cbInQue == 0)
				pSerial->m_blIdle = true;
		}

		WaitCommEvent(pSerial->m_hCom, &dwEvtMask, NULL);

		if ((dwEvtMask & EV_RXCHAR) == EV_RXCHAR)
		{
			ClearCommError(pSerial->m_hCom, &dwErrorFlags, &ComStat);

			if (ComStat.cbInQue == 0)
				continue;

			pSerial->m_blIdle = false;

			if (pRoadSvrDlg->e_nIO == 0 && !pRoadSvrDlg->e_bWithToll)
				pRoadSvrDlg->SetWindowText("RoadSvr - Receiving ...");
			else
				pRoadSvrDlg->PostMessage(WM_NOTIFYSERIALSTATE, 1, (LPARAM)pSerial); //Receiving

			nLength = 0;
			BOOL bError = false;
			while(pSerial->m_fConnected)
			{
				while((nLength = pSerial->Read(pSerial->pReceive, 1)) == 1 && pSerial->pReceive[0] == 0);

				if (nLength == 0)
					break;

				ASSERT(nLength == 1);
				ASSERT(pSerial->pReceive[0] != 0);
				nLength = pSerial->Read(pSerial->pReceive+1, 4);
				if (nLength == 0)
					break;

				nLength ++;
				pSerial->nReceive = nLength;

				if (nLength == 5 && //报文头的长度
					((pSerial->pReceive[0] == 0xF0 && pSerial->pReceive[1] == 0x0F) //如果报文头的格式正确
					|| //报文的格式为可能错误的那种格式,即只有识别数据报文的第一个字节发错误为0xFC,其他字节是正确的。
					(pSerial->pReceive[0] == 0xFC && pSerial->pReceive[1] == 0x0F && pSerial->pReceive[2] == 0x3B &&
					pSerial->pReceive[3] == 0x00 && (pSerial->pReceive[4] == 0x01 || pSerial->pReceive[4] == 0x02 || pSerial->pReceive[4] == 0x03))
					)
					)
				{
					DWORD len = pSerial->pReceive[2] + pSerial->pReceive[3] * 0x100;//报文长度

					if ((pSerial->pReceive[4] == 0x03 || pSerial->pReceive[4] == 0x01 || pSerial->pReceive[4] == 0x02) && len + pSerial->nReceive > 64)
						bError = true;
					if (pSerial->pReceive[4] == 0x21 && len + pSerial->nReceive > (DWORD)pSerial->mReceive)
						bError = true;
					else if (pSerial->pReceive[4] == 0x22 && len + pSerial->nReceive > (DWORD)pSerial->mReceive)
						bError = true;
					else if (pSerial->pReceive[4] == 0x23 && len != 0)
						bError = true;
					else
					{
						switch(pSerial->pReceive[4])
						{
						case 0x01:
						case 0x02:
						case 0x03:
							if (pSerial->pReceive[0] == 0xFC) //针对黄冈的通讯错误进行的处理
								pSerial->pReceive[0] = 0xF0; //更正错误的内容
							nLength = pSerial->Read(pSerial->pReceive + 5, len);
							pSerial->nReceive += nLength;
							pRoadSvrDlg->OnReceiveMeInfo(pSerial->pReceive, pSerial->nReceive);
							//#ifdef LPR_MATCHDEMO
							pRoadSvrDlg->OnSerialNotifyInfo(0, 0);
							//#else
							// pRoadSvrDlg->PostMessage(WM_SERIALNOTIFY_INFO, 0, 0);
							//#endif
							pSerial->m_pEye->bImage = true; //图片是否正确的标记,只对正确的图片发送和进行图片比较
							if (pRoadSvrDlg->m_pInfoExtractDlg != NULL)
								((CInfoExtractDlg*)pRoadSvrDlg->m_pInfoExtractDlg)->ShowInfoExtract(pSerial->pReceive, pSerial->nReceive);
							break;
						case 0x11:
							if (len > 0)
							{
								nLength = pSerial->Read(pSerial->pReceive + 5, 1);
								pSerial->nReceive += nLength;
								if (nLength == 1)
								{
									switch(pSerial->pReceive[5])
									{
									case 0x00:
									case 0x01:
										{
											nLength = pSerial->ReadByBlock(pRoadSvrDlg->e_pImage, len - 1, dwBlockSize);
											if (nLength < len - 1)
												memset(pRoadSvrDlg->e_pImage + nLength, 0, len - 1 - nLength);
										}

										pSerial->nReceive += nLength;
										pSerial->m_pEye->nImageOdd = nLength / 2;
										pSerial->m_pEye->nImageEven = nLength - pSerial->m_pEye->nImageOdd;
										SetEvent(pSerial->m_pEye->m_hImageReceivedEven);
										SetEvent(pSerial->m_pEye->m_hImageReceivedOdd);
										break;
									case 0x02:
										nLength = pSerial->ReadByBlock(pSerial->pReceive + 6, len - 1, dwBlockSize);
										if (nLength < len - 1)
											memset(pSerial->pReceive + 6 + nLength, 0, len - 1 - nLength);
										pSerial->nReceive += nLength;
										{
											if (pSerial->m_pEye->bImage && nLength != len - 1)
												pSerial->m_pEye->bImage = false;
											for (DWORD i = 0 ; i < len - 1 ; i ++)
											{
												if (i < nLength)
													pRoadSvrDlg->e_pImage[i * 2] = pSerial->pReceive[6 + i];
												else
													pRoadSvrDlg->e_pImage[i * 2] = 0;
											}
											pSerial->m_pEye->nImageEven = len - 1;//nLength; //强迫数据长度是对的,以可以显示一些虽然错误,但是还能基本解码的图片
											SetEvent(pSerial->m_pEye->m_hImageReceivedEven);
										}
										break;
									case 0x12:
										nLength = pSerial->ReadByBlock(pSerial->pReceive + 6, len - 1, dwBlockSize);
										if (nLength < len - 1)
											memset(pSerial->pReceive + 6 + nLength, 0, len - 1 - nLength);
										pSerial->nReceive += nLength;
										{
											if (pSerial->m_pEye->bImage && nLength != len - 1)
												pSerial->m_pEye->bImage = false;

											for (DWORD i = 0 ; i < len - 1 ; i ++)
											{
												if (i < nLength)
													pRoadSvrDlg->e_pImage[1 + i * 2] = pSerial->pReceive[6 + i];
												else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -