| |||||||||||||||||
| |||||||||||||||||
| 文章: | ||
Delphiでのシリアル通信の実装 現代の情報技術の発展とコンピュータネットワークの普及に伴い、コンピュータ通信技術はますます成熟してきましたが、柔軟で便利で信頼性の高い通信方式として、シリアル通信は依然として有効な通信方式であり、産業分野で広く使用されています。コントロール。工業生産の実践において、PC を使用してリアルタイムでプロジェクトを監視するには、通常、PC にデータ収集、データ処理、ユーザー インターフェイス上での制御信号の生成と送信などの機能が必要です。この特殊な環境では、PC をプロセス制御のリアルタイム信号に接続する場合、PC のシリアル ポートを直接操作する必要があります。ボーランドによって発売された Delphi は、ビジュアル オブジェクト指向機能を備えた強力な高級プログラミング言語であり、Windows 環境でのグラフィカル インターフェイスやユーザー プログラムの作成に特に適しています。 WIN95/NTベースのシリアル通信機構 Windows オペレーティング システムのメカニズムでは、アプリケーションがコンピュータ ハードウェアに直接アクセスすることは禁止されていますが、プログラマには一連の標準 API 関数が提供されているため、アプリケーションの準備がより便利になり、関連ハードウェアのデバッグの手間が省けます。 Windows 95/NT では、Windows 3 の元の WM_COMMNOTIFY メッセージ。読み取り/書き込みバッファを操作するだけです。 WIN95/NT で一般的に使用されるいくつかのシリアル通信操作関数は次のとおりです。 CreatFile がシリアル ポートを開きます CloseHandle はシリアルポートを閉じます SetupComm は通信バッファのサイズを設定します ReadFile 読み取りシリアル ポート操作 WriteFile 書き込みシリアル ポート操作 SetCommState は通信パラメータを設定します GetCommState はデフォルトの通信パラメータを取得します ClearCommError はシリアル ポート エラーをクリアし、現在のステータスを取得します。 上記の機能に加えて、重要な記録である DCB (Device Control Block) がよく使用されます。 DCB には定義可能なシリアル ポート パラメータが記録されています。シリアル ポート パラメータを設定する場合は、まず GetCommState 関数を使用してシステムのデフォルト値を DCB 制御ブロックに入力し、次にユーザーが指定したカスタム値を設定する必要があります。変わりたいと思っています。 WIN95/NTでシリアル通信を行うには、基本的な通信操作機能の理解に加えて、マルチスレッドプログラミングを習得する必要があります。スレッドはプロセス内の実行パスであり、オペレーティング システムが CPU 時間を割り当てるために使用する基本的なエンティティです。各プロセスは単一のスレッドで開始され、アプリケーションの実行を完了します。シリアル通信は、マルチスレッド テクノロジを使用して実装する必要があります。その主な処理ロジックは次のように表現できます。プロセスの開始時に、メイン スレッドが必要な初期化作業を実行し、その後、メイン スレッドが監視する通信監視スレッドを確立します。指定されたシリアル ポート イベントが発生すると、WM_COMMNOTIFY メッセージがメイン スレッドに送信され (WIN95 は WM_COMMNOTIFY メッセージを自分で作成する必要があります)、メイン スレッドがそれを処理します。 WM_COMMNOTIFY メッセージが不要な場合、メインスレッドは通信監視スレッドを終了します。 複数のスレッドを同時に実行すると、共有リソースで競合が発生します。競合を回避するには、同期されたマルチスレッドを使用して共有リソースにアクセスする必要があります。 WIN95 には、スレッドの同期を維持するための多くのメソッドが用意されており、イベント オブジェクトの作成を使用してスレッドの同期を維持します。 CraeteEvent() を通じてイベント オブジェクトを作成し、etEvent() または PulseEvent() 関数を使用して同期を通知するようにイベント オブジェクトを設定します。アプリケーションでは、WaitSingleObject() 関数を使用して同期トリガーを待ち、指定されたイベントが他のスレッドによってシグナルを持つように設定されるまで待ってから、プログラムの実行を続行します。 Delphiでの具体的な実装方法 Delphi の強力な機能とマルチスレッドをサポートするオブジェクト指向プログラミング技術により、シリアル通信が非常に簡単かつ便利になります。これは、外部 API 関数を呼び出すことによって実装されます。まず、CreateFile 関数を使用してシリアル ポートを開き、このアプリケーションによるシリアル ポートの所有権を決定し、次に他のアプリケーションがシリアル ポートを操作するのをブロックします。 、GetCommState 関数を使用してデバイス制御ブロック DCB を設定し、SetCommState 関数を呼び出してシリアル ポートのボー レート、データ ビット、パリティ ビット、およびストップ ビットを構成します。次に、シリアル ポート イベントを監視するシリアル ポート監視スレッドを作成します。これに基づいて、対応するシリアル ポートでデータ送信を操作できます。最後に、CloseHandle 関数を使用してシリアル ポートを閉じます。具体的なプログラムは次のとおりです。このプログラムは、読者の参考のために Delphi3.0 でコンパイルされ、Win95 環境でデバッグされました。 プログラム: ユニットコデモ。 インタフェース 用途 ウィンドウ、メッセージ、SysUtils、クラス、グラフィックス、コントロール、フォーム、ダイアログ。 定数 Wm_commNotify=Wm_User+12; タイプ TForm1 = クラス(TForm) PROcedure FormCreate(Sender: TObject); プライベート 手順を共同化する。 プロシージャ MsgcommProcess(Var Message:Tmessage); {プライベート宣言} 公共 {公的宣言} 終わり; //スレッド宣言 TComm=クラス(Tスレッド) 保護された プロシージャ 実行;上書き; 終わり; 変数 フォーム1: TForm1; hcom,Post_Event:タンドル; lpol:重なり合った; 実装 {$R *.DFM} Procedure TComm.Execute //スレッド実行処理; 変数 dwEvtMask:DWord; 待機:ブール値; 始める fillchar(lpol,sizeof(toverlapped),0); True の間は開始します dwEvtMask:=0; Wait:=WaitCommEvent(hcom,dwevtmask,lpol); //シリアルポートイベントを待ちます。 待ってから開始する場合 waitforsingleobject(post_event,infinite); //同期イベントが設定されるまで待ちます。 resetevent(post_event); //同期イベントのリセット; PostMessage(Form1.Handle,WM_COMMNOTIFY,0,0);//メッセージを送信します。 終わり; 終わり; 終わり; プロシージャ Tform1.comminitialize //シリアルポートの初期化; 変数 lpdcb:Tdcb; 始める hcom:=createfile('com2',generic_read または generic_write,0,nil,open_existing, file_attribute_normal または file_flag_overlapped,0);//シリアル ポートを開きます hcom=invalid_handle_value の場合、 それ以外 setupcomm(hcom,4096,4096); //入力バッファと出力バッファを 4096 バイトに設定します getcommstate(hcom,lpdcb); //シリアルポートの現在のデフォルト設定を取得します。 lpdcb.ボーレート:=2400; lpdcb.StopBits:=1; lpdcb.バイトサイズ:=8; lpdcb.Parity:=EvenParity; //偶数パリティ Setcommstate(hcom,lpdcb); setcommMask(hcom,ev_rxchar); //シリアルポートイベントを受信文字として指定します。 終わり; プロシージャ TForm1.MsgcommProcess(Var Message:Tmessage); 変数 クリア:ブール値; コム:Tcomstat; cbNum、ReadNumber、lpErrors:整数; Read_Buffer: 文字の配列[1..100]; 始める Clear:=Clearcommerror(hcom,lpErrors,@Coms); クリアしたら開始 cbNum:=Coms.cbInQue; ReadFile(hCom,Read_Buffer,cbNum,ReadNumber,lpol); //受信したデータを処理する SetEvent(Post_Event); //同期イベントの設定 終わり; 終わり; プロシージャ TForm1.FormCreate(送信者: TObject); 始める 共同体化する。 post_event:=CreateEvent(nil,true,true,nil); //同期イベントを作成します。 Tcomm.Create(False); //シリアルポート監視スレッドを作成します。 終わり; 終わり。 著者メンバー名:ruan_bangqiu | ||