Word (hex) to 4x Char

Andy082

Level-2
Beiträge
177
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Abend.

Ein Kunde will in seinem Datamatrixcode als fortlaufende Nummer (wird am Tagesanfang zurückgesetzt) eine 4 stellige HEX-Zahl stehen haben.

Das Ganze sieht in etwa so aus....
xxxxxxxxxxxxxxxxxx2F03 (x steht für den restlichen Dateninhalt)

Bei jedem Druck eines Labels erhöhe ich dieses Word um B#16#01, also um eins.
Um das Ganze an meinen Labeldrucker übergeben zu können muss ich den Inhalt nun in Char's umspeichern.

C#1: '2'
C#2: 'F'
C#3: '0'
C#4: '3'

Das Ganze sieht in meinem Funktionsbaustein nun so aus:
Code:
      SET   
      L     #Eingabe
      SLW   0
      SRW   12
      L     B#16#30
      +I    
      T     #C1
      L     B#16#3A
      <I    
      SPB   a001
      L     #C1
      L     B#16#7
      +I    
      T     #C1
a001: SET   
      L     #Eingabe
      SLW   4
      SRW   12
      L     B#16#30
      +I    
      T     #C2
      L     B#16#3A
      <I    
      SPB   a002
      L     #C2
      L     B#16#7
      +I    
      T     #C2
a002: SET   
      L     #Eingabe
      SLW   8
      SRW   12
      L     B#16#30
      +I    
      T     #C3
      L     B#16#3A
      <I    
      SPB   a003
      L     #C3
      L     B#16#7
      +I    
      T     #C3
a003: SET   
      L     #Eingabe
      SLW   12
      SRW   12
      L     B#16#30
      +I    
      T     #C4
      L     B#16#3A
      <I    
      SPB   a004
      L     #C4
      L     B#16#7
      +I    
      T     #C4
a004: SET

Die einen werden jetzt sagen, warum das hin- und herschieben und nicht ausmaskieren, andere sagen eventuell passt schon.
Was mir aber nicht ganz gefällt ist der Offset um einen Buchstaben, also A-F in einen Char umzuwandeln, auch wenn's funktioniert.

Hat jemand ne' andere Idee, denn ich lerne gerne dazu......


mfg,
Andy
 
Nun, nachdem S7-Steuerungen nicht gerade Meister in der Handhabung von Zeichen und Ketten davon sind (und nachdem ich vergeblich mit einigen Umwandlungsoperationen gespielt habe) würde ich folgende einfache Lösung in SCL wählen:

FUNCTION FC2 : VOID
VAR_TEMP
// temporäre Variablen
tmp_idx :INT;
END_VAR

// Ausmaskieren und Zeichen bestimmen
FOR tmp_idx := 4 TO 1 BY -1 DO
Test_DB.c[tmp_idx] := Test_DB.Zeichen[WORD_TO_INT(SHR(IN:=Test_DB.Eingabe,N:=4*(tmp_idx-1)) AND W#16#000F)];
END_FOR;

END_FUNCTION


Worin die Variable Test.xxx einem DB entstammen.

Markus
 
lol....

Was war das Schlüsselwort....?
SCL-Editor oder Teufel.....


Lt. Info ist der SCL-Editor mit meiner Prof.Edition meines 5.4 mitinstalliert.
Auch die benötigte License is drauf und aktiv, aber ich hab nicht die Möglichkeit eine SCL-Quelle zu erstellen.
 
ich würde es mit hilfe einer linearen funktion machen :cool:

y = m*x + n ... ihr erinnert euch?

einzig der böse sprung um die 40h stört, aber den kann man ja interpolieren :ROFLMAO:

also, wir nehmen an, die hexwerte 30-39 und 41-46 seien dezimal
damit bestimmen wir eine lineare funktion

x1 = 0
x2 = 15
y1 = 30
y2 = 46

-> m = 16/15; n = 30;

daraus folgt folgende wertetabelle:

Code:
X	Y
0	30
1	31,06666667
2	32,13333333
3	33,2
4	34,26666667
5	35,33333333
6	36,4
7	37,46666667
8	38,53333333
9	39,6
10	40,66666667
11	41,73333333
12	42,8
13	43,86666667
14	44,93333333
15	46

39,6 gerundet wäre 40 ... also müssen wir an der stelle "interpolieren" aber so, dass y(10) gerundet 41 ergibt ... also -0,11 sollte genügen

also ist die resultierende funktion y ≈ 16/15 * x + 29,89

ich hab das mit dem schieben mal so gelassen und die ganze funktionalität in eine schleife gepackt:

Code:
*
FUNCTION "word_to_char" : VOID
TITLE =
//this function realize the word_to_char exchange
//
//DATE:     06.11.2009
//AUTHOR:   4lagig
//VERSION:  V0.1 BasicVer
VERSION : 0.1


VAR_INPUT
  wIn : WORD ;	
END_VAR
VAR_OUTPUT
  C1 : CHAR ;	
  C2 : CHAR ;	
  C3 : CHAR ;	
  C4 : CHAR ;	
END_VAR
VAR_TEMP
  iLoopCounter : INT ;	
  aChar : ARRAY  [0 .. 3 ] OF BYTE ;	
END_VAR
BEGIN
NETWORK
TITLE =

      LAR1  P##aChar;            //start für zwischenspeicher

      L     4;                   //schleife initialisieren
next: T     #iLoopCounter; 
      L     -4;                  //links schieben
      *I    ;                    //errechnen
      +     16;                  //mit y=-4*x+16
      L     #wIn; 
      SLW   ; 
      SRW   12;                  //nibble maskieren
      DTR   ;                    //in real wandeln
      L     1.066667e+000;       //----------------------
      *R    ;                    //      16
      L     2.989000e+001;       // y = ---- * x + 29,89
      +R    ;                    //      15
      RND   ;                    //----------------------
      ITB   ;                    //gerundet als BCD
      T     B [AR1,P#0.0];       //in Byte speichern

      +AR1  P#1.0;               //pointer erhöhen
      L     #iLoopCounter; 
      LOOP  next;                //NEXT

//nach außen kopieren
      L     #aChar[0]; 
      T     #C1; 
      L     #aChar[1]; 
      T     #C2; 
      L     #aChar[2]; 
      T     #C3; 
      L     #aChar[3]; 
      T     #C4; 
     
      SET;
      SAVE;

END_FUNCTION

wenn du das ganze in einen FB packst, kannste dir die TempChars auch noch sparen ...
 

Anhänge

  • word_to_char.JPG
    word_to_char.JPG
    35,6 KB · Aufrufe: 109
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich kann einfach nur meinen Hut ziehen vor dieser doch sehr "anderen" Lösung der alten Hex->Asc Wandlungsaufgbe.

Klasse 4L!

danke, nachtschicht machts möglich ...
ich hab mir die blöde ASCII-table angeguckt und so über das blöde @ geflucht ... das hätte ja wohl auch woanders platz gehabt :rolleyes:
 
Danke für all die Vorschläge.

Da es sich bei mir aber nur um 4 Chars handelt, denke ich, dass ich's bei meiner kleinen AWL-Funktion belassen werde.

mfg,
Andy
 
Na, da ich dachte man könnte meine Funktion in AWL noch einfacher gestalten.....

Den Vorteil in deiner Funktion sehe ich darin, da es so einfacher ist längere hex-Anweisungen in Chars umzuwandeln.

Ich hoffe dies hat nicht zu viel Zeit in anspruch genommen.... :cool:
 
Ich hoffe dies hat nicht zu viel Zeit in anspruch genommen.... :cool:

hat es nicht. wenn man weiß, wo man hin will, dauert das kommentieren am längsten ...

nicht nur die länge der auswertung sehe ich als vorteil, sondern auch die stabilität der zykluszeit ... keine bedingten sprünge, schleifen abbrüche oder sonstiges ... einfach 4*11zeilen ...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
hat es nicht. wenn man weiß, wo man hin will, dauert das kommentieren am längsten ...

nicht nur die länge der auswertung sehe ich als vorteil, sondern auch die stabilität der zykluszeit ... keine bedingten sprünge, schleifen abbrüche oder sonstiges ... einfach 4*11zeilen ...

Du hast sehr geschickt einfache Ganzzahloperationen durch Gleitkommarechnung ersetzt. Dabei ist noch nicht einmal sicher, dass der Zeitbedarf einer Multiplikation unabhängig von den Operanden ist.
 
wie würde das Ganze dann mit Dez to Char ablaufen....

Hab hier einen FC einer Zulieferfirma erhalten, welcher aber in SCL geschrieben ist.

Da die Umwandlung von hex in char so wunderbar geklappt hat, dachte ich mir ich lass mal rätseln, wie man denn Dezimalzahlen in Chars umwandelt.

Meiner Ansicht nach ungleich schwieriger.... da zumindest ich in AWL an meine Grenzen stoße.

Form:
Eingabe: 12345
C#1: 1
C#2: 2
C#3: 3
C#4: 4
C#5: 5

oder

Eingabe: -45
C#1: 0
C#2: 0
C#3: -
C#4: 4
C#5: 5

oder

Eingabe: -1234
C#1: -
C#2: 1
C#3: 2
C#4: 3
C#5: 4
 
Zuletzt bearbeitet:
Abend.

Ist mir bekannt....
Aber selbst eine Funktion zu basteln, welche dies bewerkstelligt?
bzw. eben direkt Chars ausgibt und nicht einen String hierzu benötigt?

mfg,
Andy
 
ich hab da mal bei dem einen oder anderen bier drüber nachgedacht ... eigentlich ist das gar nicht so schwer ... /10 -> Rest (<10) + w#16#30 -> char ... mit dem quotienten weiter ...
dann noch rausfinden, wo das minus stehen soll ...

Code:
*
FUNCTION FC 4 : VOID
TITLE =
VERSION : 0.1


VAR_INPUT
  dInput : DINT ;    
END_VAR
VAR_OUTPUT
  C_0 : CHAR ;    
  C_1 : CHAR ;    
  C_2 : CHAR ;    
  C_3 : CHAR ;    
  C_4 : CHAR ;    
  C_5 : CHAR ;    
  C_6 : CHAR ;    
  C_7 : CHAR ;    
  C_8 : CHAR ;    
  C_9 : CHAR ;    
  C_10 : CHAR ;    
END_VAR
VAR_TEMP
  xMin : BOOL ;    
  xFirstNumber : BOOL ;    
  xMinus : BOOL ;    
  dTemp : DINT ;    
  iLoop : INT ;    
  aChar : ARRAY  [0 .. 10 ] OF BYTE ;    
  iMinusPos : INT ;    
  dMOD : DINT ;    
  dCompare : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =

//initialisieren
      CLR   ; 
      =     #xMinus; 
      =     #xMin; 
      L     1; 
      T     #iMinusPos; 
//sonderfall
      L     #dInput; 
      L     L#-2147483648; 
      ==D   ; 
      SPBN  nmin; 
      =     #xMin; 
      L     #dInput; 
      +     1; 
      SPA   min; 

//input ist minus??
nmin: L     #dInput; 
      L     L#0; 
      <D    ; 
      L     #dInput; 
      SPBN  nonu; 
min:  SET   ; 
      =     #xMinus; 
      L     L#-1; 
      *D    ; 
nonu: T     #dTemp; 

//ja, ist minus - position für - berechnen
      U     #xMinus; 
      SPBN  ohmi; 
      L     10; 
      T     #dCompare; 
      L     10; 
nex1: T     #iLoop; 
      L     #dTemp; 
      L     #dCompare; 
      <D    ; 
      SPBN  noch; 
      L     #iLoop; 
      T     #iMinusPos; 
      SPA   ohmi; 
noch: L     #dCompare; 
      L     L#10; 
      *D    ; 
      T     #dCompare; 
      L     #iLoop; 
      LOOP  nex1; 

//ausgabe der einzelnen stellen
ohmi: LAR1  P##aChar; 
      L     11; 
next: T     #iLoop; 
      L     #dTemp; 
      L     10; 
      MOD   ; 
      L     W#16#30; 
      +I    ; 
      T     B [AR1,P#0.0]; 
      L     #dTemp; 
      L     10; 
      /D    ; 
      T     #dTemp; 
      +AR1  P#1.0; 
      L     #iLoop; 
      LOOP  next; 

//ausgabe -
      U     #xMinus; 
      SPBN  end; 
      LAR1  P##aChar; 
      L     11; 
nex2: T     #iLoop; 
      L     #iMinusPos; 
      ==I   ; 
      SPBN  naec; 
      L     W#16#2D; 
      T     B [AR1,P#0.0]; 
      SPA   end; 
naec: +AR1  P#1.0; 
      L     #iLoop; 
      LOOP  nex2; 

//rauskopieren
end:  L     #aChar[10]; 
      T     #C_0; 
      L     #aChar[9]; 
      T     #C_1; 
      L     #aChar[8]; 
      T     #C_2; 
      L     #aChar[7]; 
      T     #C_3; 
      L     #aChar[6]; 
      T     #C_4; 
      L     #aChar[5]; 
      T     #C_5; 
      L     #aChar[4]; 
      T     #C_6; 
      L     #aChar[3]; 
      T     #C_7; 
      L     #aChar[2]; 
      T     #C_8; 
      L     #aChar[1]; 
      T     #C_9; 
      U     #xMin; 
      L     #aChar[0]; 
      SPBN  nee;       
      +     1;       
nee:  T     #C_10;      
      SET   ; 
      SAVE  ; 
END_FUNCTION
 

Anhänge

  • dint_to_char.JPG
    dint_to_char.JPG
    43,5 KB · Aufrufe: 59
Zuletzt bearbeitet:
Zurück
Oben