HSG |
|
Ein Transceiver ist gleichzeitig Sender und Empfänger.
Um den miniSender und den miniEmpfänger in einem Programm zu vereinen, müssen mindestens zwei Threads parallel laufen. Es soll nun der Empfänger als Thread implementiert werden.
Es zeigt sich, dass das Programm (transceiver0.zip) noch nicht wunschgemäß arbeitet. Eigentlich klar, wenn man dem main-Thread keine Zeit für die VCL-Komponenten einräumt. Daher muss auch der Sender als Thread implementiert werden. Zumindest im vorliegenden Testfall bekam man erst befriedigende Ergebnisse, wenn die Zeit-Granularität mit timeBeginPeriod(1); auf 1ms gestellt wurde. Am Ende des Programms (transceiver1.zip) sollte diese Einstellung mit timeEndPeriod(1); zurückgenommen werden. Die beiden Prozeduren benötigen die Unit mmsystem.
unit uTransceiver1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls, mTNetzHW, mmsystem; type TEmpf = class(TThread) private baud : integer; b : byte; NetzHW : TNetzHW; public procedure execute; override; procedure SetBaud(pBaud : integer); procedure SetNetzHW(pNetzHW : TNetzHW); procedure update; end; TSend = class(TThread) private baud : integer; sendetext : String; NetzHW : TNetzHW; public procedure execute; override; procedure SetBaud(pBaud : integer); procedure SetNetzHW(pNetzHW : TNetzHW); procedure SetSendeText(pText : string); end; TForm1 = class(TForm) eBaud: TEdit; lBaud2: TLabel; bSende: TButton; mSend: TMemo; mEmpf: TMemo; eEmpf: TButton; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure eEmpfClick(Sender: TObject); procedure bSendeClick(Sender: TObject); private NetzHW : TNetzHW; Empf : TEmpf; Send : TSend; public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} procedure TEmpf.execute; var bitzeit : integer; i,j : byte; begin bitzeit := round(1000/baud); while not Terminated do begin // warten auf StartBit while Not NetzHW.GetEin do sleep(0); // 1,5 Bitlängen warten sleep(bitzeit+bitzeit div 2); // Datenbits einlesen b := 0; for i := 7 downto 0 do begin b := b shl 1; if NetzHw.GetEin then Inc(b); sleep(bitzeit); end; synchronize(update); end; end; procedure TEmpf.SetBaud(pBaud : integer); begin baud := pBaud; end; procedure TEmpf.SetNetzHW(pNetzHW : TNetzHW); begin NetzHW := pNetzHW; end; procedure TEmpf.update; begin // Zeichen anhängen Form1.mEmpf.Text := Form1.mEmpf.Text+chr(b); // Bildaufbau erzwingen Form1.Refresh; end; procedure TSend.execute; var bitzeit : integer; b,i,j : byte; begin bitzeit := round(1000/baud); for j := 1 to Length(SendeText) do begin b := ord(SendeText[j]); // StartBit NetzHW.SetAus(true); sleep(bitzeit); // Datenbits for i := 7 downto 0 do begin NetzHW.SetAus(odd(b shr i)); sleep(bitzeit); end; // StoppBit NetzHW.SetAus(false); sleep(bitzeit); end; end; procedure TSend.SetBaud(pBaud : integer); begin baud := pBaud; end; procedure TSend.SetNetzHW(pNetzHW : TNetzHW); begin NetzHW := pNetzHW; end; procedure TSend.SetSendeText(pText : string); begin SendeText := pText; end; procedure TForm1.FormCreate(Sender: TObject); begin timeBeginPeriod(1); NetzHW := TNetzHW.Create; Empf := TEmpf.Create(true); // suspended starten netzHW.Start(1); end; procedure TForm1.FormDestroy(Sender: TObject); begin Empf.Terminate; NetzHW.Free; timeEndPeriod(1); end; procedure TForm1.eEmpfClick(Sender: TObject); begin Empf.SetBaud(StrToInt(eBaud.text)); Empf.SetNetzHW(NetzHW); Empf.FreeOnTerminate := true; Empf.Resume; end; procedure TForm1.bSendeClick(Sender: TObject); begin Send := TSend.Create(true); Send.SetBaud(StrToInt(eBaud.text)); Send.SetSendeText(mSend.Text); Send.SetNetzHW(NetzHW); Send.FreeOnTerminate := true; Send.Resume; end; end.
Man kann Windows zu einem entscheidend - für unsere Zwecke - besseren Zeitverhalten veranlassen, wenn man mit dem Taskmanager (Strg-Alt-Entf) dem Prozess mit der rechten Maustaste eine höhere Priorität zuweist. Die Priorität 'Echtzeit' erreicht man nur mit Administratorrechten.