C++実現上位機4:シリアルポート制御類の派生類CSerialPort実現1
C++実装上位機3:シリアルポート制御クラスの抽象ベースクラス設計を実現し,前述した抽象ベースクラスの設計について説明したが,ここでは詳しく述べない.
CSerialPortクラスは前文のCComminicationToolクラスを継承し、接続を開く、接続を切る、データを送信する、データを受信する4つの方法を継承している.本稿ではまずCSerialPortのヘッダファイル定義を見て、その中の主要メンバー関数を次々と説明する.
CSerialPortのヘッダファイル:
接続を開く
PrintMessageはすでにC++実装上位機3:実装シリアルポート制御クラスの抽象ベースクラス設計で定義されており,詳細は後述しない.
関数機能:文字列をワイド文字(unicode)の文字列にマッピングします.この関数によってマッピングされる文字列は、マルチバイト文字グループである必要はありません.
関数のプロトタイプ:
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cchMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
関数が正常に動作し、cchWideCharがゼロでない場合、戻り値はlpWideCharStrが指すバッファに書き込まれた幅の広い文字数です.関数が正常に実行され、cchWideCharがゼロの場合、戻り値は、変換される文字列を受信するバッファに必要な幅の広い文字数のサイズです.
Ansi 2 WChar()ANSI符号化文字列をワイド文字(unicode)文字列に変換:
SetMyPort()
接続を開くOpenSerialPort()
ReadFileとWriteFileでシリアルポートを読み書きする場合は、タイムアウトの問題を考慮する必要があります.指定された時間内に指定された数の文字が読み書きされていない場合、ReadFileまたはWriteFileの操作は終了します.現在のタイムアウト設定を問い合わせるにはGetCommTimeouts関数を呼び出す必要があります.この関数にはCOMMTIMEOUTS構造が埋め込まれます.SetCommTimeoutsを呼び出すと、あるCOMMTIMEOUTS構造のコンテンツでタイムアウトを設定できます.タイムアウトには、間隔タイムアウトと合計タイムアウトの2つがあります.間隔タイムアウトとは、受信時の2文字間の最大遅延であり、合計タイムアウトとは、読み書き操作にかかる合計最大時間である.書き込み操作は合計タイムアウトのみをサポートし、読み取り操作の両方のタイムアウトはサポートします.
aa
CSerialPortクラスは前文のCComminicationToolクラスを継承し、接続を開く、接続を切る、データを送信する、データを受信する4つの方法を継承している.本稿ではまずCSerialPortのヘッダファイル定義を見て、その中の主要メンバー関数を次々と説明する.
CSerialPortのヘッダファイル:
#pragma once
#include "CComminicationTool.h"
#include "../stdafx.h"
class CSerialPort :public CComminicationTool{
// Construction
public:
CSerialPort();//
~CSerialPort();
// Operations:
public:
#ifdef __AFX_H__
void SetPort(CString COM = L"COM3");//
#else
void SetMyPort(std::wstring COM = L"COM3");//
#endif
int SetDCB(DWORD BaudRate = 57600, BYTE ByteSize = 8, BYTE Parity = NOPARITY, BYTE StopBits = ONESTOPBIT);//
int SetCache(DWORD InBuff = 1024, DWORD OutBuff = 1024);//
int SetTimeout(COMMTIMEOUTS timeOuts);//
std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen);
char m_resver_str[1024];//
private:
void CloseHcom();
bool OpenSerialPort();//
// Attributes:
private:
#ifdef __AFX_H__
CString m_strCOM;// COM
#else
std::wstring m_strCOM;// COM
#endif
COMMTIMEOUTS m_TimeOuts;//
DCB m_wdcb;//
HANDLE m_hCom;//
// Implementation
public:
bool Connect();//
bool Connect(std::string com);//
bool Disconnect();//
DWORD SendData(void* data, DWORD size);// ( , ( ))
char* ReadData(DWORD& wCount);// ( ( ))
bool IsConnect();
};
接続を開く
bool CSerialPort::Connect(){
if (m_hCom == NULL){
return OpenSerialPort();
}
else{
PrintMessage(" ");
}
return false;
}
bool CSerialPort::Connect(std::string com){
if (m_hCom == NULL){
SetMyPort(Ansi2WChar(com.c_str(), com.size()));
return OpenSerialPort();
}
else{
PrintMessage(" ");
}
return false;
}
PrintMessageはすでにC++実装上位機3:実装シリアルポート制御クラスの抽象ベースクラス設計で定義されており,詳細は後述しない.
関数機能:文字列をワイド文字(unicode)の文字列にマッピングします.この関数によってマッピングされる文字列は、マルチバイト文字グループである必要はありません.
関数のプロトタイプ:
int MultiByteToWideChar(
UINT CodePage,
DWORD dwFlags,
LPCSTR lpMultiByteStr,
int cchMultiByte,
LPWSTR lpWideCharStr,
int cchWideChar
);
関数が正常に動作し、cchWideCharがゼロでない場合、戻り値はlpWideCharStrが指すバッファに書き込まれた幅の広い文字数です.関数が正常に実行され、cchWideCharがゼロの場合、戻り値は、変換される文字列を受信するバッファに必要な幅の広い文字数のサイズです.
Ansi 2 WChar()ANSI符号化文字列をワイド文字(unicode)文字列に変換:
std::wstring CSerialPort::Ansi2WChar(LPCSTR pszSrc, int nLen)
{
int nSize = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, 0, 0);
if (nSize <= 0) return NULL;
WCHAR *pwszDst = new WCHAR[nSize + 1];
if (NULL == pwszDst) return NULL;
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pszSrc, nLen, pwszDst, nSize);
pwszDst[nSize] = 0;
if (pwszDst[0] == 0xFEFF) // skip Oxfeff
for (int i = 0; i < nSize; i++)
pwszDst[i] = pwszDst[i + 1];
std::wstring wcharString(pwszDst);
delete pwszDst;
return wcharString;
}
SetMyPort()
#ifdef __AFX_H__
void CSerialPort::SetPort(CString COM){
m_strCOM = COM;
}
#else
void CSerialPort::SetMyPort(std::wstring COM){
m_strCOM = COM;
}
#endif
接続を開くOpenSerialPort()
ReadFileとWriteFileでシリアルポートを読み書きする場合は、タイムアウトの問題を考慮する必要があります.指定された時間内に指定された数の文字が読み書きされていない場合、ReadFileまたはWriteFileの操作は終了します.現在のタイムアウト設定を問い合わせるにはGetCommTimeouts関数を呼び出す必要があります.この関数にはCOMMTIMEOUTS構造が埋め込まれます.SetCommTimeoutsを呼び出すと、あるCOMMTIMEOUTS構造のコンテンツでタイムアウトを設定できます.タイムアウトには、間隔タイムアウトと合計タイムアウトの2つがあります.間隔タイムアウトとは、受信時の2文字間の最大遅延であり、合計タイムアウトとは、読み書き操作にかかる合計最大時間である.書き込み操作は合計タイムアウトのみをサポートし、読み取り操作の両方のタイムアウトはサポートします.
bool CSerialPort::OpenSerialPort(){
m_hCom = CreateFile(m_strCOM.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (m_hCom == INVALID_HANDLE_VALUE)
{
PrintMessage(" COM ");
return false;
}
else
{
memset(&m_TimeOuts, 0, sizeof(m_TimeOuts));
m_TimeOuts.ReadIntervalTimeout = 1;
// ReadIntervalTimeout 0, 。
m_TimeOuts.ReadTotalTimeoutMultiplier = 1;
m_TimeOuts.ReadTotalTimeoutConstant = 10;
/* MAXDWORD,
ReadTotalTimeoutConstant ReadTotalTimeoutMultiplier 0,
, 。*/
//
m_TimeOuts.WriteTotalTimeoutMultiplier = 50;
m_TimeOuts.WriteTotalTimeoutConstant = 2000;
/* WriteTotalTimeoutMultiplier WriteTotalTimeoutConstant 0, 。
: , , 。*/
if (!SetCommTimeouts(m_hCom, &m_TimeOuts)){//
PrintMessage(" !(set timeout failed)");
CloseHandle(m_hCom);
return false;
}
if (!SetupComm(m_hCom, 1024, 1024)){ // 1024
PrintMessage(" !(set cache failed)");
CloseHandle(m_hCom);
return false;
}
if (!GetCommState(m_hCom, &m_wdcb)){
PrintMessage(" !(get ComState failed)");
CloseHandle(m_hCom);
return false;
}
m_wdcb.BaudRate = 57600;// :57600, :
m_wdcb.ByteSize = 8; // 8
m_wdcb.Parity = NOPARITY; //
m_wdcb.StopBits = ONESTOPBIT;//1
if (!SetCommState(m_hCom, &m_wdcb)){
PrintMessage(" !(set ComState failed)");
CloseHandle(m_hCom);
return false;
}
PurgeComm(m_hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_RXABORT | PURGE_RXCLEAR);
}
return true;
}
aa