📄 rs485读写源程序 vc++代码 .cpp
字号:
//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 + -