Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Funktion liefert nicht immer das was es soll


TheD - Mo 31.03.03 21:05
Titel: Funktion liefert nicht immer das was es soll
Hallöchen,




Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function TSW.IstGeraetAn: Boolean;
begin
//  Result := False;
  GetAdressValue(12039, Value);
  if ((Value and 32) <> 0) then
    Result := True
  else
    Result := False;
end;


folgendes Problem, nach Programmstart, klicke ich auf einen Button, wodurch ich diese Funktion aufrufe. Das ganze geht im prinzip.
Ich überprfüe dabei ob ein Gerät an der seriellen Schnittstelle angeschlossen ist. Dabei schicke ich ein Byte und empfange eins. Dann schau ich ob in dem empfangenem Byte, ein Bit 1 ist, wenn ja, dann soll halt eben True, wenn nicht dann False geliefert werden.
Das Problem, wenn ich beim ersten Anklicken des Buttons klicke und das Gerät ist nicht dran, dann wird mir False geliefert. Und zwar auch wenn ich dann das Gerät anshcliesse und dann wieder den Button drücke! Daher kann ich auch nicht mit dem restlichen Code weiter machen.
Wenn aber beim ersten klick das Gerät da ist, dann funktionierts.
Hoffe dass das verständlcih war, ist ein bisschen blöd zum erklären. ;)

Achja, das else habe ich reingemacht, nachdem ich die eine Zeile auskommentiert habe. War nur ein Versuch.


AndyB - Mo 31.03.03 23:01

Zitat:
if ((Value and 32) <> 0) then

Damit überprüfst du, ob Bit 5 (2^5=32) gesetzt ist. Wenn du prüfen willst ob überhaupt irgendein Bit gesetzt ist, dann geht das ganz einfach mit

Quelltext
1:
if Value <> 0 then                    


TheD - Mo 31.03.03 23:08

Das ist schon so beabsichtigt! ;)
Es muss das 5te Bit an sein. Wenn das Gerät ein ist und bereit ist, dann setzt es das 5te Bit auf 1, das möchte ich eben überprüfen.


Brueggendiek - Di 01.04.03 00:42
Titel: Re: Funktion liefert nicht immer das was es soll
Hallo!

Zunächst einmal: Wo und wie ist Value definiert, wer verändert das sonst noch?

Ansonsten kann ich keinen Fehler sehen. Allerdings vermisse ich die Ausgabe auf der Schnittstelle, mit der das Gerät zur Antwort aufgefordert wird. Fehlt das etwa beim 2. Aufruf?
Oder sollte GetAdressValue den Wert nur liefern, aber nicht im Schnittstellenregister löschen?

Übrigens kann man das noch besser so schreiben:

Quelltext
1:
2:
3:
4:
5:
function TSW.IstGeraetAn: Boolean;
begin
  GetAdressValue(12039, Value);
  Result := (Value and $20) <> 0;
end;

Bei bitweiser Auswertung von Werten und bei Adressen bevorzuge ich die Sedezimalform, weil $20 leichter in Bits umzusetzen ist als 32! Bevor jetzt Beschwerden kommen, dem Compiler sei das egal: ich meine besser lesbar für den Programmierer oder den, der den Code später warten soll! Besonders bei mehreren Bits ist das wichtig: $26 ist klarer als 38!

Eine Deklaration von

Quelltext
1:
const GeraeteAdresse = $2F07;                    

und die Verwendung von GeraeteAdresse bei den Aufrufen erhöht außerdem die Lesbarkeit und erleichtert Änderungen (suche mal im ganzen Projekt die Adresse und ändere sie, ohne einen zufällig gleichen Wert in anderem Zusammenhang zu verändern!)

Gruß

Dietmar Brüggendiek


TheD - Di 01.04.03 07:44

Hallo,

Value ist eine globale Byte-Variable. Die benutze ich in allen möglichen Funktionen und Prozduren.

Hier mal der Code mit dem auslesen von der Schnittstelle.

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
function TSW.GetAdressValue(bAdresse: Byte; var Value: Byte): Boolean;
var
  sByte: String;
begin
  Result := False;
  case Format of
    0: begin //
       end;
    1: begin //
       end;
    2: begin //
         if bAdresse > 111 then
         begin
           Result := False;
         end
         else
         begin
           ComPort1.WriteStr(Chr(bAdresse));
           ComPort1.ReadStr(sByte, 2);
           if Length(sByte) < 2 then //Falls weniger als zwei Bytes ankommen
           begin
             Result := False;
           end
           else if Byte(sByte[1]) <> bAdresse then //Falls das erste Byte <> AdressByte
           begin
             Result := False;
           end
           else
           begin
             Value := Byte(sByte[2]); //Wert des zweiten Bytes weiter geben
             Result := True;
           end;
         end; //if
       end; //begin
  end; //case
end;

Format ist wieder ne globale Variable vom Typ Integer.

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
function TSW.IstZentraleAn: Boolean;
begin
//  Result := False;
  GetAdressValue(109, Value);
  if ((Value and 32) <> 0) then
    Result := True
  else
    Result := False;
end;


Das sind funktionen die in einer allgemeinen Unit sind.
Im Hauptprogramm sieht es dann so aus:


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
procedure TForm1.BitBtnLesenClick(Sender: TObject);
//Daten Lesen
var
//  bUnter, bOber: Word;
  s: String;
begin
  ButtonsOff;
  LabelGeraetVersion.Caption := '';
  LabelHersteller.Caption := '';
  LabelModul.Caption := '';
  LabelVersion.Caption := '';
  if SW.IstZentraleAn then //Prüfen ob Gerät eingeschaltet ist
  begin
    if SW.IstModulAn then //Prüfen ob Modul im Programmiermodus
    begin
      if SW.GetHerstellercode = 1 then //Prüfen ob Herstellercode richtig ist
      begin
        if SW.GetModulCode = 3 then //Prüfen ob richtiges Modul im Programmiermodus ist
        begin
          ;
        end
        else
        begin
          ShowMessage('Es ist kein ' + IntToStr(SW.GetModulCode));
        end;
      end
      else
      begin
        ShowMessage('Hersteller');
      end;
    end
    else
    begin
      ShowMessage('Es ist kein Modul im Programmiermodus!');
    end;
  end
  else
  begin
    ShowMessage('Gerät ist nicht eingeschaltet,' + #13#10
      + 'oder nicht mit dem Computer verbunden!');
  end;
  ButtonsOn;
end;