ARRAY_Umwandlung_BYTES_TO_HEX

WinniePooh

Level-1
Beiträge
102
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo liebe SPS Gemeinde...

ich habe mal unten ein kleinen Code aufgeschrieben. ( siehe unten).

Dieser soll mir ein (in) ARRAY OF BYTES[1..17] in ein (out) ARRAY OF BYTES [1..8] umwandlen.

Das IN ARRAY besteht aus HEX werten der ASCII Tabelle Bsp.: 30, 35, 42, 39 etc.....
Dieses wandle ich erstmal in ein ASCII Zeichen um also Bsp.: 0, 5, B, 9 etc......
und danach sollen zwei ASCII Zeichen zu einem gesetzt werden Bsp: 05, B9 etc.....
Diese ASCII Zusammensetzung soll dann als ein HEX Wert wieder in ein Byte umgewandelt werden.

Nun habe ich ja den Code geschrieben, aber der will nicht so richtig wie ich es oben beschrieben habe...

kann mir jemand helfen, wo ich den Fehler im Code habe und vielleicht einen besseren Lösungsvorschlag oder Verbesserung geben...

Danke für Eure Verständnis

Gruß
Winnie


Code:
(* Ausgabe soll am Anfang nicht gesetzt werden*)
ENO:=FALSE;
(* Wenn der Baustein aktiviert wird Starten*)
IF    ENI
    THEN 
    i:=1;
    (*Schleife um die Eingangsbytes rauszunehmen und
      daraus einen Array von ASCII Zeichen machen...
      Das InputArray beinhaltet HEX WERTE in BYTES*)                    
    FOR i:=1 TO 16 BY 1
        DO
        BYTE_TO_STRH_1(
        IN:=arrReceiveInput[i]
        );
        arrASCIIString[i]:=BYTE_TO_STRH_1.BYTE_TO_STRH;
    END_FOR;
    (*Initialisieren der Variablen*)
    TempString:='';
    ii:=1;
    i:=1;
    (*In einer Schleife die ASCII String Array[17] auf String Array [8]
      INSTRING1:=2, INSTRING2:=5   OUTSTRING:=25*)
    FOR i:=1 TO 16 BY 1
    DO
        (*Setzt die einzelnen ASCII zeichen zusammen*)
        TempString:=CONCAT(TempString,arrASCIIString[i]);
        (*misst die länge des TempStrings*)
        strLength:=LEN(TempString);
        (*wenn die länge größer oder gleich 2 und ii kleiner 8 dann soll ein
        neues ARRAY [8] geschrieben werden, das eine String mit 2 Chars wird
        zu einem String im Array of String gesetzt*)
        IF    ((strLength >= 2) AND (ii <= 8))
            THEN                     
            arrTempString[ii]:=TempString;
            (*die hochzähl variable ii wird um 1 erhöht und das TempString 
            wird wieder auf '' (leer) gesetzt*)
            ii:=ii+1;
            TempString:='';
        END_IF;
    END_FOR;


    (*Das Array mit den zusammengesetzten String wird nun als HEX- Wert behandelt
    und in einen BYTE aus der ASCII Tabelle verwandelt*)
    i:=1;
    FOR i:=1 TO 8 BY 1
        DO
        HEX_TO_BYTE_1(
        HEX:=arrTempString[i]
        );
        arrReceiveHEX[i]:=HEX_TO_BYTE_1.HEX_TO_BYTE;
    END_FOR;
    (*Einzelne Ausgangsbytes von den HEX Bytes werden rausgeführt*)
    BYTE1:=arrReceiveHEX[1];
    BYTE2:=arrReceiveHEX[2];
    BYTE3:=arrReceiveHEX[3];
    BYTE4:=arrReceiveHEX[4];
    BYTE5:=arrReceiveHEX[5];
    BYTE6:=arrReceiveHEX[6];
    BYTE7:=arrReceiveHEX[7];
    BYTE8:=arrReceiveHEX[8];
    (*Kompletter Ablauf erledigt, weiterschaltbedinung wird auf TRUE gesetzt.*)
    ENO:=TRUE;
END_IF;
 
Hallo,
ganz schön verwirrend! Kann deinen Code nicht so ganz nachvollziehen, scheitere schon an:
Code:
BYTE_TO_STRH_1(IN:=arrReceiveInput[i]);
Ich kenne nur:
Code:
MyString:=BYTE_TO_STRING(MyByte);
sieht bei dir wie ne Instanz aus. Okay ist vielleicht irgendwas aus Oscat oder so!?
Aber jetzt mal zu Thema generell:
Wenn deine Bytes (Array) schon im ASCII code vorhanden sind kommt nur Mist raus wenn Du diese in einen STRING konvertierst, ist ja schon ein String. Mit ner einfachen Case Anweisung sollte das zu lösen sein z.Bsp.:
Code:
(*Deklaration*)
arrReceiveInput:ARRAY [1..17] OF BYTE;//Input?
arrReceiveHex:ARRAY [1..8] OF BYTE;//Output?
tembByte:BYTE;
i:INT;
ii:INT;
(*Implementation*)
FOR i:=1 to 16 DO
 CASE arrReceiveInput[i] OF //überprüfen des Bytes auf ASCII code 1-9 & A-F
  16#31: tempByte:=1;
  [COLOR=#008000]... <- hier die WERTE für 16#32 - 16#39[/COLOR]
  16#41: tempByte:=16#A;
  [COLOR=#008000]... <- hier die WERTE für 16#42 - 16#45[/COLOR]
  16#46: tempByte:=16#F;
 ELSE
  tempByte:=0; //für andere Werte immer 0 zwischenspeichern
 END_CASE
 IF i MOD 2 = 0 THEN
  ii:=i/2;
  arrReceiveHex[ii]:=arrReceiveHex[ii] OR tempByte;
 ELSE
  ii:=i/2+1;
  arrReceiveHex[ii]:=ROL(tempByte,4);
 END_IF
END_FOR
Ich verzichte mal auf weitere Kommentare im Code, ein bissel sollst ja auch selber noch nachdenken!;)
PS: Ich habe den Code selbst nicht getestet aber so halbwegs sollte es passen!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Warum machst du nicht gleich alles in einem Thread?

Hier mein Vorschlag, deinen würde ich verwerfen. Allein schon wegen der Fehleranfälligkeit.

Code:
IN    ARRAY_OF_BYTE_0_16    VAR_INPUT                0    0    0    0    0    0    
OUT    ARRAY_OF_BYTE_0_7    VAR_OUTPUT                0    0    0    0    0    0    
abTemp1    ARRAY_OF_BYTE_0_16    VAR                0    0    0    0    0    0    
abTemp2    ARRAY_OF_BYTE_0_7    VAR                0    0    0    0    0    0    
sTemp    STRING    VAR                0    0    0    0    0    0    
i    INT    VAR                0    0    0    0    0    0    
sByte    STRING    VAR                0    0    0    0    0    0

Code:
abTemp1 := IN;
sTemp := '';

FOR i := 0 TO 15 BY 1 DO
    sTemp := CONCAT(sTemp, BYTE_TO_STRING(abTemp1[i], '%c'));
END_FOR;

FOR i := 0 TO 7 BY 1 DO
    sByte := MID(sTemp, 2, (i * 2) + 1);
    sByte := CONCAT('16#', sByte);
    abTemp2[i] := STRING_TO_BYTE(sByte);
END_FOR;

OUT := abTemp2;

Denke mal jetzt müsste es passen.
Achja, bei Arrays würde ich an deiner Stelle immer bei 0 anfangen und nicht erst bei 1.
 

Anhänge

  • Unbenannt.jpg
    Unbenannt.jpg
    37,3 KB · Aufrufe: 13
Ich habe mal unten zwei Bilder hochgeladen um das mal zu demonstrieren, wie der Input aussieht und was mir mein Baustein in diesem Zustand rausgibt.@ Simatiker: Ja die Funktion kommt von der oscat Bibliothek... und deins werde ich mal nun eintippen :)Unangesteuert.jpg Das gibt mir mein angesteuerter FB raus Angesteuert.jpg
 
Zuletzt bearbeitet:
Hallo Moby,
was passiert eigentlich in diesem Code?:confused:
Code:
sTemp := CONCAT(sTemp, BYTE_TO_STRING(abTemp1[i], '%c'));
Meines Wissens hat CONCAT nur 2 Inputs. Änderung: BYTE_TO_STRING nur einen Input.
Dein Code scheint ja zu funktionieren (bei dir zumindest), aber wie schauts aus wenn das Input Byte den WERT 16#43 (ASCII: 'C') hat?
MOBY schrieb:
Achja, bei Arrays würde ich an deiner Stelle immer bei 0 anfangen und nicht erst bei 1.
Warum?

Übrigens meinen CODE aus Beitrag#2 funktioniert. siehe Bild
 

Anhänge

  • Test_ASCII_Hex.jpg
    Test_ASCII_Hex.jpg
    141,9 KB · Aufrufe: 17
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn da ein %c steht, heißt das, er interpretiert das als ASCII-Zeichen. D.h. wenn dann da ein 16#43 ist kommt da ein 'C' raus und wenn da ein 16#38, dann kommt da eine '8' raus.

Hier mal zur Hilfe:
Code:
Format der Zeichenfolge.
'%c' = ASCII Nummer
'%d' = Dezimalzahl
'%u' =  Vorzeichenlose ganze Zahl
'%x' = Hexadezimalzahl
'%e' = Gleitkommazahl  Exponential
'%f' = Gleitkommazahl
'%l' = Optionaler Parameter
'' =  Standardwerte werden benutzt

Und mit 0 fang ich an, weil ich es so in C# gelernt habe. Da viele Bausteine, wenn sie ein Array zurückgeben, 0-basierend sind. Außerdem ist es doch besser wenn man am Anfang anfängt und nicht an der zweiten Stelle. Wie bei einem Byte, da fängste ja auch bei Bit 0 an.
 
Hallo,
Wenn da ein %c steht, heißt das, er interpretiert das als ASCII-Zeichen. D.h. wenn dann da ein 16#43 ist kommt da ein 'C' raus und wenn da ein 16#38, dann kommt da eine '8' raus.
und das ist verfügbar unter PC Works? In CodeSys geht das auf jeden Fall nicht.

...Und mit 0 fang ich an, weil ich es so in C# gelernt habe. Da viele Bausteine, wenn sie ein Array zurückgeben, 0-basierend sind. Außerdem ist es doch besser wenn man am Anfang anfängt und nicht an der zweiten Stelle. Wie bei einem Byte, da fängste ja auch bei Bit 0 an.
Ich fange bei 0 an weil es möglich ist und manchmal fange ich bei 1 an weil es übersichtlicher ist. Und wenn ein Baustein ein Array [0..9] of irgendwas liefert kann ich da auch mein Array [1.10] of irgendwas anbinden.;) Ich will nur sagen, es ist jedem selbst überlassen wie er sein Array deklariert.
 
Hallo,
und das ist verfügbar unter PC Works? In CodeSys geht das auf jeden Fall nicht.
Jap ist es.
Ich fange bei 0 an weil es möglich ist und manchmal fange ich bei 1 an weil es übersichtlicher ist. Und wenn ein Baustein ein Array [0..9] of irgendwas liefert kann ich da auch mein Array [1.10] of irgendwas anbinden.;) Ich will nur sagen, es ist jedem selbst überlassen wie er sein Array deklariert.
Da haste ja auch recht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Simatiker und Hallo Mobi... Danke für eure Tipps...

Danke Simatiker... deinen Vorschlag habe ich implementiert und hat gut geklappt obwohl bei diesem die PCWorx etwas Probleme hatte mit der Syntax...
einbißchen umgeschrieben und es hat mir die Werte so implementiert wie ich es wollte... DANKE...

Danke Mobi... für die Erklärung der Byte in String Umwandlung... habe es nicht so richtig bei der Phoenix Hilfe kapiert... aber jetzt ist kein Problem...
und mein Quellcode habe ich entsorgt... und nun habe ich auch keine Kopfschmerzen... :)

So sieht das implementiert aus... :) und es klappt... :)

Gruß
Code:
ENO:=FALSE;
IF ENI
THEN
FOR i:=1 TO 16 BY 1
	DO
    
    tempInteger:=BYTE_TO_INT(arrReceiveInput[i]);
	CASE tempInteger OF
	    48:  tempByte:=BYTE#0;
        49:  tempByte:=BYTE#1;
        50:  tempByte:=BYTE#2;
        51:  tempByte:=BYTE#3;
        52:  tempByte:=BYTE#4;
        53:  tempByte:=BYTE#5;
        54:  tempByte:=BYTE#6;
        55:  tempByte:=BYTE#7;
        56:  tempByte:=BYTE#8;    
        57:  tempByte:=BYTE#9;
        65:  tempByte:=BYTE#16#A;
        66:  tempByte:=BYTE#16#B;
        67:  tempByte:=BYTE#16#C;
        68:  tempByte:=BYTE#16#D;
        69:  tempByte:=BYTE#16#E;
        70:  tempByte:=BYTE#16#F;
	ELSE
        tempByte:=BYTE#0;
    END_CASE;
    IF ((i MOD 2) = 0)
	THEN 					
		ii:=i / 2;
        arrReceiveHex[ii]:=arrReceiveHex[ii] OR tempByte;
	ELSE
	    ii:=((i / 2) + 1);
        arrReceiveHex[ii]:=ROL(tempByte,4);
    END_IF;
END_FOR;
FOR i:=1 TO 8 BY 1
	DO
	CASE i OF
	1:  BYTE1:=arrReceiveHex[i];
    2:  BYTE2:=arrReceiveHex[i];
    3:  BYTE3:=arrReceiveHex[i];
    4:  BYTE4:=arrReceiveHex[i];
    5:  BYTE5:=arrReceiveHex[i];
    6:  BYTE6:=arrReceiveHex[i];
    7:  BYTE7:=arrReceiveHex[i];
    8:  BYTE8:=arrReceiveHex[i];
END_CASE;
END_FOR;
ENO:=TRUE;
END_IF;
 
@ Mobi... habe den anderen code gesehen verstanden und sofort implementiert...
dein code hat aber eine starke ähnlichkeit mit der pcworx... arbeitest du mit ihr???

gruß
 
Klar, ich hab hier mehrere ILC und deswegen dann auch PC Worx. Sonst hätte ich es ja auch mit dem BYTE_TO_STRING nicht machen können.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
@ mobi... ich habe bei pcworx ein fb früher gesehen weiß nur nicht mehr wie der heißt...
er verschiebt bei einem TRUE 1 Wert auf den Anderen...
so ähnlich einer IF Anweisung...

gru
 
Hallo,
in der CASE Anweisung kannst Du den Code noch etwas optimieren:
Code:
CASE tempinteger OF
  49..57: tempByte:=INT_TO_BYTE(tempinteger-48);
  65..70: tempByte:=INT_TO_BYTE(tempinteger-55);
ELSE
  tempByte:=Byte#0;
END_CASE
 
hatte ihn gar nicht gebraucht... merk ich jetzt..,...
oh my god wenn es ist zeit für feierabend... :)

wie machst du das bloß biste just 4 fun on oder biste am arbeiten...

gruß
 
Ich bin zu Hause, bekomme halt nur mit per Handy wenn etwas passiert. Was hättest du denn nicht gebraucht?
 
Zurück
Oben