INT oder DINT in CHAR/BYTE Umwandeln

ok nochmal langsam.....
der weg geht.

ein int besteht aus einem word:
0000 0000 0000 0001 = int 1
0000 0000 0000 0010 = int 2
0000 0000 0000 0011 = int 3
0000 0000 0000 0100 = int 4
0000 0000 0000 0101 = int 5
0000 0000 0100 0011 = int 69
usw... binäre zahlencodierung eben.

der zahlenformat bcd kommt aus der "alten zeit" wo alles mit 7segment anzeigen dargestellt worden ist.
--
| |
--
| |
--

1= sind dort die rechten beiden striche
2= oben, rechts oben, mitte, links unten und unten
3= oben, rechts oben, mitte, rechts unten und unten
usw.

man brauch also, um die zahlen anzeigen zu können, jede zahl in einem eigenen bereich.

123 int = 0000 0000 0111 101 binär
mit so einer zahlenfolge bzw. binärcodierung kann man keine 7segmentanzeige ansteuern.

123 int in bcd gewandelt sieht dann so aus:
0000 0001 0010 0011 jede zahl bekommt ein "halb"byte (4 bollsche werte)


ein char ist ein zeichen. diese zeichen (zb '1') sind einem HEX wert zugeordnet. b#16#31 = ist gleich das zeichen für eine 1
b = byte
16 = hexdezimale darstellung
31 = der eigentliche wert

nun ist es bei siemens so, dass ich in awl verschiedene datentypen in andere einfach reintransferieren kann.

L 123 // int zahl
int_to_bcd //wandlungsfunktion von siemens
T MW30 //word in merkerbereich

im MW30 steht nun 0000 0001 0010 0011 (binär ansicht)

L MW30
slw 4 //siemensfunktion=> schiebe links word 4, dann steht im AKKU1 0001 0010 0011 0000
//alle stellen sind binär gesehen 4 nach links geschoben worden.
srw 12 //siemensfunktion=> schiebe rechts word 12, dann steht im AKKU1 0000 0000 0000 0001
//alle stellen sind binär gesehen 12 nach rechts geschoben worden. und somit steht die dezimale 1 aleine um AKKU1
L b#16#30 //lädt eine hexidezimale 30
+i // integer addition
t char // byte als char deklariert
es steht nun eine 1 ALS ZEICHEN in dem byte.

für die zweite zahl (2):
L 123 // int zahl
int_to_bcd //wandlungsfunktion von siemens
T MW30 //word in merkerbereich

L MW30 //0000 0001 0010 0011
slw 8 //siemensfunktion=> schiebe links word 8, dann steht im AKKU1 0010 0011 0000 0000
//alle stellen sind binär gesehen 8 nach links geschoben worden.
srw 12 //siemensfunktion=> schiebe rechts word 12, dann steht im AKKU1 0000 0000 0000 0010
//alle stellen sind binär gesehen 12 nach rechts geschoben worden. und somit steht die dezimale 2 aleine um AKKU1
L b#16#30 //lädt eine hexidezimale 30
+i // integer addition
t char // byte als char deklariert
es steht nun eine 2 ALS ZEICHENin dem byte.

usw usw....
das verschieben änder sich immer um 4 nach links.

man kann natürlich auch doppelwörter schieben. sld und srd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
bei doppelwörtern (dword) tauscht siemens das high und das low word.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

aufgabenstellung:
für alle die es sich jetzt mit einer cpu (oder simu) anschauen wollen gehen wie folgt vor:

im ob 1 sollte stehen:
L MW30
int_to_bcd
slw 12
srw 12
t mb40

L MD35
sld 12
srd 20
t mb41



varieablentabelle:

MW30 darstellung zahl //für die versuche nur hier verschiedenen zahlen eintragen
MW30 darstellung bool/binär
MB30 darstellung zahl
MB30 darstellung zeichen
MD30 darstellung zahl
MD30 darstellung bool/binär
MD30 gleitpunkt
MB40 darstellung zeichen

MD35 darstellung zahl //für die versuche nur hier verschiedenen zahlen eintragen
MW35 darstellung bool/binär
MW36 darstellung bool/binär
MD30 darstellung bool/binär
MB35 darstellung zeichen
MD30 gleitpunkt
MB41 darstellung zeichen


jetzt sollten jeden die zusammenhänge der verschiedenen zahlenformaten (zeichen) klar werden. ;)

die genauen bezeichnungen für die variablentabelle können etwas ander heisen. hab kein step 7 auf dem rechner :)
p.s. wer rechtschreibfehler findet, darf sie behalten (hoffe habe im kopf richtig geschoben).

MfG Fanta
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
mit Dieser code geht es
Code:
  L     "DB10".Char_Nummer[10]
      L     W#16#F
      UW    
      T     "DB10".Dint_Nummer

      L     "DB10".Char_Nummer[9]
      L     W#16#F
      UW    
      L     10
      *I    
      L     "DB10".Dint_Nummer
      +D    
      T     "DB10".Dint_Nummer

      L     "DB10".Char_Nummer[8]
      L     W#16#F
      UW    
      L     L#100
      *D    
      L     "DB10".Dint_Nummer
      +D    
      T     "DB10".Dint_Nummer


      L     "DB10".Char_Nummer[7]
      L     W#16#F
      UW    
      L     L#1000
      *D    
      L     "DB10".Dint_Nummer
      +D    
      T     "DB10".Dint_Nummer


      L     "DB10".Char_Nummer[6]
      L     W#16#F
      UW    
      L     10000
      *D    
      L     "DB10".Dint_Nummer
      +D    
      T     "DB10".Dint_Nummer

// UZW
 

Anhänge

  • ScreenHunter_01 Oct. 18 23.38.jpg
    ScreenHunter_01 Oct. 18 23.38.jpg
    44,4 KB · Aufrufe: 38
Es geht dann auch mit :
- Char-Array zu String umtransferieren (oder die Daten gleich in den Datenbereich eines Strings schicken lassen).
- mit dem String-FC RIGHT den rechten Teil des Strings abschneiden und in einen Hilfsstring packen (lassen).
- den Hilfsstring mit STRING_to_DINT (oder STRING_to_INT) in eine Zahl umwandeln.

Ich habe es noch nicht ausprobiert, aber möglicherweise würde der STRING_to_INT-FC sogar den ursprünglichen String komplett in eine Zahl wandeln - das macht aber nur dann Sinn, wenn es immer führende Nullen sind ...

Gruß
Larry
 
bombe ! vielen dank. mit fantas methode hats geklappt. danke auch für die ausführliche erklärung. joopBs und larrys methode werde ich später auch noch versuchen...bin jetzt erstmal glücklich. :D
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
ich habe ein Problem mit der Umwandlung von Byte in INT. Ich möchte die Stunden DB5.DBB5 und die Minuten DBB5.DBB6 zur Weiterverarbeitung in INT umwandeln. Das Umwandeln funktioniert aber ich mache was falsch. Ich habe es versicht mit MOVE, habe aber das Problem wenn der DB5.DBB5 eine 12 anzeigt steht am Ausgang des MOVE auch ein 12, verarbeite ich das Signal aber weiter wird mit einer anderen Zahl weitergearbeitet. Bei dem DB5.DBB6 ist dies auch der Fall, was mache ich falsch?
Die Programmierung sieht folgendermaßen aus:
L DB5.DBB 5 (hier steht zum Bsp. die Stunden) 12
T #Stunden (hier steht im Online auch die 12, aber verarbeite ich #Stunden im nächsten NW weiter steht eine 15 oder oder so da? was stimmt da nicht.
Habe es schon mit Merkerwort und Merkerdoppelwort probiert war aber das gleiche Problem.

Kann mir einer von Euch weiterhelfen?

MFG siggi76
 
vermutlich stehen in Deinen DBB5 und DBB6 die Stunden und Minuten im BCD-Format und Deine Verwirrung kommt einfach nur vom ungenauen Beobachten und interpretieren. Der MOVE dürfte Dir 16#12 anzeigen, Dein späteres Laden zeigt aber einen INT ( 18 ).
Was meinst Du eigentlich mit "Weiterverarbeiten" der Stunden und Minuten in einen INT? Soll da zum Schluß die Anzahl Minuten drinstehen?
Das wäre dann etwa diese Formel: #Zeitdauer = BCD_TO_INT(DBB5) * 60 + BCD_TO_INT(DBB6)

PS: Es wäre schöner gewesen, wenn Du ein eigenes Thema angefangen hättest ...

Harald
 
Hallo Harald,
ich wollte ein neues Thema anfangen, habe es aber irgendwie nicht hinbekommen. muss mich nochmals umschauen.
Ja richtig Move zeigt mir 16#12 und ein späteres Laden zeigt mir 18 an.
Ich möchte die 12 als Stunde verwenden um einen Schichtzähler zu programmieren.
Aber wenn es 12 Uhr ist wird mir 18 bei der Weiterverwendung angezeigt.
Die Stunden werden im DB5.DBB5 angezeit und die Minuten in DB5.DBB6.

Die Stunden und Minuten möchte ich als Eingänge von Vergleichern nutzen um einen Schichtzähler von 3 Stunden zu programmieren.

MFG
Siggi76
 
Zuviel Werbung?
-> Hier kostenlos registrieren
moin....
16#12 heist, dass es in im HEX-format dargestellt wird. dezimale = 0..10(0123456789); hexidezimal 0..F (0123456789ABCDEF).
HEX16=Dezimal18

dein problem(denkfehler), so denke ich;), liegt an der tatsache, dass der tag 24 stunden hat und du auch dieses in den stunden angezeigt bekommst.
für deinen schichtzähler solltest du auch daran denken, dass in einer schicht es auch 0:00Uhr ist/gibt (der nächste tag). in keiner firma fängt die schicht um 0:00uhr an. also muss dein vergleicher diese berücksichtigen.

hoffe konnte die helfen ansonsten beschreib mal dein prob. genauer.

Fanta
 
Hallo,
da ich auch mal was zu diesem Forum beitragen will, hier zwei Funktionen die ich kürzlich für die Wandlung von DINT in CHAR bzw. CHAR in DINT geschrieben habe.

DINT_TO_CHAR
Code:
//Umwandlung DINT nach ASCII
//
//Stand: 2012 - 10 - 08
//

FUNCTION FC2001 : VOID
TITLE = 'DINT_TO_ASCII'
VERSION : '1.0'
AUTHOR : Jupp06
//---------------------------------------------//
// Schnittstelle                               //
//---------------------------------------------//
// Eingangsparameter
VAR_INPUT  
Datenbaustein : BLOCK_DB; //Datenbaustein mit ARRAY OF CHAR (max. 10 Stellen)
Start_Byte : INT; //Erstes Byte des Ziel Arrays
Laenge : INT; //Anzahl der Stellen der zu wandelnden Zahl
DINT_Wert : DINT; //Zu wandelnde DINT-zahl
END_VAR
//temporäre Variablen
VAR_TEMP
Bytes : INT;
DINT_Puffer : DINT;
EXPONENT : DINT;
MULTIPLIKATOR : DINT;
CHAR_ARRAY : ARRAY[0..9] OF BYTE;     
END_VAR
BEGIN
DINT_Puffer := DINT_Wert;
IF Laenge >= 1 AND Laenge <= 10
   THEN
   FOR Bytes := 0 TO Laenge - 1 BY 1 DO
       MULTIPLIKATOR := 1;
       IF (Laenge - Bytes - 1) > 0
          THEN
          FOR EXPONENT := 1 TO Laenge - Bytes - 1 BY 1 DO
              MULTIPLIKATOR := MULTIPLIKATOR * 10;
          END_FOR;
       END_IF; 
       CHAR_ARRAY[Bytes] := DINT_TO_BYTE(DINT_Puffer / MULTIPLIKATOR + 48);
       DINT_Puffer := DINT_Puffer - ((BYTE_TO_DINT(CHAR_ARRAY[Bytes]) - 48) * MULTIPLIKATOR);
       Datenbaustein.DB[Start_Byte + Bytes] := CHAR_ARRAY[Bytes];
   END_FOR;    
END_IF;
END_FUNCTION

Beispiel:
"DINT_TO_ASCII"(Datenbaustein:=DB10, Start_Byte:=6, Laenge:=4, DINT_Wert:=Sequenz_Nummer);



ASCII_TO_DINT
Code:
//Umwandlung ASCII nach DINT
//
//Stand: 2012 - 10 - 08
//

FUNCTION FC2000 : DINT
TITLE = 'ASCII_TO_DINT'
VERSION : '1.0'
AUTHOR : Jupp06
//---------------------------------------------//
// Schnittstelle                               //
//---------------------------------------------//
// Eingangsparameter
VAR_INPUT  
Datenbaustein : BLOCK_DB; //Umzuwandelndes ARRAY OF CHAR (max. 10 Stellen)
Start_Byte : INT; //Erstes Byte des Quell-Arrays
Laenge : INT; //Länge des Arrays (1 - 10 Stellen)
END_VAR
//temporäre Variablen
VAR_TEMP
Bytes : INT;
EXPONENT : DINT;
MULTIPLIKATOR : DINT;
BCD_ARRAY : ARRAY[0..9] OF BYTE;     
END_VAR
BEGIN
FC2000 := 0;
IF Laenge >= 1 AND Laenge <= 10
   THEN
   FOR Bytes := 0 TO Laenge - 1 BY 1 DO
       BCD_ARRAY[Bytes] := INT_TO_BYTE(BYTE_TO_INT(Datenbaustein.DB[Start_Byte + Bytes]) - 48);
       MULTIPLIKATOR := 1;
       IF (Laenge - Bytes - 1) > 0
          THEN
          FOR EXPONENT := 1 TO Laenge - Bytes - 1 BY 1 DO
              MULTIPLIKATOR := MULTIPLIKATOR * 10;
          END_FOR;
       END_IF; 
       FC2000 := FC2000 + (BYTE_TO_DINT(BCD_ARRAY[Bytes]) * MULTIPLIKATOR);
   END_FOR;    
END_IF;
END_FUNCTION


Beispiel:
Aktuelle_Nummer := "ASCII_TO_DINT"(Datenbaustein:=DB10 , Start_Byte:=32, Laenge:=10);


Gruß
Johannes ;)
 
Zuletzt bearbeitet:
Ne das wäre ja dann die 49 in Dez und 31 in Hex
Ich möchte sozusagen die 1 in Dez und die 1 in Hex

Gruß Psych
 
Was genau willst Du tun? Einen Zahlenwert irgendwo anzeigen?
Erkläre es mal ohne Programmierer-Fremdworte. Und ohne "sozusagen". ;)

Harald
 
Hallo, ich habe ASCII Zeichen im Format "Array [1..20] of Char" in einem DB stehen.
Möchte nun 8 Zeichen von Char[12] bis Char[19] in ein DWORD kopieren.
Die Zeichen beinhalten nur 0-F.
Wie mache ich das am einfachsten?
Vielen Dank!
 
Zurück
Oben