📄 serial.cpp
字号:
//************************************************
//项目:
//文件名:Serial.cpp
//功能:串口类
//日期:2008/07/28
//版权:Copyright (C) 2008
//作者:杨世峰
//
//修改备注
//...
//************************************************
#include "StdAfx.h"
#include "Serial.h"
/*这是一个线程读的例子,你可以在你的主程序里参考该函数写出你需要的函数*/
//参数为串口类指针
DWORD CommReadThread(LPVOID lpParam)
{
HANDLE hComm;
CSerial* pSerial;
pSerial = (CSerial*)lpParam;
hComm = pSerial->Comm_GetHandle();
DWORD dwReaded, dwMask;
BYTE btRecv;
if(hComm != INVALID_HANDLE_VALUE)
::SetCommMask(hComm,EV_RXCHAR);
while(pSerial->Comm_GetHandle() != INVALID_HANDLE_VALUE)
{
hComm = pSerial->Comm_GetHandle();
::WaitCommEvent(hComm,&dwMask,NULL);
::SetCommMask(hComm,EV_RXCHAR);
if(dwMask & EV_RXCHAR)
{
do
{
::ReadFile(hComm,&btRecv,1,&dwReaded,NULL);
if(dwReaded == 1)
{
pSerial->Comm_Process(btRecv);
}
}
while(dwReaded == 1);
}
}
return 0;
}
CSerial::CSerial(void)
{
this->m_hComm = INVALID_HANDLE_VALUE;
}
CSerial::~CSerial(void)
{
this->m_hWnd = NULL;
}
BOOL CSerial::Comm_Open(int nComm, DWORD dwBaut, PARITY parity, BYTE btDataBits, STOPBITS stopbits, FLOWCONTROL fc)
{
CString str;
COMMTIMEOUTS CommTimeouts;
if(this->Comm_IsOpen())
return TRUE;
str.Format(TEXT("COM%d:"),nComm);
this->m_hComm = CreateFile((LPTSTR)(LPCTSTR)str,
GENERIC_READ | GENERIC_WRITE,
0,
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(this->m_hComm == INVALID_HANDLE_VALUE)
{
::AfxMessageBox(TEXT("打开串口错误!"));
return FALSE;
}
if(!this->Comm_SetBuffer(COMM_BUFFER_IN,COMM_BUFFER_OUT))
{
this->Comm_Close();
::AfxMessageBox(TEXT("串口缓冲设置错误!"));
return FALSE;
}
//set comm
if(!this->Comm_SetBaut(dwBaut,parity,btDataBits,stopbits,fc))
{
this->Comm_Close();
::AfxMessageBox(TEXT("串口设置错误!"));
return FALSE;
}
//set commtimeouts
GetCommTimeouts(this->m_hComm, &CommTimeouts);
// Change the COMMTIMEOUTS structure settings.
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 10;
CommTimeouts.WriteTotalTimeoutConstant = 1000;
// Set the time-out parameters for all read and write operations
// on the port.
if (FALSE == SetCommTimeouts(this->m_hComm, &CommTimeouts))
{
::AfxMessageBox(TEXT("串口设置错误!"));
this->Comm_Close();
return FALSE;
}
if(!this->Comm_Clear(PURGE_TXCLEAR | PURGE_RXCLEAR))
{
::AfxMessageBox(TEXT("清空缓冲错误!"));
this->Comm_Close();
return FALSE;
}
return TRUE;
}
BOOL CSerial::Comm_IsOpen(void)
{
return (this->m_hComm != INVALID_HANDLE_VALUE);
}
void CSerial::Comm_Close(void)
{
if(this->Comm_IsOpen())
{
if(!CloseHandle(this->m_hComm))
{
TRACE(TEXT("关闭串口错误%d\n"),::GetLastError());
}
this->m_hComm = INVALID_HANDLE_VALUE;
}
}
HANDLE CSerial::Comm_GetHandle(void)
{
return this->m_hComm;
}
BOOL CSerial::Comm_SetBaut(DWORD dwBaut, PARITY parity, BYTE btDataBits, STOPBITS stopbits, FLOWCONTROL fc)
{
DCB dcb;
if(!this->Comm_IsOpen())
return FALSE;
// set dcb
dcb.DCBlength = sizeof(DCB);
::GetCommState(this->m_hComm,&dcb);
//set baut
dcb.BaudRate = dwBaut;
//set parity
dcb.fParity = TRUE;
switch(parity)
{
case PT_NONE:
dcb.fParity = FALSE;
dcb.Parity = NOPARITY;
break;
case PT_ODD:
dcb.Parity = ODDPARITY;
break;
case PT_EVEN:
dcb.Parity = EVENPARITY;
break;
default:
dcb.fParity = FALSE;
dcb.Parity = NOPARITY;
}
//set databits
dcb.ByteSize = btDataBits;
//stop bits
switch(stopbits)
{
case SB_ONE:
dcb.StopBits = ONESTOPBIT;
break;
case SB_ONEPOINTFIVE:
dcb.StopBits = ONE5STOPBITS;
break;
case SB_TWO:
dcb.StopBits = TWOSTOPBITS;
break;
default:
dcb.StopBits = ONESTOPBIT;
}
//control
switch(fc)
{
case FC_NONE:
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
case FC_RTSCTS:
dcb.fOutxCtsFlow = TRUE;
dcb.fOutxDsrFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
break;
case FC_XONXOFF:
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutX = TRUE;
dcb.fInX = TRUE;
dcb.XonChar = 0x11;
dcb.XoffChar = 0x13;
dcb.XoffLim = COMM_XOFF_LIMIT;
dcb.XonLim = COMM_XON_LIMIT;
break;
default:
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
}
//
if(!::SetCommState(this->m_hComm,&dcb))
{
return FALSE;
}
return TRUE;
}
BOOL CSerial::Comm_SetBuffer(DWORD dwIn, DWORD dwOut)
{
if(!this->Comm_IsOpen())
{
return FALSE;
}
return ::SetupComm(this->m_hComm,dwIn,dwOut);
}
BOOL CSerial::Comm_Clear(DWORD dwFlags)
{
if(!this->Comm_IsOpen())
{
return FALSE;
}
return ::PurgeComm(this->m_hComm,dwFlags);
}
BOOL CSerial::Comm_Read(BYTE* pbtBuffer, DWORD dwCount, LPDWORD lpdwRead)
{
if(!this->Comm_IsOpen())
return FALSE;
return (::ReadFile(this->m_hComm,pbtBuffer,dwCount,lpdwRead,NULL));
}
BOOL CSerial::Comm_Write(BYTE* pbtBuffer, DWORD dwCount, LPDWORD lpdwWritten)
{
if(!this->Comm_IsOpen())
return FALSE;
return (::WriteFile(this->m_hComm,pbtBuffer,dwCount,lpdwWritten,NULL));
}
BOOL CSerial::Comm_BytesInBuffer(DWORD* lpdwIn, DWORD* lpdwOut)
{
if(!this->Comm_IsOpen())
return FALSE;
COMSTAT comstat;
DWORD dwError;
if(::ClearCommError(this->m_hComm,&dwError,&comstat))
{
*lpdwIn = comstat.cbInQue;
*lpdwOut = comstat.cbOutQue;
return TRUE;
}
return FALSE;
}
BOOL CSerial::Comm_GetModemStatus(LPDWORD lpdwStatus)
{
if(!this->Comm_IsOpen())
return FALSE;
return(::GetCommModemStatus(this->m_hComm,lpdwStatus));
}
void CSerial::Comm_Process(BYTE bRecv)
{
//这里调用了一个虚函数,便于从该类继承
this->Comm_ProcessDo(bRecv);
}
void CSerial::Comm_ProcessDo(BYTE bRecv)
{
//其它处理,特别是串口传输具有特定格式,可以放在这里处理
if(this->m_hWnd != NULL)
{
//接收到了字符,如果窗口句柄不为空,发送一个收到字符消息
//参考此消息,你可以定制你要的消息
::SendMessage(this->m_hWnd,WM_COMM_RECV,(WPARAM)bRecv,0);
}
}
void CSerial::Comm_SetWnd(HWND hWnd)
{
this->m_hWnd = hWnd;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -