?? rs232.cpp
字號:
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232 ////
//// ////
//// Author: MonkeyKing Aug 31th, 2003 ////
//// ////
////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
class RS232 {
public:
RS232( void );
RS232( LPCSTR lpszPortNum );
~RS232();
// For more definitions see <winbase.h>
int open( LPCSTR lpszPortNum = "com1", // 串口號
DWORD dwBaudRate = CBR_9600, // 波特率
BYTE byParity = NOPARITY, // 奇偶校驗
BYTE byStopBits = ONESTOPBIT,// 停止位個數
BYTE byByteSize = 8 ); // 字節長度
DWORD output( LPCVOID pdata, DWORD len );
DWORD input( LPVOID pdest, DWORD len, DWORD dwMaxWait = 500 );
LPSTR GetErrorMessage( void );
void close();
private:
VOID ErrorToString( LPCSTR lpszMessage );
BOOL IsNT( void );
TCHAR m_lpszErrorMessage[256];
HANDLE m_hCom; // 串口句柄
OVERLAPPED m_ov; // 包含異步輸入輸出操作信息的結構
};
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::RS232() ////
//// ////
////////////////////////////////////////////////////////////////////////////////
RS232::RS232( void )
{
m_hCom = 0;
m_lpszErrorMessage[0] = '\0';
ZeroMemory(&m_ov, sizeof(m_ov));
}
RS232::RS232( LPCSTR lpszPortNum )
{
RS232::RS232();
RS232::open( lpszPortNum );
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::~RS232() ////
//// ////
////////////////////////////////////////////////////////////////////////////////
RS232::~RS232() {
close();
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::GetErrorMessage ////
//// ////
////////////////////////////////////////////////////////////////////////////////
LPSTR RS232::GetErrorMessage( void ) {
return m_lpszErrorMessage;
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::open( ) ////
//// ////
////////////////////////////////////////////////////////////////////////////////
int RS232::open( LPCSTR lpszPortNum,
DWORD dwBaudRate,
BYTE byParity,
BYTE byStopBits,
BYTE byByteSize ) {
DCB dcb; //串口設備控制塊 Device Control Block
BOOL bSuccess;
// m_hCom即為函數返回的串口的句柄
m_hCom = CreateFile( lpszPortNum, // pointer to name of the file
GENERIC_READ|GENERIC_WRITE, // 允許讀寫。
0, // 通訊設備必須以獨占方式打開。
NULL, // 無安全屬性,表示該串口不可
// 被子程序繼承。
OPEN_EXISTING, // 通訊設備已存在。
FILE_FLAG_OVERLAPPED, // 使用異步方式 overlapped I/O。
NULL); // 通訊設備不能用模板打開。
if ( m_hCom == INVALID_HANDLE_VALUE ) {
RS232::ErrorToString("RS232::open() CreateFile() failed, invalid handle value");
return FALSE;
}
// 與串口相關的參數非常多,當需要設置串口參數時,通常是先取得串口
// 的參數結構,修改部分參數后再將參數結構寫入
bSuccess = GetCommState(m_hCom, &dcb);
if ( !bSuccess ) {
RS232::close();
RS232::ErrorToString("RS232::open() GetCommState() failed");
return FALSE;
}
dcb.BaudRate = dwBaudRate; // 串口波特率。
dcb.Parity = byParity; // 校驗方式,值0~4分別對應無校驗、奇
// 校驗、偶校驗、校驗、置位、校驗清零。
dcb.fParity = 0; // 為1的話激活奇偶校驗檢查。
dcb.ByteSize = byByteSize; // 一個字節的數據位個數,范圍是5~8。
dcb.StopBits = byStopBits; // 停止位個數,0~2分別對應1位、1.5位、
// 2位停止位。
if ( !bSuccess ) {
RS232::close();
RS232::ErrorToString("RS232::open() SetCommState() failed");
return FALSE;
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::output() ////
//// ////
////////////////////////////////////////////////////////////////////////////////
DWORD RS232::output( LPCVOID pdata, DWORD len ) {
BOOL bSuccess;
DWORD written = 0;
if ( len < 1 )
return 0;
// create event for overlapped I/O
m_ov.hEvent = CreateEvent( NULL, // pointer to security attributes
FALSE, // flag for manual-reset event
FALSE, // flag for initial state
""); // pointer to event-object name
if ( m_ov.hEvent == INVALID_HANDLE_VALUE ) {
RS232::ErrorToString( "RS232::output() CreateEvent() failed" );
return -1;
}
bSuccess = WriteFile( m_hCom, // handle to file to write to
pdata, // pointer to data to write to file
len, // number of bytes to write
&written, // pointer to number of bytes written
&m_ov ); // pointer to structure needed for overlapped I/O
// 如果函數執行成功的話檢查written的值為寫入的字節數,WriteFile函數執行完畢后
// 自行填充的,利用此變量的填充值可以用來檢查該函數是否將所有的數據成功寫入串口
if ( RS232::IsNT() ) {
bSuccess = GetOverlappedResult( m_hCom, &m_ov, &written, TRUE );
if ( !bSuccess ) {
CloseHandle( m_ov.hEvent );
RS232::ErrorToString( "RS232::output() GetOverlappedResult() failed" );
return -1;
}
}
else if ( len != written ) {
CloseHandle( m_ov.hEvent );
RS232::ErrorToString( "RS232::output() WriteFile() failed" );
return -1;
}
CloseHandle( m_ov.hEvent );
return written;
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::input() ////
//// ////
////////////////////////////////////////////////////////////////////////////////
DWORD RS232::input( LPVOID pdest, DWORD len, DWORD dwMaxWait ) {
BOOL bSuccess;
DWORD result = 0,
read = 0, // num read bytes
mask = 0; // a 32-bit variable that receives a mask
// indicating the type of event that occurred
if ( len < 1 )
return(0);
// create event for overlapped I/O
m_ov.hEvent = CreateEvent( NULL, // pointer to security attributes
FALSE, // flag for manual-reset event
FALSE, // flag for initial state
"" ); // pointer to event-object name
if ( m_ov.hEvent == INVALID_HANDLE_VALUE ) {
RS232::ErrorToString( "RS232::input() CreateEvent() failed" );
return -1;
}
// Specify here the event to be enabled
bSuccess = SetCommMask( m_hCom, EV_RXCHAR );
if ( ! bSuccess ) {
CloseHandle(m_ov.hEvent);
RS232::ErrorToString("RS232::input() SetCommMask() failed");
return -1;
}
// WaitForSingleObject
bSuccess = WaitCommEvent(m_hCom, &mask, &m_ov);
if ( !bSuccess ) {
int err = GetLastError();
if ( err == ERROR_IO_PENDING ) {
result = WaitForSingleObject(m_ov.hEvent, dwMaxWait); //wait dwMaxWait
// milli seconds before returning
if ( result == WAIT_FAILED ) {
CloseHandle(m_ov.hEvent);
RS232::ErrorToString( "RS232::input() WaitForSingleObject() failed" );
return -1;
}
}
}
// The specified event occured?
if ( mask & EV_RXCHAR )
{
bSuccess = ReadFile( m_hCom, // handle of file to read
pdest, // address of buffer that receives data
len, // number of bytes to read
&read, // address of number of bytes read
&m_ov); // address of structure for data
if ( RS232::IsNT() ) {
bSuccess = GetOverlappedResult(m_hCom, &m_ov, &read, TRUE);
if ( !bSuccess ) {
CloseHandle( m_ov.hEvent );
RS232::ErrorToString( "RS232::input() GetOverlappedResult() failed" );
return -1;
}
}
else if ( !bSuccess ) {
CloseHandle(m_ov.hEvent);
RS232::ErrorToString( "RS232::input() ReadFile() failed" );
return -1;
}
}
else {
CloseHandle(m_ov.hEvent);
wsprintf( m_lpszErrorMessage, "RS232::input() No EV_RXCHAR occured\n" );
return -1;
}
CloseHandle(m_ov.hEvent);
return read;
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::Close() ////
//// ////
////////////////////////////////////////////////////////////////////////////////
void RS232::close( void ) {
if ( m_hCom > 0 )
CloseHandle( m_hCom );
m_hCom = 0;
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::IsNT ////
//// ////
////////////////////////////////////////////////////////////////////////////////
VOID RS232::ErrorToString( LPCSTR lpszMessage ) {
LPVOID lpMessageBuffer;
DWORD error = GetLastError();
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, // source and processing options
NULL, // pointer to message source
error, // requested message identifie
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // the user default language.
( LPTSTR ) &lpMessageBuffer, // pointer to message buffer
0, // maximum size of message buffer
NULL); // address of array of message inserts
// and copy it in our error string
wsprintf(m_lpszErrorMessage,"%s: (%d) %s\n", lpszMessage, error, lpMessageBuffer);
LocalFree(lpMessageBuffer);
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// RS232::IsNT ////
//// ////
////////////////////////////////////////////////////////////////////////////////
BOOL RS232::IsNT( void ) {
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
GetVersionEx( &osvi );
if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
return TRUE;
else
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////
//// ////
//// The End of RS232 ////
//// ////
////////////////////////////////////////////////////////////////////////////////
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -