Visual C++によるシリアル通信プログラミングの詳細分析

5355 ワード

Visual C++を利用してwindows環境の下で非同期シリアル通信プログラムを設計して異なる方法を使うことができます.
1つの方法はwindowsシステムが提供するシリアルポートAPI関数を使用することができる.もう1つの方法は、Microsoft社が提供するActiveXコントロールMSCOMMを直接使用することができる.OCX.MSCOMMを利用する.OCXコントロールはシリアルポートプログラムの設計が比較的簡単で、そのコントロールの属性、イベント、方法を設定し、操作すれば、簡単なシリアル通信機能を完成することができる.Windowsシステムが提供するシリアルポートAPI関数を直接使用するのは比較的柔軟です.実験では,自分の状況のいずれかに応じてプログラミングを行うことができる.
以下ではwindowsシステムが提供するシリアルポートAPI関数をどのようにプログラミングするかについて簡単に紹介します.windowsシステムでは、シリアルポートや他の通信装置がファイルとして処理されています.シリアルポートのオン、オフ、送信、受信に使用される関数は、操作ファイルの関数と同じです.全体的に、Visual C++による非同期シリアル通信プログラムの設計は、通常、シリアルポートオープンフェーズ、シリアルポート状態値読み出しおよび属性設定フェーズ、シリアルデータの送信および受信フェーズ、シリアルポートクローズフェーズの4つの大きなフェーズに分けることができる.
(1)シリアルポートを開くシリアルポートに対してすべての操作を行う前に、まずそれを開く.シリアルポートの開くにはCreateFile関数を使用し、CreateFile関数はハンドルを返し、その後のシリアルポートに関連する様々な操作で使用する.ファイル操作と同様にCreateFileを使用してシリアルポートを開く場合、シリアルポートを「読み取りアクセス」として指定することもできる、書き込みアクセス、または読み取り/書き込みアクセス.
 
  
HANDLE CreateFile(
LPCTSTR  lpFileName
DWORD   dwDesiredAccess
DWORD   dwSharedMode
LPSECURITY_ATTRIBUTES  lpSecurityAttributes
DWORD   dwCreationDisposition
DWORD   dwFlagsAndAttributes
HANDLE   hTemplateFile
);

呼び出しが成功すると、CreateFileは、後でシリアルポートに関連する各呼び出し関数で使用されるファイルを開いたハンドルを返します.呼び出しに失敗した場合、CreateFileはINVALID_を返します.HANDLE_VALUE.
(2)シリアルポートの状態読み出しと属性設定シリアルポートを開くと、そのシリアルポートの属性を設定することができる.シリアルポートの属性は非常に複雑であるため、通常、そのシリアルポートの現在の状態値を読み出し、それに基づいて修正する方法を採用する.
シリアルポートの現在の状態の取得
 
  
BOOL  GetCommState(
  HANDLE hFile
  LPDCB  lpDCB
);

GetCommState関数の最初のパラメータhFileは、CreateFile関数によって開いているシリアルポートを指すハンドルを返します.2番目のパラメータは、デバイス制御ブロックDCBを指す.DCBは非常に重要なデータ構造であり、ほとんどのシリアルポート属性と状態が構造のメンバー変数に格納されている.
シリアルポートの設定windowsシステムは、SetCommState関数を使用してシリアルポートの現在のパラメータ構成を変更します.SetCommState関数は次のように宣言されます.
 
  
BOOL  SetCommState(
  HANDLE hFile
  LPDCB  lpDCB
);

GetCommState関数の最初のパラメータhFileは、CreateFile関数によって開いているシリアルポートを指すハンドルを返します.2番目のパラメータは、デバイス制御ブロックDCBを指す.関数呼び出しに成功した場合、戻り値は0ではありません.関数呼び出しに失敗すると、戻り値は0になります.アプリケーションがシリアルポートの構成値の一部を変更する必要がある場合、GetCommState関数で現在のDCB構造を取得し、パラメータを変更してから、SetCommState関数を呼び出して変更したDCBを設定してシリアルポートを構成できます.
シリアルポートに受信バッファと送信バッファを割り当てる
シリアルポートが開いている場合、シリアルポートに送信バッファと受信バッファを割り当てることができます.シリアルポート送信バッファと受信バッファの構成は、関数SetupCommによって実現することができる.SetupCommを呼び出さないと、シリアルポートにデフォルトの送信バッファと受信バッファが割り当てられます.ただし、バッファのサイズが実際のニーズと一致するように、この関数を呼び出して設定することが望ましい.SetupComm関数のプロトタイプは次のとおりです.
 
  
BOOL  SetupComm(
 HANDLE hFile
 DWORD dwInQueue
 DWORD dwOutQueue
);

ここで、hFileはCreateFile関数によって開かれたシリアルポートを指すハンドルを返します.パラメータdwInQueueとdwOutQueueは、アプリケーションが推奨する受信バッファと送信バッファのサイズをそれぞれ指定します.
シリアルポートのすべての送信および受信データ操作を行う前に、PurgeComm関数を使用してシリアルポート送信バッファおよび受信バッファのデータをクリアすることが望ましい.PurgeComm関数のプロトタイプは次のとおりです.
 
  
BOOL  PurgeComm(
 HANDLE  hFile
 DWORD   dwFlages
);

パラメータhFileはCreateFile関数によって開かれたシリアルポートを指すハンドルを返し、パラメータdwFlagsは実行する動作を示す.dwFlagsがPURGE_の場合TXCLEARは、システムに送信バッファを空にすることを通知する.dwFlagsがPURGE_の場合RXCLEARは、システムに受信バッファを空にすることを通知する.送信バッファと受信バッファをすべてクリアする必要がある場合は、dwFlagsをPURGE_に設定できます.TXCLEAR|PURGE_RXCLEAR.PurgeComm関数の呼び出しが成功した場合、戻り値は0ではありません.関数呼び出しに失敗すると、戻り値は0になります.
(3)シリアルデータの送受信は通常のファイル操作と同様であり,シリアルポートを操作する際には通常,ReadFile関数を用いてシリアルポートから受け取ったデータを読み出し,WriteFileを用いてシリアルポートのように送信する必要があるデータを書き込む.
シリアルデータの受信
ReadFile関数を使用すると、シリアルポートで受信したデータを読み込むことができます.ReadFile関数のプロトタイプは次のとおりです.
 
  
BOOL  ReadFile(
HANDLE  hFile
LPVIOD   lpBuffer
DWORD   nNumberOfBytesToRead
LPDWORD   lpNumberOfBytesRead
LPOVERLAPPED  lpOverlapped
);

ここで、パラメータhFileは、すでに開いているシリアルポートハンドルを指す.lpBufferは、読み出しデータバッファを指す.nNumberOfBytesToReadシリアルデバイスから読み出すバイト数を指定します.lpNumberOfBytesReadは、実際にシリアルポートから読み出したバイト数を示す.lpOverlappedは、同期イベントを含むOVERLPPED構造変数を指す.
通常、呼び出しが成功した場合、ReadFileは0以外の値を返します.それ以外の場合、戻り値は0です.ただし、受信操作がバックグラウンドで行われるシリアルポートでは、戻り値が0の場合、関数呼び出しに失敗したとは限らない.GetLastError関数を呼び出して、さらなる情報を取得できます.GetLastErrorの戻り値がERROR_の場合IO_PENDINGは、実際の意味でのエラーではなく、読み出しシリアルポートの動作がバックグラウンド待機状態にあることを示します.
シリアルデータの送信はWriteFile関数でシリアルポートにデータを書き込むことができます.WriteFile関数のプロトタイプは次のとおりです.
 
  
BOOL  WriteFile(
HANDLE  hFile
LPVIOD   lpBuffer
DWORD   nNumberOfBytesToWrite
LPDWORD   lpNumberOfBytesWritten
LPOVERLAPPED  lpOverlapped
);

ここで、パラメータhFileは、すでに開いているシリアルポートハンドルを指す.lpBufferは送信データバッファを指す.nNumberOfBytesToReadシリアルデバイスから送信するバイト数を指定します.lpNumberOfBytesReadは、実際にシリアルポートから送信されるバイト数を示す.lpOverlappedは、同期イベントを含むOVERLPPED構造変数を指す.
通常、呼び出しが成功した場合、WriteFileは0以外の値を返します.それ以外の場合、戻り値は0です.ただし、送信操作がバックグラウンドで行われるシリアルポートでは、戻り値が0の場合、関数呼び出しに失敗したとは限らない.GetLastError関数を呼び出して、さらなる情報を取得できます.GetLastErrorの戻り値がERROR_の場合IO_PENDINGは、実際の意味でのエラーではなく、書き込みシリアルポートの動作がバックグラウンド待機状態にあることを示します.
(4)シリアルポートを閉じるシリアルポートは、シリアルポートが使用済みになると通常閉じられます.閉じるのを忘れた場合、シリアルポートは常に開いているため、他のアプリケーションでは開いたり使用したりできません.
シリアルポートを閉じるには、関数CloseHandleを使用します.関数のプロトタイプは次のとおりです.
 
  
BOOL  CloseHandle(
HANDLE  hObject
);

CloseHandle関数は非常に簡単で、hObjectはシリアルポートを開くハンドルです.関数の呼び出しに成功した場合、戻り値は0ではありません.それ以外の場合、戻り値は0です.