📄 uart.cpp
字号:
#include "stdafx.h"
#include <windows.h>
#include "systemtype\bastype.h"
#include "charque.h"
#include "uart.h"
#include "sysfun.h"
/*!
* <Detailed description of the method>
*
* UART constructor
*
* @param VOID :
*
* @return :
*/
char port[][8] =
{
"COM1",
"COM2",
"COM3",
"COM4"
};
#define CBR_76800 76800
#define CBR_115200 115200
DWORD baudRate[] =
{
CBR_4800 ,
CBR_9600 ,
CBR_14400 ,
CBR_19200 ,
CBR_38400 ,
CBR_57600 ,
CBR_76800 ,
CBR_115200,
};
BYTE Parity[] =
{
NOPARITY ,//No parity
ODDPARITY ,//Odd
EVENPARITY //Even
};
UART::UART( VOID )
{
handler = NULL;
m_bOpened = FALSE;
memset( &overlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &overlappedWrite, 0, sizeof( OVERLAPPED ) );
overlappedRead.hEvent = NULL;
overlappedRead.Offset = 0;
overlappedRead.OffsetHigh = 0;
overlappedWrite.hEvent = NULL;
overlappedWrite.Offset = 0;
overlappedWrite.OffsetHigh = 0;
m_totalCnt=0;
m_minCnt=0;
m_maxCnt=0;
return;
}
/*!
* <Detailed description of the method>
*
* UART destructor
*
* @param VOID :
*
* @return :
*/
UART::~UART( VOID )
{
Close();
}
/*!
* <Detailed description of the method>
*
* request that serial port is opened
*
* @param none
*
* @return BOOL : TRUE: opened; FALSE: is not opened
*/
BOOL UART::isOpened()
{
return m_bOpened;
}
/*!
* <Detailed description of the method>
*
* Close the serial port
*
* @param none
*
* @return VOID :
*/
VOID UART::Close()
{
m_bOpened = FALSE;
if ( NULL != handler)
CloseHandle(handler);
if ( NULL != overlappedRead.hEvent )
CloseHandle ( overlappedRead.hEvent );
if ( NULL != overlappedWrite.hEvent )
CloseHandle ( overlappedWrite.hEvent );
}
/*!
* Open the serial port
*
* @param nPort : the port to be open
* @param nBaudRate : the baud rate to set
* @param nParity : the parity to set
*
* @return BOOL : if the function succeeds,the return value is nonzero
* if the function fail, the return value is zero
*/
BOOL UART::Open(INT nPort,INT nBaudRate,INT nParity)
{
if ( TRUE == m_bOpened )
Close();
COMMTIMEOUTS CommTimeOuts;
DCB dcb;
DWORD errorCode;
// create read event
memset(&overlappedRead,0,sizeof(OVERLAPPED));
overlappedRead.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ); // no name
if (NULL == overlappedRead.hEvent)
return FALSE;
// create write event
memset(&overlappedWrite,0,sizeof(OVERLAPPED));
overlappedWrite.hEvent = CreateEvent( NULL, // no security
TRUE, // explicit reset req
FALSE, // initial event reset
NULL ) ; // no name
if (NULL == overlappedWrite.hEvent)
return FALSE;
// create file
if ( INVALID_HANDLE_VALUE == (handler =
CreateFile( port[nPort],
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // no security attrs
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL )) )
{
errorCode = GetLastError();
return FALSE;
}
// get any early notifications
if ( ! SetCommMask( handler, EV_RXCHAR | EV_ERR ) )
return FALSE;
// setup device buffers
if ( ! SetupComm( handler, 4096, 4096 ) )
return FALSE;
// setup device buffers larger
//SetupComm( handler, 10240, 10240 ) ;
// purge any information in the buffer
if ( ! PurgeComm( handler,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) )
return FALSE;
// set up for overlapped I/O
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;//0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
// CBR_19200 is approximately 2.5byte/ms. For our purposes, allow
// double the expected time per character for a fudge factor.
CommTimeOuts.WriteTotalTimeoutMultiplier = 50; //2*CBR_9600/CBR_19200; //0;
// can be zero ???????????
CommTimeOuts.WriteTotalTimeoutConstant = 2000; // 5000
SetCommTimeouts( handler, &CommTimeOuts ) ;
if ( ! GetCommState( handler, &dcb ) )
return FALSE;
dcb.DCBlength = sizeof( DCB );
dcb.BaudRate = baudRate[nBaudRate];
//dcb.BaudRate = 256000;
// CBR_256000
// dcb.BaudRate =CBR_256000;
dcb.BaudRate =CBR_115200;
dcb.fBinary = TRUE;
dcb.fParity = TRUE;
dcb.ByteSize = 8;
dcb.Parity = Parity[nParity];
dcb.StopBits = ONESTOPBIT;
// setup hardware flow control
dcb.fOutxDsrFlow = FALSE;
dcb.fDtrControl = DTR_CONTROL_DISABLE ;
dcb.fOutxCtsFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE ;
dcb.fDsrSensitivity = FALSE;
dcb.fInX = dcb.fOutX = FALSE ;
dcb.fNull = TRUE;
// other various settings
if ( ! SetCommState( handler, &dcb ) )
return FALSE;
m_bOpened = TRUE;
return TRUE;
}
/*!
* receive interrupt service routine
*
* @param block the buffer for saving received characters
* @param blockLen the length of the block
*
* @return the number of characters received
*/
// DWORD length;
// UCHAR block[100];
INT UART::RxString( VOID )
{
BOOL readStat;
COMSTAT comStat;
DWORD erroFlag;
DWORD error;
INT reCheck;
DWORD length;
UCHAR block[100];
//==bug,md by ywy ,when there are multi com
//static long totalCnt = 0, minCnt = 0, maxCnt = 0;
long totalCnt = 0, minCnt = 0, maxCnt = 0;
totalCnt = m_totalCnt;
minCnt = m_minCnt;
maxCnt = m_maxCnt;
//--bug
// only try to read number of bytes in queue
ClearCommError( handler, &erroFlag, &comStat );
length = comStat.cbInQue;
totalCnt ++;
// return if no characters received from UART
if ( 0 >= length )
{
minCnt ++;
return 0;
}
reCheck = 0;
if (100 <= length )
{
maxCnt ++;
length = 100;
reCheck = 1;
}
readStat = ReadFile( handler, block, length, &length, &overlappedRead );
if ( !readStat )
{
if ( ERROR_IO_PENDING == GetLastError() )
{
//OutputDebugString("\n\rIO Pending");
// We have to wait for read to complete.
// This function will timeout according to the
// CommTimeOuts.ReadTotalTimeoutConstant variable
// Every time it times out, check for port errors
while ( !GetOverlappedResult( handler, &overlappedRead, &length, TRUE ) )
{
error = GetLastError();
if (ERROR_IO_INCOMPLETE == error)
// normal result if not finished
continue;
else
{
// an error occurred, try to recover
ClearCommError(handler , &erroFlag, &comStat ) ;
break;
}
}
}
else
{
// some other error occurred
length = 0;
ClearCommError( handler, &erroFlag, &comStat ) ;
}
}
mRxCharQue.PutString(block, length);
// save serial port receive data
if ( gbDumpReceiveData )
{
//if ( RECEIVE_BUFFER_LENGTH < length )
// length = RECEIVE_BUFFER_LENGTH;
DWORD len2Tail = gSerialReceiveTail - gSerialReceivePtr + 1;
if ( len2Tail > length )
{
memcpy(gSerialReceivePtr,block,length);
gSerialReceivePtr += length;
}
else
{
memcpy(gSerialReceivePtr,block,len2Tail );
gSerialReceivePtr = gSerialReceiveHead;
memcpy(gSerialReceivePtr,block+len2Tail,length-len2Tail);
gSerialReceivePtr += length-len2Tail;
}
gSerialReceiveCount += length;
if ( RECEIVE_BUFFER_LENGTH < gSerialReceiveCount )
gSerialReceiveCount = RECEIVE_BUFFER_LENGTH;
}
// dump data if required
// dump data if required
m_totalCnt = totalCnt ;
m_minCnt=minCnt ;
m_maxCnt=maxCnt ;
return reCheck;
//return 1;
}
/*!
* Transmit a string
*
* @param string the characters to be transmited
* @param strLen the number of characters of the string
*
* @return <code>0</code> if buffer is full, no operation,
* <code>1</code> if transmit success
*/
INT UART::TxString(UCHAR* string, INT strLen)
{
BOOL wirteStat;
DWORD bytesWritten;
DWORD errorFlag;
DWORD error;
int bytesSent = 0;
COMSTAT comStat;
wirteStat = WriteFile( handler, string, strLen,
&bytesWritten, &overlappedWrite ) ;
// Note that normally the code will not execute the following
// because the driver caches write operations. Small I/O requests
// (up to several thousand bytes) will normally be accepted
// immediately and WriteFile will return true even though an
// overlapped operation was specified
if ( !wirteStat)
{
if ( ERROR_IO_PENDING == GetLastError() )
{
// We should wait for the completion of the write operation
// so we know if it worked or not
// This is only one way to do this. It might be beneficial to
// place the write operation in a separate thread
// so that blocking on completion will not negatively
// affect the responsiveness of the UI
// If the write takes too long to complete, this
// function will timeout according to the
// CommTimeOuts.WriteTotalTimeoutMultiplier variable.
// This code logs the timeout but does not retry
// the write.
while (!GetOverlappedResult( handler, &overlappedWrite, &bytesWritten, TRUE ))
{
error = GetLastError();
if ( ERROR_IO_INCOMPLETE == error )
{
// normal result if not finished
bytesSent += bytesWritten;
continue;
}
else
{
ClearCommError( handler, &errorFlag, &comStat );
break;
}
}
bytesSent += bytesWritten;
}
else
{
// some other error occurred
ClearCommError( handler, &errorFlag, &comStat );
return 0;
}
}
// save serial port transmit data
if ( gbDumpTransmitData )
{
//if ( TRANSMIT_BUFFER_LENGTH < strLen )
// strLen -= TRANSMIT_BUFFER_LENGTH;
int len2Tail = gSerialTransmitTail - gSerialTransmitPtr + 1;
if ( len2Tail > strLen )
{
memcpy(gSerialTransmitPtr,string,strLen);
gSerialTransmitPtr += strLen;
}
else
{
memcpy(gSerialTransmitPtr,string,len2Tail );
gSerialTransmitPtr = gSerialTransmitHead;
memcpy(gSerialTransmitPtr,string+len2Tail,strLen-len2Tail);
gSerialTransmitPtr += strLen-len2Tail;
}
gSerialTransmitCount += strLen;
if ( TRANSMIT_BUFFER_LENGTH < gSerialTransmitCount )
gSerialTransmitCount = TRANSMIT_BUFFER_LENGTH;
}
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -