?? port.cpp
字號:
// Port.cpp: implementation of the CPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Port.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#ifndef _DEBUG
#define DebugMsgStr(a) AfxMessageBox(a)
#else
#define DebugMsgStr(a) 0
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CPort::CPort()
{
//初始化數據
m_hComm = NULL;
m_szWriteBuffer = NULL;
m_bInited=FALSE;
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
m_ov.hEvent = NULL;
}
CPort::~CPort()
{
CloseHandle(m_hComm);
}
//初始化端口
BOOL CPort::Init1(UINT portnr,DWORD dwCommEvents,UINT writebuffersize)
{
//端口號只能是1到4
if (portnr<1||portnr>4)
{
DebugMsgStr("端口號超出范圍!");
return FALSE;
}
//設置m_ov的事件
if (m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//BOOL bResult;//得到函數調用結果
char *szPort = new char[5];//端口號對應的字符串
//生成要求的字符串
sprintf(szPort, "COM%d", portnr);
//對類變量進行賦值
if (m_szWriteBuffer != NULL)
delete [] m_szWriteBuffer;
m_szWriteBuffer = new char[writebuffersize];
m_nPortNr = portnr;
m_nWriteBufferSize = writebuffersize;
m_dwCommEvents = dwCommEvents;
//設置超時間隔
m_CommTimeouts.ReadIntervalTimeout = 50;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 50;
m_CommTimeouts.ReadTotalTimeoutConstant = 50;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 50;
m_CommTimeouts.WriteTotalTimeoutConstant = 50;
//如果端口已打開了,就把它關閉
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
//創建端口
m_hComm = CreateFile(szPort, // 端口號字符串
GENERIC_READ | GENERIC_WRITE, // 讀寫類型
0, // 絕對訪問
NULL, // 沒有安全屬性
OPEN_EXISTING, // 打開方式
FILE_FLAG_OVERLAPPED, // 異步
0); // 必須為0
//如果創建失敗則返回
if (m_hComm == INVALID_HANDLE_VALUE)
{
delete [] szPort;
// delete [] szBaud;
return FALSE;
}
//設置端口的其它屬性
//超時
if (!SetCommTimeouts(m_hComm, &m_CommTimeouts))
{
DebugMsgStr("設置端口超時錯誤!");
return FALSE;
}
if (!SetCommMask(m_hComm, dwCommEvents))
{
DebugMsgStr("設置端口觸發事件錯誤!");
return FALSE;
}
return TRUE;
}
BOOL CPort::InitPort(UINT portnr,DCB &dcb,DWORD dwCommEvents,UINT writebuffersize)
{
if(!Init1(portnr,dwCommEvents,writebuffersize))
return FALSE;
if (!SetCommState(m_hComm, &dcb))
{
DebugMsgStr("設置端口DCB錯誤!");
return FALSE;
}
//清空緩存
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
m_bInited=TRUE;
return TRUE;
}
BOOL CPort::InitPort(UINT portnr,// 端口號,數字1-4
UINT baud,// 波特率,整數,如9600,等。
char parity,// 奇偶校驗位,字符
// N-無校驗 O-奇校驗 E-偶校驗
// M-保持為1 S-保持為0 ,這兩項一般用于多機通信模式
UINT databits,// 數據位長度,整數
UINT stopbits,// 停止位長度,整數,1或2
DWORD dwCommEvents,// 觸發事件
UINT writebuffersize)//寫緩存的長度
{
if(!Init1(portnr,dwCommEvents,writebuffersize))
return FALSE;
char *szBaud = new char[50];//波特率對應的字符串
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
DCB m_dcb;
if (!GetCommState(m_hComm, &m_dcb))
{
DebugMsgStr("試圖得到DCB錯誤!");
return FALSE;
}
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
if (!BuildCommDCB(szBaud, &m_dcb))
{
DebugMsgStr("生成DCB錯誤!");
return FALSE;
}
if (!SetCommState(m_hComm, &m_dcb))
{
DebugMsgStr("設置端口DCB錯誤!");
return FALSE;
}
//清空緩存
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
m_bInited=TRUE;
return TRUE;
}
//往端口寫字符,cWriteData為要寫字符的指針
BOOL CPort::WriteChar(unsigned char cWriteData)
{
if (!m_bInited)
{
DebugMsgStr("端口尚未初始化!");
return FALSE;
}
//初始化變量
DWORD BytesSent = 0;
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
BOOL bResult;
//寫字符
bResult=WriteFile(m_hComm,&cWriteData,1,&BytesSent,&m_ov);
if (bResult)
{
//成功則返回
return TRUE;
}
//得到錯誤代碼
DWORD dwError = GetLastError();
//如果不是尚未完成則返回錯誤信號
if (dwError!=ERROR_IO_PENDING)
{
DebugMsgStr("寫字符錯誤!");
return FALSE;
}
//尚未完成則等待完成
if (!GetOverlappedResult(m_hComm,&m_ov,&BytesSent,TRUE))
{
//失敗返回錯誤信號
DebugMsgStr("寫字符錯誤!");
return FALSE;
}
//成功
return TRUE;
}
//往端口寫字符串,nNumToWrite為要寫字符串的長度,pDataAddr為字符串首地址
BOOL CPort::WriteData(LPVOID pDataAddr,DWORD nNumToWrite)
{
if (!m_bInited)
{
DebugMsgStr("端口尚未初始化!");
return FALSE;
}
//初始化變量
DWORD BytesSent = 0;
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
BOOL bResult;
//寫字符
bResult=WriteFile(m_hComm,pDataAddr,nNumToWrite,&BytesSent,&m_ov);
if (bResult)
{
//成功則返回
return TRUE;
}
//得到錯誤代碼
DWORD dwError = GetLastError();
//如果不是尚未完成則返回錯誤信號
if (dwError!=ERROR_IO_PENDING)
{
DebugMsgStr("寫字符串錯誤!");
return FALSE;
}
//尚未完成則等待完成
GetOverlappedResult(m_hComm,&m_ov,&BytesSent,TRUE);
if (BytesSent!=nNumToWrite)
{
//失敗返回錯誤信號
DebugMsgStr("沒有足夠的字符數!");
return FALSE;
}
//成功
return TRUE;
}
//從端口讀一個字符,cReadData接收字符,nWait-如果緩沖中沒有字符,等待時間的長度
BOOL CPort::ReadChar(unsigned char *cReadData,UINT nWait)
{
BOOL bResult;
DWORD dwError,dwBytesRead;
COMSTAT comstat;
if (!m_bInited)
{
DebugMsgStr("端口尚未初始化!");
return FALSE;
}
//得到當前輸入緩存狀態
bResult = ClearCommError(m_hComm, &dwError, &comstat);
//如果沒有數據且不等待則返回錯誤
if (comstat.cbInQue==0&&nWait==0)
{
DebugMsgStr("CPort::ReadChar-沒數據,不等了!");
return FALSE;
}
//讀字符
bResult = ReadFile(m_hComm,cReadData,1,&dwBytesRead,&m_ov);
if (!bResult)
{
//如果不是尚未完成則返回錯誤
if (dwError=GetLastError()!=ERROR_IO_PENDING)
{
DebugMsgStr("CPort::ReadChar-有問題!");
return FALSE;
}
if (WaitForSingleObject(m_ov.hEvent,nWait)!=WAIT_OBJECT_0)
{
DebugMsgStr("CPort::ReadChar-沒等到(足夠)數據!");
return FALSE;
}
}
//返回正確
return TRUE;
}
//從端口讀nNumToRead個字符,存在以pDataAddr為首地址的緩存中
//m_nWait表示輸入緩存中如果沒有足夠的數據,等待時間的長度
BOOL CPort::ReadData(LPVOID pDataAddr,DWORD nNumToRead,UINT m_nWait)
{
BOOL bResult;
DWORD dwError,dwBytesRead;
COMSTAT comstat;
if (!m_bInited)
{
DebugMsgStr("端口尚未初始化!");
return FALSE;
}
//得到當前輸入緩存狀態
bResult = ClearCommError(m_hComm, &dwError, &comstat);
//如果沒有數據且不等待則返回錯誤
if (comstat.cbInQue==0&&m_nWait==0)
{
DebugMsgStr("CPort::ReadString-沒數據,不等了!");
return FALSE;
}
//讀字符
bResult = ReadFile(m_hComm,pDataAddr,nNumToRead,&dwBytesRead,&m_ov);
if (!bResult)
{
//如果不是尚未完成則返回錯誤
if (dwError=GetLastError()!=ERROR_IO_PENDING)
{
DebugMsgStr("CPort::ReadString-有問題!");
return FALSE;
}
if (WaitForSingleObject(m_ov.hEvent,m_nWait)!=WAIT_OBJECT_0)
{
DebugMsgStr("CPort::ReadString-沒等到(足夠)數據!");
return FALSE;
}
}
//返回正確
return TRUE;
}
//從端口讀一個字符,如果沒有則等到有為止
BOOL CPort::WaitChar(unsigned char *pCharData)
{
DWORD pEvtMask,dwError;
COMSTAT comstat;
BOOL bResult;
unsigned char cGetData;
//端口未初始化錯誤
if (!m_bInited)
{
DebugMsgStr("端口尚未初始化!");
return FALSE;
}
//判斷輸入緩存中是否已經有了字符
bResult=ClearCommError(m_hComm, &dwError, &comstat);
//有則讀出并返回正確
if (comstat.cbInQue!=0)
{
bResult=ReadChar(&cGetData);
if (bResult)
{
*pCharData=cGetData;
return TRUE;
}
}
UINT nNum=0;
//等到讀出一個字符為止
while (nNum==0)
{
bResult=WaitCommEvent(m_hComm,&pEvtMask,&m_ov);
if (bResult)
{
//先判斷是否是出現了時間差引起的錯誤
bResult = ClearCommError(m_hComm, &dwError, &comstat);
//是錯誤則跳過這次循環,重新等待
if (comstat.cbInQue==0)
continue;
}
else
dwError = GetLastError();
//等待字符到來
WaitForSingleObject(m_ov.hEvent,INFINITE);
//讀字符
bResult=ReadChar(&cGetData);
if (bResult)
{
//讀出了則返回正確結果
*pCharData=cGetData;
nNum++;
}
else
{
//出了錯誤,繼續下一次等待
DebugMsgStr("WaitChar:read error!");
}
}
return TRUE;
}
//清緩存
void CPort::ClearBuffer()
{
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
}
//返回端口狀態
BOOL CPort::Inited()
{
return m_bInited;
}
BOOL CPort::SetMark(BOOL bMark)
{
DCB m_dcb;
if (!GetCommState(m_hComm, &m_dcb))
{
DebugMsgStr("試圖得到DCB錯誤!");
return FALSE;
}
if (bMark)
m_dcb.Parity = MARKPARITY;
else
m_dcb.Parity = SPACEPARITY;
if (!SetCommState(m_hComm, &m_dcb))
{
DebugMsgStr("設置端口DCB錯誤!");
return FALSE;
}
return TRUE;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -