📄 serial.cpp
字号:
// Serial.cpp: implementation of the CSerial class.
//
//////////////////////////////////////////////////////////////////////
/*
** FILENAME CSerial.cpp
**
** PURPOSE This class can read, write and watch one serial port.
** It sends messages to its owner when something happends on the port
** The class creates a thread for reading and writing so the main
** program is not blocked.
**
** CREATION DATE 15-09-2003
** LAST MODIFICATION 08-11-2003
**
** AUTHOR rootgr wu
**
**
*/
#include "stdafx.h"
#include "comm.h"
#include "Serial.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CSerial::CSerial()
{
// Init handle to NULL
m_hPort = NULL;
m_hThread = NULL;
m_nPortNr=0;
m_hWnd=NULL;
}
CSerial::~CSerial()
{
// release resources
//DWORD dwExitCode;
if(m_hPort !=NULL)
CloseHandle(m_hPort);
m_hPort = NULL;
if(m_hWnd!=NULL)
CloseHandle(m_hWnd);
m_hWnd = NULL;
/* Force Exit Thread.
if(m_hThread!=NULL)
{
GetExitCodeThread(m_hThread,&dwExitCode);
ExitThread(dwExitCode);
}
*/
StopReadThread();
m_hThread=NULL;
}
BOOL CSerial::InitializePort(HWND hWnd,CString PortNum,UINT Baud, CString Parity, UINT DataBits, UINT StopBits)
{
CString Nnn;
// initialize critical section
InitializeCriticalSection(&m_cs);
// now it critical!
EnterCriticalSection(&m_cs);
// Empty Port Handle.
if(m_hPort!=NULL)
{
CloseHandle(m_hPort);
m_hPort = NULL;
}
if(m_hThread!=NULL)
{
CloseHandle(m_hThread);
m_hThread = NULL;
}
if(m_hWnd!=NULL)
{
CloseHandle(m_hWnd);
m_hWnd = NULL;
}
// format port num.
if(PortNum==L"COM1") m_nPortNr=1;
if(PortNum==L"COM2") m_nPortNr=2;
Nnn = PortNum + ":";
// set message Handle.
m_hWnd=hWnd;
// Clear RX Buffer.
// memset(m_RXBuff,0,512);
m_hPort = CreateFile (Nnn, // Pointer to the name of the port
GENERIC_READ | GENERIC_WRITE,
// Access (read-write) mode
0, // Share mode
NULL, // Pointer to the security attribute
OPEN_EXISTING, // How to open the serial port
0, // Port attributes
NULL); // Handle to port with attribute
// to copy
if (m_hPort == INVALID_HANDLE_VALUE)
{
AfxMessageBox(_T("can't open port!"));
return FALSE;
}
// Get Comm DCB
if(!GetCommState(m_hPort,&m_dcb)) return FALSE;
// Set Comm DCB
m_dcb.BaudRate = Baud;
if(Parity == "NONE") m_dcb.Parity = 0;
if(Parity == "ODD") m_dcb.Parity = 1;
if(Parity == "EVEN") m_dcb.Parity = 2;
m_dcb.ByteSize = DataBits;
if(StopBits == 1) m_dcb.StopBits = ONESTOPBIT;
if(StopBits == 1.5) m_dcb.StopBits = ONE5STOPBITS;
if(StopBits == 2) m_dcb.StopBits = TWOSTOPBITS;
if(!SetCommState(m_hPort,&m_dcb)) return FALSE;
// Get Comm Timeouts
if(!GetCommTimeouts(m_hPort,&m_CommTimeouts)) return FALSE;
// Set Comm Timeouts
m_CommTimeouts.ReadIntervalTimeout = 500;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 500;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 500;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
if(!SetCommTimeouts(m_hPort,&m_CommTimeouts))
return FALSE;
// Set Comm Mask
if(!SetCommMask(m_hPort,EV_RXCHAR | EV_CTS | EV_DSR | EV_RING))
return FALSE;
// flush the port
PurgeComm(m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// release critical section
LeaveCriticalSection(&m_cs);
return TRUE;
}
BOOL CSerial::WriteChar(BYTE Byte)
{
DWORD dwNumBytesWritten;
BOOL bResult;
// Clear Comm Error
PurgeComm(m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// write to port.
bResult = WriteFile(m_hPort, // Handle to COMM Port
&Byte, // Pointer to message buffer in calling finction
1, // Length of message to send
&dwNumBytesWritten, // Where to store the number of bytes sent
NULL);
if(!bResult || dwNumBytesWritten == 0) return FALSE;
return TRUE;
}
DWORD WINAPI CSerial::ReadThread(LPVOID lpParam)
{
CSerial *p=(CSerial *)lpParam;
DWORD dwCommStatus = 0; // comm event
BOOL bResult = FALSE; // waitcommevent result
BOOL bClear = FALSE; // clearcomm result
BOOL bReadResult = FALSE; // readfile result
DWORD dwNumBytesRead = 0; // number readed
COMSTAT comstat; // COMSTAT struct
DWORD dwError; // error message
unsigned char RXBuff; // receive buffer
// check if the port is opened,then clear buffer first.
if (p->m_hPort)
PurgeComm(p->m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
else
return 0;
// clear buffer again,maybe it is no necessary.
PurgeComm(p->m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
while (1)
{
// Wait for an event to occur for the port.
bResult = WaitCommEvent (p->m_hPort, &dwCommStatus, NULL);
if (bResult && (dwCommStatus & EV_RXCHAR))
{
do
{
// now it critical!
EnterCriticalSection(&p->m_cs);
// Clear port Error message.
bClear = ClearCommError(p->m_hPort, &dwError, &comstat);
if(comstat.cbInQue ==0) break;
// clear RX Buffer and count
dwNumBytesRead = 0;
RXBuff = 0;
bReadResult = ReadFile(p->m_hPort , // Handle to COMM port
&RXBuff, // RX Buffer Pointer
1, // Read one byte
&dwNumBytesRead, // Stores number of bytes read
NULL);
// release critical section
LeaveCriticalSection(&p->m_cs);
// display data.
if(bReadResult && dwNumBytesRead == 1)
{
SendMessage(p->m_hWnd,WM_COMM_RXCHAR,(WPARAM)RXBuff,(LPARAM)p->m_nPortNr);
}
}while(bReadResult && dwNumBytesRead == 1);
}
}
return 1;
}
BOOL CSerial::ClosePort()
{
// Close Port Handle.
if(m_hPort!=NULL)
CloseHandle(m_hPort);
if(m_hWnd!=NULL)
CloseHandle(m_hWnd);
// Set port handle to NULL.
m_hPort=NULL;
m_hWnd=NULL;
// delete CRITICAL_SECTION
DeleteCriticalSection(&m_cs);
return TRUE;
}
BOOL CSerial::StartReadThread()
{
DWORD dwThreadID;
// Start Comm Thread.
if(!(m_hThread=(HANDLE)CreateThread(NULL,0,ReadThread,this,0,&dwThreadID)))
return FALSE;
return TRUE;
}
BOOL CSerial::WriteChar(LPCTSTR lpString)
{
DWORD dwNumBytesWritten;
BOOL bResult;
//UINT len = wcslen(lpString);
// Clear Comm Error
PurgeComm(m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// write to port.
bResult = WriteFile(m_hPort, // Handle to COMM Port
lpString, // Pointer to message buffer in calling finction
wcslen(lpString)*2, // Length of message to send
&dwNumBytesWritten, // Where to store the number of bytes sent
NULL);
if(!bResult || dwNumBytesWritten == 0) return FALSE;
return TRUE;
}
BOOL CSerial::WriteChar(char *buf)
{
DWORD dwNumBytesWritten;
BOOL bResult;
// Clear Comm Error
PurgeComm(m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// write to port.
bResult = WriteFile(m_hPort, // Handle to COMM Port
buf, // Pointer to message buffer in calling finction
strlen(buf), // Length of message to send
&dwNumBytesWritten, // Where to store the number of bytes sent
NULL);
if(!bResult || dwNumBytesWritten == 0) return FALSE;
return TRUE;
}
void CSerial::StopReadThread()
{
DWORD dwExitCode; // thread exit code
UINT nError; // return error code
GetExitCodeThread(m_hThread,&dwExitCode); // get Exit code
nError = TerminateThread(m_hThread,dwExitCode); // stop and delete readthread
if(nError = 0)
{
TRACE(L"TerminateThread Fail");
// AfxMessageBox(L"TerminateThread Fail");
}
}
BOOL CSerial::WriteChar(char *buf, int nsize)
{
DWORD dwNumBytesWritten;
BOOL bResult;
// Clear Comm Error
PurgeComm(m_hPort, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// write to port.
bResult = WriteFile(m_hPort, // Handle to COMM Port
buf, // Pointer to message buffer in calling finction
nsize, // Length of message to send
&dwNumBytesWritten, // Where to store the number of bytes sent
NULL);
if(!bResult || dwNumBytesWritten == 0) return FALSE;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -