プログラムの流れ
DCB構造体とSetComSmtate()関数でシリアルポートの設定をする
なお、わたし自身、シリアルポートの規格に詳しくないので、各種設定の意味をすべて把握しきれていません。加えて、MSDN Liblaryの英文をわたしが訳したということもあって、内容の正確さを保証できません。訂正などはメールでお願いします。
DTR_CONTROL_DISABLEDTR
=フローコントロール有効
RTS_CONTROL_ENABLE
=RTSフローコントロール有効
EVENPARITY
=偶数パリティ
ONESTOPBIT
=1ストップビット
COMMTIMEOUTS構造体とSetComTimeouts()関数でシリアルポートのタイムアウトを設定する
(受信タイムアウト) = ReadTotalTimeoutMultiplier * (受信バイト数) + ReadTotalTimeoutConstant
プログラムの流れを初めに紹介します。
シリアルポートの制御は、基本的にファイルの入出力と同じです。したがって、CreateFile()関数でシリアルポートを開き、戻り値のファイルハンドルをReadFile()関数やWriteFile()関数の引数として、データの送受信をします。通信が終わったらCloseHandle()関数でシリアルポートを閉じます。ただし、ファイルの入出力と違うところは、シリアルポートの設定について記述することです。
先述したようにCrateFile()関数を使います。引数は以下の通りです。シリアルポートの制御場合、指定する引数が決まりきっているので簡単です。
HANDLE CreateFile(
LPCSTR lpszComPort, /* シリアルポート名前 */
DWORD dwAccessMode, /* アクセスモード */
DWORD dwShareMode, /* 共有モード */
LPSECURITY_ATTRIBUTES lpSecurityAttributes, /* セキュリティに関する情報 */
DWORD dwCreationDistribution, /* オープン時の動作 */
DWORD dwFlagsAndAttributes, /* 属性 */
HANDLE hTemplateFile /* テンプレートのハンドル */
);
シリアルポートを閉じる場合は簡単です。CreateFile()関数の戻り値であるファイルハンドルをCloseHandle()関数を使って解放するだけです。シリアルポートを使い終わったら必ずファイルハンドルは解放しましょう。関数のプロトタイプを書いておきます。
BOOL CloseHandle(HANDLE hHandle);
データの送信はWriteFile()関数を使います。プロトタイプは以下の通りです。
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
データの送信はReadFile()関数を使います。プロトタイプは以下の通りです。
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
ClearCommError()関数でポートのエラーをクリアして、ポートの状態を取得することができます。この関数を使って、受信バッファのバイト数を取得して、ReadFile()関数のnNumberOfBytesToReadに指定します。この関数のプロトタイプは以下の通りです。
BOOL ClearCommError(
HANDLE hFile,
LPDWORD lpErrors,
LPCOMSTAT lpStat
);
typedef _COMSTAT {
DWORD fCtsHold;
DWORD fDsrHold;
DWORD fRlsdHold;
DWORD fXoffHold;
DWORD fXoffSend;
DWORD fEof;
DWORD fTxim;
DWORD fReserved;
DWORD cbInQue;
DWORD cbOutQue;
} COMSTAT;
CreateFile()関数ではシリアルポートの設定らしい設定をしませんでした。ファイル処理と共通する設定だけでしたが、シリアルポートでは通信速度やパリティ、フロー制御などの設定が必要です。DCB構造体とSetComSmtate()関数を使ってそれらの設定をします。まず、以下にDCB構造体のメンバを示します。
typedef struct _DCB {
DWORD DCBlength; /* DCB構造体のサイズ */
DWORD BaudRate; /* 通信速度 */
DWORD fBinary; /* バイナリモードの設定 */
DWORD fParity; /* パリティの設定 */
DWORD fOutxCtsFlow; /* CTS出力フローコントロールの設定 */
DWORD fOutxDsrFlow; /* DSR出力フローコントロールの設定 */
DWORD fDtrControl; /* DTRフローコントロールの種類 */
DWORD fDsrSensitivity; /* DSR信号処理の設定 */
DWORD fTXContinueOnXoff; /* XOFF送信後の処理の設定 */
DWORD fOutX; /* XON/XOFF出力フローコントロールの設定 */
DWORD fInX; /* XON/XOFF入力フローコントロールの設定 */
DWORD fErrorChar; /* パリティエラーの代替文字の設定 */
DWORD fNull; /* NULLバイトの破棄 */
DWORD fRtsControl; /* RTSフローコントロールの設定 */
DWORD fAbortOnError1; /* エラー時の動作 */
DWORD fDummy2; /* 予約 */
WORD wReserved; /* 予約 */
WORD XonLim; /* XON文字送信の最小値バイト数 */
WORD XoffLim; /* XOFF文字送信の最小値バイト数 */
BYTE ByteSize; /* 1バイトのサイズ */
BYTE Parity; /* パリティの種類 */
BYTE StopBits; /* ストップビットの種類 */
char XonChar; /* XON文字 */
char XoffChar; /* XOFF文字 */
char ErrorChar; /* パリティエラーの代替文字 */
char EofChar; /* EOF文字 */
char EvtChar; /* イベント通知文字 */
WORD wReserved1; /* 予約 */
} DCB;
つぎに、DCB構造体に値を代入した後に、SetCommState()関数でDCB構造体の情報を(OSに)登録します。SetCommState()関数のプロトタイプを示します。
DTR_CONTROL_ENABLEDTR
=フローコントロール無効
DTR_CONTROL_HANDSHAKEDTR
=ハンドシェイク有効
RTS_CONTROL_DISABLE
=RTSフローコントロール無効
RTS_CONTROL_HANDSHAKE
=RTSハンドシェイク有効
RTS_CONTROL_TOGGLE
=RTSトグル有効
MARKPARITY
=マークパリティ
NOPARITY
=パリティなし
ODDPARITY
=奇数パリティ
SPACEPARITY
=空白パリティ
ONE5STOPBITS
=1.5ストップビット
TWOSTOPBITS
=2ストップビット
BOOL SetCommState(
Handle hHandle,
LPDCB lpDCB
);
タイムアウトは絶対指定するものではありませんが、プログラムの処理上必要になる場合もあります。
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutConstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutConstant;
};
送受信タイムアウトで各メンバは次式の計算要素になります(ReadIntervalTimeout以外)。次式を使って、処理に必要なタイムアウト時間を決定してください。
(送信タイムアウト) = WriteTotalTimeoutMultiplier * (送信バイト数) + WriteTotalTimeoutConstant
前のページに戻る