?? ceserial.cpp
字號:
// CeSerial.cpp: implementation of the CCeSerial class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CeSerial.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCeSerial::CCeSerial()
{
m_hComm = INVALID_HANDLE_VALUE; /* 串口操作句柄無效 */
hRecvThread = NULL;
m_ExitThreadEvent = NULL; /* 串口接收線程退出事件無效 */
}
CCeSerial::~CCeSerial()
{
ClosePort();
if (hRecvThread != NULL)
{
CloseHandle(hRecvThread);
SetEvent(m_ExitThreadEvent); /* 通知串口接收線程退出 */
Sleep(200);
CloseHandle(m_ExitThreadEvent); /* 關閉線程退出事件 */
}
}
/*******************************************************************************************
函數名稱: CCeSerial::CommRecvTread
描 述: 串口接收線程
輸入參數: LPVOID lparam: 線程參數,創建線程時傳入
輸出參數: 無
返 回: 0: 線程退出, 返回值沒特殊含義
********************************************************************************************/
DWORD CCeSerial::CommRecvTread(LPVOID lparam)
{
DWORD dwLength;
BYTE *recvBuf = new BYTE[1024];
CCeSerial *pCeSerial = (CCeSerial *)lparam;
while(TRUE)
{ /* 等待線程退出事件 */
if (WaitForSingleObject(pCeSerial->m_ExitThreadEvent, 0) == WAIT_OBJECT_0)
break;
if (pCeSerial->m_hComm != INVALID_HANDLE_VALUE)
{ /* 從串口讀取數據 */
BOOL fReadState = ReadFile(pCeSerial->m_hComm, recvBuf, 1024, &dwLength, NULL);
if(!fReadState)
{
//MessageBox(_T("無法從串口讀取數據!"));
}
else
{
if(dwLength != 0) /* 接收成功調用回調函數 */
pCeSerial->OnCommRecv(pCeSerial->m_UserParam, recvBuf, dwLength);
}
}
}
delete[] recvBuf;
recvBuf = NULL;
return 0;
}
/*******************************************************************************************
函數名稱: CCeSerial::OpenPort
描 述: 打開串口
輸入參數: LPCTSTR Port: 串口名,如"COM0:","COM1:"
DWORD BaudRate: 波特率
DWORD DataBits: 數據位, 取值為7或8
DWORD StopBits: 停止位
DWORD Parity : 奇偶校驗位
輸出參數: 無
返 回: FALSE: 失敗; TRUE: 成功
********************************************************************************************/
BOOL CCeSerial::OpenPort(LPCTSTR Port, DWORD BaudRate, DWORD DataBits, DWORD StopBits, DWORD Parity,
BOOL bDTRShake, BOOL bRTSShake, DWORD UserParam)
{
COMMTIMEOUTS CommTimeOuts;
// 打開串口
m_hComm = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(m_hComm == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("無法打開端口或端口已打開!請檢查是否已被占用."));
return FALSE;
}
GetCommState(m_hComm, &dcb); /* 讀取串口的DCB */
dcb.BaudRate = BaudRate;
dcb.ByteSize = DataBits;
dcb.Parity = Parity;
dcb.StopBits = StopBits;
dcb.fParity = FALSE; /* 禁止奇偶校驗 */
dcb.fBinary = TRUE;
if (bDTRShake == FALSE)
dcb.fDtrControl = 0; /* 禁止流量控制 */
else
dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
if (bRTSShake == FALSE)
dcb.fRtsControl = 0;
else
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fOutX = 0;
dcb.fInX = 0;
dcb.fTXContinueOnXoff = 0;
//設置狀態參數
SetCommMask(m_hComm, EV_RXCHAR); /* 串口事件:接收到一個字符 */
SetupComm(m_hComm, 2048, 2048); /* 設置接收與發送的緩沖區大小 */
if(!SetCommState(m_hComm, &dcb)) /* 設置串口的DCB */
{
AfxMessageBox(_T("無法按當前參數配置端口,請檢查參數!"));
ClosePort();
return FALSE;
}
//設置超時參數
GetCommTimeouts(m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = 100; /* 接收字符間最大時間間隔 */
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 100; /* 讀數據總超時常量 */
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 0;
if(!SetCommTimeouts(m_hComm, &CommTimeOuts))
{
AfxMessageBox(_T("無法設置超時參數!"));
ClosePort();
return FALSE;
}
PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); /* 清除收/發緩沖區 */
m_UserParam = UserParam; /* 傳遞用戶參數 */
// 創建線程及句柄
DWORD IDThread;
/* 創建串口接收線程退出事件*/
m_ExitThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// 創建串口接收線程
hRecvThread = CreateThread(0, 0, CommRecvTread, this, 0, &IDThread);
if (hRecvThread == NULL)
{
ClosePort();
AfxMessageBox(_T("創建接收線程失敗!"));
return FALSE;
}
return TRUE;
}
/*******************************************************************************************
函數名稱: IsPortOpen
描 述: 判斷串口是否打開
輸入參數: 無
輸出參數: 無
返 回: FALSE: 串口打開; TRUE: 串口關閉
********************************************************************************************/
BOOL CCeSerial::IsPortOpen(void)
{
if(m_hComm != INVALID_HANDLE_VALUE)
return TRUE;
return FALSE;
}
/*******************************************************************************************
函數名稱: CCeSerial::ClosePort
描 述: 關閉串口
輸入參數: 無
輸出參數: 無
返 回: FALSE: 失敗; TRUE: 成功
********************************************************************************************/
BOOL CCeSerial::ClosePort(void)
{
if(m_hComm != INVALID_HANDLE_VALUE)
{
SetCommMask(m_hComm, 0);
PurgeComm(m_hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); /* 清除收/發緩沖 */
CloseHandle(m_hComm); /* 關閉串口操作句柄 */
m_hComm = INVALID_HANDLE_VALUE;
return TRUE;
}
return FALSE;
}
/*******************************************************************************************
函數名稱: Senddata
描 述: 串口發送數據
輸入參數: BYTE *psendbuf:要發送的數據, DWORD length:數據長度
輸出參數: 無
返 回: 無
********************************************************************************************/
void CCeSerial::Senddata(BYTE *psendbuf, DWORD length)
{
DWORD dwactlen;
if (m_hComm == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("串口未打開!"));
return;
}
WriteFile(m_hComm, psendbuf, length, &dwactlen, NULL); /* 從串口發送數據 */
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -