Forum: Mikrocontroller und Digitale Elektronik ASCII nach Binär umwandlung => was muss ich da tun


von Stefan S. (buffalochill)


Lesenswert?

Hallo liebes Forum,

ich hab jetzt hier das forum und internet durchstöbert aber leider nix 
passendes gefunden.
Ich muss meine Daten 3 ASCII zeichen in ein Binärbyte umwandeln. Meine 
Werte sind immer kleiner gleich 255.
Ich habe eine Routine gefunden die das kann, weiss aber nicht so recht 
wie ich dieser Routine die Daten übergeben muss damit ich hinterher mein 
binär Byte rauskriege.

Zum Beispiel: ich hab drei zeichen im SRAM stehen sram1: 2 Sram2: 5 sram 
3: 4
das würde dann einem Wert binär von 254 ergeben.

Wie muss ich den Z pointer jetzt einstellen damit er mir das umwandelt? 
und wie müssen die ASCII zeichen im SRAM abgelegt sein damit die 
berechnung hinterher stimmt ?

Grüße
Stefan

; AscToBin2
; =========
; converts an ASCII coded number to a 2-Byte bi-
; nary
; In: Z points to first digit, conversion stops at first
;   digit detected or if overflow of the result occurs,
;   end of number must be terminated by a non-decimal
;   ASCII-digit!
; Out: Z points to first non-valid digit or to the digit
;   where the overflow occurred, if number is valid the
;   T-Flag is clear and the number is in registers
;   rBin1H:rBin1L
; Used registers: rBin1H:L (result), rBin2H:L (restored
;   after use), rmp
; Called subroutines: Bin1Mul10
;

AscToBin2:
  clr rBin1H ; Clear the result
  clr rBin1L
  clt ; Clear error flag bit
AscToBin2a:
  ld rmp,Z+ ; ignore leading blanks and zeros
  cpi rmp,' ' ; blank?
  breq AscToBin2a
  cpi rmp,'0' ; zero?
  breq AscToBin2a
AscToBin2b:
  subi rmp,'0' ; subtract ASCII zero
  brcs AscToBin2d ; End of the number
  cpi rmp,10 ; check invalid digit
  brcc AscToBin2d ; No-decimal char
  rcall Bin1Mul10 ; Multiply binary number by 10
  brts AscToBin2c ; overflow, return with T-Flag set
  add rBin1L,rmp ; add the digit to the binary
  ld rmp,Z+ ; read next char
  brcc AscToBin2b ; no overflow to binary MSB
  inc rBin1H ; Overflow to binary MSB
  brne AscToBin2b ; no overflow of binary MSB
  set ; Set overflow flag
AscToBin2c:
  sbiw ZL,1 ; Back one char, last char end/invalid
AscToBin2d:
  ret

; Bin1Mul10
; =========
; multiplies a 16-bit-binary by 10
; Sub used by: AscToBin2, Asc5ToBin2, Bcd5ToBin2
; In: 16-bit-binary in rBin1H:L
; Out: T-flag shows general result:
;   T=0: Valid result, 16-bit-binary in rBin1H:L ok
;   T=1: Overflow occurred, number too big
;
Bin1Mul10:
  push rBin2H ; Save the register of 16-bit-binary 2
  push rBin2L
  mov rBin2H,rBin1H ; Copy the number
  mov rBin2L,rBin1L
  add rBin1L,rBin1L ; Multiply by 2
  adc rBin1H,rBin1H
  brcs Bin1Mul10b ; overflow, get out of here
Bin1Mul10a:
  add rBin1L,rbin1L ; again multiply by 2 (4*number reached)
  adc rBin1H,rBin1H
  brcs Bin1Mul10b ; overflow, get out of here
  add rBin1L,rBin2L ; add the copied number (5*number reached)
  adc rBin1H,rBin2H
  brcs Bin1Mul10b ;overflow, get out of here
  add rBin1L,rBin1L ; again multiply by 2 (10*number reached)
  adc rBin1H,rBin1H
  brcc Bin1Mul10c ; no overflow occurred, don't set T-flag
Bin1Mul10b:
  set ; an overflow occurred during multplication
Bin1Mul10c:
  pop rBin2L ; Restore the registers of 16-bit-binary 2
  pop rBin2H
  ret

von Axel S. (a-za-z0-9)


Lesenswert?

Stefan S. schrieb:
> Ich muss meine Daten 3 ASCII zeichen in ein Binärbyte umwandeln.

Das geht gar nicht. Ein ASCII Zeichen ist genau 8 Bits (vulgo: 1 Byte) 
lang. 3 Zeichen brauchen also auch 3 Bytes.

> Zum Beispiel: ich hab drei zeichen im SRAM stehen sram1: 2 Sram2: 5 sram
> 3: 4

Das sind keine Zeichen, sondern Zahlen. 2 ist eine Zahl. Das Zeichen '2' 
muß in einfache Anführungszeichen gesetzt werden. Und es entspricht dann 
der Zahl 50 (siehe https://de.wikipedia.org/wiki/ASCII-Tabelle)

> das würde dann einem Wert binär von 254 ergeben.

Auch wieder falsch. Das ist nicht binär, sondern dezimal. Die 
Dezimalzahl 254 besteht aus den Ziffern 2, 5 und 4 - in absteigender 
Wertigkeit.

Aber so langsam verstehe ich, was du erreichen willst. Auch wenn du 
selber das noch gar nicht verstehst. Du willst aus einem Array, das die 
Ziffern einer dreistelligen Dezimalzahl enthält, den Wert der Zahl 
ausrechnen.

Und dazu mußt du erst mal wissen, wie sich der Wert einer Dezimalzahl 
aus den einzelnen Ziffern ergibt. Dazu empfehle ich weitere 
Wikipedia-Artikel:

https://de.wikipedia.org/wiki/Dezimalsystem

Damit solltest du den direkten Weg für eine dreistellige Zahl 
hinschreiben können. Hinweis: es kommt eine Multiplikation mit 10 und 
eine mit 100 darin vor.

https://de.wikipedia.org/wiki/Horner-Schema

Das ist dann der bessere Weg für Zahlen mit einer variablen Anzahl 
Stellen. Es kommen nur noch Multiplikationen mit 10 vor. Und natürlich 
Additionen. Das oben gezeigte Programm verwendet diesen Ansatz.

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Du suchst das in Assembler?
Da wäre die Angabe des Prozessors nicht schlecht.
(Auch wenn die Profis das sicherlich erkennen)

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Stefan S. schrieb:
> Zum Beispiel: ich hab drei zeichen im SRAM stehen sram1: 2 Sram2: 5 sram
> 3: 4
> das würde dann einem Wert binär von 254 ergeben.

 Nein.
 Das würde einen Hex Wert von 0x452 ergeben oder Dezimal 1106.
 Binär kennt als Wert nur 0 oder 1.


> Wie muss ich den Z pointer jetzt einstellen damit er mir das umwandelt?
> und wie müssen die ASCII zeichen im SRAM abgelegt sein damit die
> berechnung hinterher stimmt ?

 Steht doch alles oben:

 sram1: 0x32    Sram2: 0x35    sram3: 0x34    sram4: 0x00
 Z => 0x0001  (zl = 1 / zh = 0)

 Und das Resultat ist danach in rBin1H:rBin1L
 0x00 : 0xFE

 P.S.
 Wobei die SRAM Adresse nicht 1 sein kann.
 SRAM fängt meistens bei 0x100 an.

: Bearbeitet durch User
von Stefan S. (buffalochill)


Lesenswert?

ich kenne schon den unterschied zwischen den datentypen... hatte mich 
nur verschrieben...

also sagen wir da drin steht als ascii dezimal:
sram3 : 50  Sram2: 53 Sram1: 52

umgerechnet wären dass dann quasi 254 dezimal und binär 0b01111111 wenn 
man sie zusammenreiht und das möchte ich...

aber nochmal zu der frage :
Wie muss ich den Z pointer jetzt einstellen damit er mir das umwandelt?
und wie müssen die ASCII zeichen im SRAM abgelegt sein damit die
berechnung hinterher stimmt ?

: Bearbeitet durch User
von Stefan S. (buffalochill)


Lesenswert?

Marc V. schrieb:
>
>  sram1: 0x32    Sram2: 0x35    sram3: 0x34    sram4: 0x00
>  Z => 0x0001  (zl = 1 / zh = 0)
>
>  Und das Resultat ist danach in rBin1H:rBin1L
>  0x00 : 0xFE
>
>  P.S.
>  Wobei die SRAM Adresse nicht 1 sein kann.
>  SRAM fängt meistens bei 0x100 an.


also wäre das zum testen so richtig ?

  ldi    temp, 53              ;ascii zeichen "4"
  sts    Sram_start+45, temp
  ldi    temp, 54              ;ascii zeichen "5"
  sts    Sram_start+46, temp
  ldi    temp, 50              ;ascii zeichen "2"
  sts    Sram_start+47, temp
  ldi    temp, 0               ;keine zahl als ascii
  sts    Sram_start+48

  ldi    ZH, 0
  ldi    ZL, Sram_start+45

  call          AscToBin2

  out    PortB, rBin1L

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Stefan S. schrieb:
> Wie muss ich den Z pointer jetzt einstellen damit er mir das umwandelt?
> und wie müssen die ASCII zeichen im SRAM abgelegt sein damit die
> berechnung hinterher stimmt ?

 So:
1
;******  Deinen Prozessor eintragen !!!  ******
2
.include  "m328pdef.inc"
3
;******  Deinen Prozessor eintragen !!!  ******
4
5
6
    .DSEG
7
sram1:    .byte   1
8
sram2:    .byte   1
9
sram3:    .byte   1
10
sram4:    .byte   1
11
12
LoByt:    .byte 1
13
HiByt:    .byte 1
14
    
15
    .CSEG
16
Init:
17
    ldi  zl, low(LoByt)   ;* Oder auch:    ldi  zl, low(sram4+1)
18
    ldi  zh, high(LoByt)
19
    clr  r16
20
    st  -Z, r16      ;* String endet normalerweise mit 0
21
    ldi  r16, 0x34
22
    st  -Z, r16      ;* '4'
23
    ldi  r16, 0x35
24
    st  -Z, r16      ;* '5'
25
    ldi  r16, 0x32
26
    st  -Z, r16      ;* '2'
27
    rcall  AscToBin2    ;* Z-Reg zeigt jetzt auf sram1
28
    sts  LoByt, rBin1L    ;* Als Kontrolle
29
    sts  HiByt, rBin1H
30
Eloop:
31
    rjmp  Eloop

: Bearbeitet durch User
von Stefan S. (buffalochill)


Lesenswert?

vielen Dank nochmal für die Hilfe es geht jetzt alles wunderbar :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.