📄 serialport.cpp
字号:
#include "stdafx.h"
#include "SerialPort.h"
#include <assert.h>
//
// Constructor
//
CSerialPort::CSerialPort()
{
m_hComm = NULL;
// initialize overlapped structure members to zero
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;
// create events
m_ov.hEvent = NULL;
m_hWriteEvent = NULL;
m_hShutdownEvent = NULL;
m_szWriteBuffer = NULL;
m_nWriteSize=1;
m_bThreadAlive = FALSE;
}
//
// Delete dynamic memory
//
CSerialPort::~CSerialPort()
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
delete [] m_szWriteBuffer;
}
//
// Initialize the port. This can be port 1 to 4.
//
BOOL CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
CString str_SerialPort, // portnumber (1..4) portnr
int baud, // baudrate
int parityBit, // parity
int dataBits, // databits
int stopBits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
UINT writebuffersize) // size to the writebuffer
{
// assert(portnr > 0 && portnr < 5);
// assert(pPortOwner != NULL);
// CString str_SerialPort = portnr;
// if the thread is alive: Kill
if (m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
}
// create events
if (m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent != NULL)
ResetEvent(m_hWriteEvent);
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent != NULL)
ResetEvent(m_hShutdownEvent);
m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
// initialize the event objects
m_hEventArray[0] = m_hShutdownEvent; // highest priority
m_hEventArray[1] = m_ov.hEvent;
m_hEventArray[2] = m_hWriteEvent;
// initialize critical section
InitializeCriticalSection(&m_csCommunicationSync);
// set buffersize for writing and save the owner
m_pOwner = pPortOwner;
if (m_szWriteBuffer != NULL)
delete [] m_szWriteBuffer;
m_szWriteBuffer = new char[writebuffersize];
//m_nPortNr = portnr;
m_nWriteBufferSize = writebuffersize;
m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE;
// char *szPort = new char[50];
// char *szBaud = new char[50];
// now it critical!
EnterCriticalSection(&m_csCommunicationSync);
// if the port is already opened: close it
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
// 打开串口
if (!OpenSerialPort(str_SerialPort))
return FALSE;
// 配置串口
if (!ConfigSeriport(baud, parityBit, dataBits, stopBits))
return FALSE;
/* // prepare port strings
sprintf(szPort, "COM%d", portnr);
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
// get a handle to the port
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
// port not found
delete [] szPort;
delete [] szBaud;
return FALSE;
}
// set the timeout values
m_CommTimeouts.ReadIntervalTimeout = 1000;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
// configure
if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
{
if (SetCommMask(m_hComm, dwCommEvents))
{
if (GetCommState(m_hComm, &m_dcb))
{
m_dcb.EvtChar = 'q';
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
if (BuildCommDCB(szBaud, &m_dcb))
{
if (SetCommState(m_hComm, &m_dcb))
; // normal operation... continue
else
ProcessErrorMessage("SetCommState()");
}
else
ProcessErrorMessage("BuildCommDCB()");
}
else
ProcessErrorMessage("GetCommState()");
}
else
ProcessErrorMessage("SetCommMask()");
}
else
ProcessErrorMessage("SetCommTimeouts()");
delete [] szPort;
delete [] szBaud;
// flush the port
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// release critical section
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);
*/
return TRUE;
}
BOOL CSerialPort::OpenSerialPort(CString str_SerialPort){
// CString str_SerialPort; //串口号
if(str_SerialPort) {
LPCSTR port = str_SerialPort;
// get a handle to the port
m_hComm = CreateFile(str_SerialPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
0); // template must be 0 for comm devices
}
if(m_hComm == INVALID_HANDLE_VALUE)
return FALSE;
// flush the port
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// release critical section
LeaveCriticalSection(&m_csCommunicationSync);
return TRUE;
}
BOOL CSerialPort::ConfigSeriport(int baud, int parityBit, int dataBits, int stopBits ) {
// int int_Baud = 9600; //波特率
// int int_DataBits = 8; //数据位
// int int_Parity = 1; //校验位
// int int_StopBits = 2; //停止位
// int int_FlowCtrl; //流控制选项
// BOOL b_EnabParity = FALSE; // 奇偶校验使能
if(m_hComm == INVALID_HANDLE_VALUE)
return FALSE;
if(!GetCommState(m_hComm, &m_dcb))
return FALSE;
// m_dcb.fBinary = TRUE; // 二进制传输
// m_dcb.BaudRate = int_Baud; // 波特率
// m_dcb.ByteSize = int_DataBits; // 数据位数
// m_dcb.fParity = b_EnabParity; // 奇偶校验使能位
m_dcb.fBinary=TRUE; // 二进制传输
m_dcb.BaudRate = baud; // 波特率
m_dcb.ByteSize = dataBits; // 数据位数
m_dcb.fParity = TRUE; // 奇偶校验位
switch(parityBit) // 校验设置
{
case 0:
m_dcb.Parity=NOPARITY; // 无奇偶校验
break;
case 1:
m_dcb.Parity=EVENPARITY; // 偶校验
break;
case 2:
m_dcb.Parity=ODDPARITY; // 奇校验
break;
default:; // 默认(不设定)
}
switch(stopBits) // 停止位
{
case 0:
m_dcb.StopBits=ONESTOPBIT; // 1
break;
case 1:
m_dcb.StopBits=ONE5STOPBITS; // 1.5
break;
case 2:
m_dcb.StopBits=TWOSTOPBITS; // 2
break;
default:; // 默认
}
/* switch(m_nFlowCtrl) //流控制选项设置
{
case 0:
// 硬件流控制设置
m_dcb.fOutxCtsFlow = FALSE;
m_dcb.fRtsControl = FALSE;
// XON/XOFF流控制设置
m_dcb.fInX=dcb.fOutX = FALSE;
//m_dcb.XonChar = XON;
//m_dcb.XoffChar = XOFF;
////m_dcb.XonLim = 50;
//m_dcb.XoffLim = 50;
break;
case 1:
// 硬件流控制设置
m_dcb.fOutxCtsFlow = TRUE;
m_dcb.fRtsControl = TRUE;
// XON/XOFF流控制设置
m_dcb.fInX=m_dcb.fOutX = FALSE;
//m_dcb.XonChar = XON;
//m_dcb.XoffChar = XOFF;
//m_dcb.XonLim = 50;
//m_dcb.XoffLim = 50;
break;
case 2:
// 软件流控制设置
m_dcb.fOutxCtsFlow = FALSE;
m_dcb.fRtsControl = FALSE;
// XON/XOFF流控制设置
m_dcb.fInX=m_dcb.fOutX = TRUE;
m_dcb.XonChar = XON;
m_dcb.XoffChar = XOFF;
m_dcb.XonLim = 50;
m_dcb.XoffLim = 50;
break;
default:
break;
}
*/
// DCB设定
if(!SetCommState(m_hComm, &m_dcb))
return FALSE;
// 把间隔超时设为最大,把总超时设为0将导致ReadFile立即返回并完成操作
m_CommTimeouts.ReadIntervalTimeout=MAXDWORD;
m_CommTimeouts.ReadTotalTimeoutMultiplier=0;
m_CommTimeouts.ReadTotalTimeoutConstant=0;
/* 设置写超时以指定WriteComm成员函数中的GetOverlappedResult函数的等待时间*/
m_CommTimeouts.WriteTotalTimeoutMultiplier=50;
m_CommTimeouts.WriteTotalTimeoutConstant=2000;
// 超时设定
SetCommTimeouts(m_hComm, &m_CommTimeouts);
SetupComm(m_hComm,MAXBLOCK,MAXBLOCK); // 缓冲区大小设定
SetCommMask(m_hComm, EV_RXCHAR); // 通信事件设定 EV_RXCHAR:输入缓冲区收到新字符
return TRUE;
}
//
// The CommThread Function.
//
UINT CSerialPort::CommThread(LPVOID pParam)
{
// Cast the void pointer passed to the thread back to
// a pointer of CSerialPort class
CSerialPort *port = (CSerialPort*)pParam;
// Set the status variable in the dialog class to
// TRUE to indicate the thread is running.
port->m_bThreadAlive = TRUE;
// Misc. variables
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
COMSTAT comstat;
BOOL bResult = TRUE;
// Clear comm buffers at startup
if (port->m_hComm) // check if the port is opened
PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// begin forever loop. This loop will run as long as the thread is alive.
for (;;)
{
// Make a call to WaitCommEvent(). This call will return immediatly
// because our port was created as an async port (FILE_FLAG_OVERLAPPED
// and an m_OverlappedStructerlapped structure specified). This call will cause the
// m_OverlappedStructerlapped element m_OverlappedStruct.hEvent, which is part of the m_hEventArray to
// be placed in a non-signeled state if there are no bytes available to be read,
// or to a signeled state if there are bytes available. If this event handle
// is set to the non-signeled state, it will be set to signeled when a
// character arrives at the port.
// we do this for each port!
bResult = WaitCommEvent(port->m_hComm, &Event, &port->m_ov);
if (!bResult)
{
// If WaitCommEvent() returns FALSE, process the last error to determin
// the reason..
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// This is a normal return value if there are no bytes
// to read at the port.
// Do nothing and continue
break;
}
case 87:
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -