//专本针对命令试的串口
Serial.h
#if !defined(AFX_SERIAL_H__F97E181C_46A7_404D_98FB_07595B7767F3__INCLUDED_)
#define AFX_SERIAL_H__F97E181C_46A7_404D_98FB_07595B7767F3__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define MAXSERBUF 2048 //串口最大缓存
class CSerial
{
private:
//检测串口程序
static void CommWatchProc(LPVOID pParam);
HANDLE m_hIDComDev;
static BOOL m_bOpened; //串口是否打开
static HANDLE R_Event; //接收事件
static HANDLE W_Event; //发送事件
static BYTE m_szRevBuf[MAXSERBUF];
static DWORD m_dwRevBuf;
//读数据到串口
BOOL ReadComm(PBYTE pbuf, DWORD *pbuflen);
//写数据到串口
BOOL WriteComm(const unsigned char *pbBuf, DWORD dwSize);
public:
VOID StarMonitor(); //打开监测线程
VOID StarRevData(); //开始接收数据
VOID StopRevData(); //停止接收数据
DWORD Transmit(PBYTE pbSendBuffer, DWORD cbSendLength,
PBYTE pbRecvBuffer, DWORD *pcbRecvLength,
DWORD dwOverTime = 1000);
//串口是否打开
BOOL isOpen() { return m_bOpened; };
//打开串口
BOOL Open(int nPort = 1,
int nBaud = 9600,
int nByteSize = 8,
int nParity = 0,
int nStopBits = 1,
int nSendBuffer = MAXSERBUF);
//关闭串口
void Close();
CSerial();
virtual ~CSerial();
};
#endif // !defined(AFX_SERIAL_H__F97E181C_46A7_404D_98FB_07595B7767F3__INCLUDED_)
Serial.cpp
#include "stdafx.h"
#include "Serial.h"
#include <assert.h>
#include <process.h>
//创建一个读事件, 读完数据后产生该事件
HANDLE CSerial::R_Event;
//创建一个写事件, 写完数据后产生该事件
HANDLE CSerial::W_Event;
//串口是否被打开
BOOL CSerial::m_bOpened;
//串口缓存
BYTE CSerial::m_szRevBuf[MAXSERBUF];
DWORD CSerial::m_dwRevBuf;
//
// Construction/Destruction
//
CSerial::CSerial()
{
m_bOpened = FALSE;
}
CSerial::~CSerial()
{
Close();
}
BOOL CSerial::Open(int nPort, int nBaud, int nByteSize, int nParity, int nStopBits, int nSendBuffer)
{
if ( isOpen() ) return true;
DWORD lpErrCode = 0;
char szPort[15] = {"/0"};
wsprintf(szPort, "COM%d", nPort);
m_hIDComDev = CreateFile(szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (m_hIDComDev == INVALID_HANDLE_VALUE) return FALSE;
//设置超时
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier= 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(m_hIDComDev, &CommTimeOuts);
//设置为字符形
if (!SetCommMask(m_hIDComDev, EV_RXCHAR))
{
goto err;
}
//设置输入输出缓存
if (!SetupComm(m_hIDComDev, nSendBuffer, nSendBuffer))
{
goto err;
}
// Clear all comunication errors
ClearCommError(m_hIDComDev, &lpErrCode, NULL);
//清空缓存
if (!PurgeComm(m_hIDComDev, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT))
{
goto err;
}
// Gets COM Settings
// Gets COM Settings
DCB dcb;
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = nByteSize;
dcb.Parity = nParity ;
dcb.StopBits = nStopBits;
char sDCBState[100];
wsprintf( sDCBState,"baud=%d parity=N data=%d stop=%d",
nBaud, nByteSize, nStopBits );
if(!BuildCommDCB(sDCBState, &dcb))
{
DWORD ret = GetLastError();
goto err;
}
if (!SetCommState(m_hIDComDev, &dcb))
{
DWORD ret = GetLastError();
goto err;
}
m_bOpened = true;
return true;
err:
CloseHandle(m_hIDComDev);
return false;
}
void CSerial::Close()
{
if (!isOpen() || m_hIDComDev == NULL) return;
CloseHandle(R_Event);
CloseHandle(m_hIDComDev);
m_bOpened = false;
m_hIDComDev = NULL;
m_bOpened = false;
}
BOOL CSerial::ReadComm(PBYTE pbuf, DWORD *pbuflen)
{
assert(pbuf != NULL);
if ( !isOpen() ) return FALSE;
OVERLAPPED ovRead;
memset(&ovRead,0,sizeof(ovRead));
ovRead.hEvent = CreateEvent(0, true, 0, 0);
if (!ReadFile(m_hIDComDev, pbuf, *pbuflen, pbuflen, &ovRead) )
return FALSE;
CloseHandle( ovRead.hEvent );
return TRUE;
}
BOOL CSerial::WriteComm(const unsigned char * pbBuf, DWORD dwSize)
{
assert(pbBuf != NULL);
if ( !isOpen() ) return FALSE;
if (dwSize > MAXSERBUF) return FALSE;
int iRet = 0 ;
OVERLAPPED ov;
memset(&ov,0,sizeof(ov));
ov.hEvent = CreateEvent( 0,true,0,0);
DWORD dwBytesWritten = 0;
//do
{
iRet = WriteFile (m_hIDComDev,pbBuf,dwSize,&dwBytesWritten ,&ov);
if ( iRet == 0 )
{
WaitForSingleObject(ov.hEvent, INFINITE);
}
}// while ( ov.InternalHigh != dwSize ) ;
CloseHandle(ov.hEvent);
return TRUE;
}
void CSerial::CommWatchProc(LPVOID pParam)
{
assert(pParam != 0);
HANDLE _hIDComDev = pParam;
DWORD dwBytesRead = 0;
DWORD dwWaitOverTime = 0; //ms单项位时间
BOOL isSend = FALSE;
char szTmp[MAXSERBUF];
OVERLAPPED ovRead;
memset(&ovRead,0,sizeof(ovRead));
ovRead.hEvent = CreateEvent(0, true, 0, 0);
while(m_bOpened){
WaitForSingleObject(W_Event, INFINITE);
if (isSend && dwWaitOverTime>=2){
PulseEvent(R_Event);
dwWaitOverTime = 0;
isSend = FALSE;
}
dwBytesRead = 1;//ComStat.cbInQue;
if (dwBytesRead + m_dwRevBuf > MAXSERBUF){
PulseEvent(R_Event);
continue;
}
if (!ReadFile(_hIDComDev, szTmp, dwBytesRead, &dwBytesRead, &ovRead) ) return;
if (dwBytesRead > 0){
isSend = TRUE;
dwWaitOverTime = 0;
m_szRevBuf[m_dwRevBuf] = szTmp[0]; //dwBytesRead);
m_dwRevBuf += dwBytesRead;
continue;
}
dwWaitOverTime++;
Sleep(1);
}
CloseHandle( ovRead.hEvent );
}
DWORD CSerial::Transmit(PBYTE pbSendBuffer, DWORD cbSendLength,
PBYTE pbRecvBuffer, DWORD *pcbRecvLength,
DWORD dwOverTime)
{
if (!isOpen()) return ERROR_ACCESS_DENIED;
if (cbSendLength > MAXSERBUF || pbRecvBuffer == NULL ||
pbSendBuffer == NULL || pcbRecvLength == NULL)
return ERROR_INVALID_PARAMETER;
WriteComm(pbSendBuffer, cbSendLength);
m_dwRevBuf = 0;
StarRevData();
if (WaitForSingleObject(R_Event, dwOverTime))
{
StopRevData();
return WAIT_TIMEOUT;
}
StopRevData();
memcpy(pbRecvBuffer, m_szRevBuf, m_dwRevBuf);
*pcbRecvLength = m_dwRevBuf;
m_dwRevBuf = 0;
return 0;
}
VOID CSerial::StopRevData()
{
ResetEvent(W_Event);
}
VOID CSerial::StarRevData()
{
SetEvent(W_Event);
}
VOID CSerial::StarMonitor()
{
//创建一个读事件, 读完数据后产生该事件
R_Event = CreateEvent(NULL, TRUE, false, NULL);
//创建一个写事件, 写完数据后产生该事件
W_Event = CreateEvent(NULL, TRUE, false, NULL);
//开始
::_beginthread(CommWatchProc, 0, m_hIDComDev);
}