Forum: Mikrocontroller und Digitale Elektronik BASCOM: Zeichenumwandlung nach Vorgaben aus einer Tabelle


von Max (Gast)


Lesenswert?

Hallo!

Ich habe ein Gerät, das eine eigene ASCII Tabelle verwendet zur 
Darstellung von Zeichen auf einem Bildschirm. Z.B. entspricht der 
Hexwert 00 dem Buchstaben "A" und nicht wie beim ASCII Zeichensatz dem 
Leerzeichen.

Jetzt habe ich einen String in BASCOM der so aussieht:

"TEST12345"

Diesen muss ich zerlegen und dann sollte jedem Char im String der 
entsprechende Hexwert der ASCII Tabelle des Gerätes zugewiesen werden.

T -> &H13
E -> &H04
S -> &H12
T -> &H13

Wie kann ich das mit Bascom realisieren?

Danke schonmal für die Antworten.

Max

von Karl H. (kbuchegg)


Lesenswert?

Max wrote:
>
> T -> &H13
> E -> &H04
> S -> &H12
> T -> &H13
>
> Wie kann ich das mit Bascom realisieren?

Mit einer Tabelle (Array)?

In einer Schleife, die über die Länge des Strings geht (Doku 
nachschauen, wie man in BACOM rauskriegt wieviele Zeichen in einem 
String enthalten sind): Für jedes Zeichen im String, isolierst du jedes 
Zeichen einzeln aus dem Eingabestring (Doku nachschauen, wie man bei 
BASCOM an einzelne Zeichen eines Strings rankommt). Jedes Zeichen wird 
als Index in die Tabelle genommen (Doku nachschauen, wie man ein Array 
dimensioniert und mit Werten füllt) und dort steht der Wert, der 
stattdessen zu verwenden ist. Diesen Wert nimmst du und schreibst in 
anstelle des ursprünglichen Zeichens in den String (Doku nachschauen, 
wie man in BASCOM ein Zeichen eines Strings auf einen bestimmten Wert 
setzt)

Summa Summarum: Bis auf den Teil: Du brauchst ein Array als 
Codeumsetzer, läuft fast alles auf Dokustudium hinaus. Und die Idee 
eines Array als Codeumsetzer, hattest du alleine auch schon :-)

(Im übrigen würde ich mal damit anfangen, die Doku zu studieren, ob es 
bestimmte Zeichen gibt, die man in BASCOM nicht in einen String packen 
kann. Wäre nämlich blöd, wenn sich hinterher dann rausstellt, dass das 
so gar nicht funktionieren kann, weil deine Umsetztabelle zu einem 
ungültigen Ergebnisstring führen wird.)

von Ralf S. (spacedog) Benutzerseite


Lesenswert?

Wenn die Zeichen in deinem selber kreierten Zeichensatz die selbe 
Reihenfolge haben, wie die Zeichen im ASCII, dann lässt sich deine 
Codewandlung durch eine Subtraktion erledigen.

von Max (Gast)


Lesenswert?

@Ralf
Die Reihenfolge ist leider nicht gleich der im ASCII Zeichensatz. Sonst 
wäre es ja auch zu einfach :-)

@Karl Heinz
Wie ich die Stinglänge rausbekomm weiß ich. Wie ich die einzelnen 
Zeichen aus dem String bekomme weiß ich auch. Aber den Rest hab ich 
nicht verstanden.

Was meinst du mit "Schleife die über die Stinglänge geht" ? Wenn ich die 
einzelnen Zeichen habe, wie sage ich BASCOM das aus A ein &H00 werden 
soll?

Danke!

Max

von Dominique G. (dgoersch)


Lesenswert?

Kann Bascom Arrays mit Key => Value-Paaren? Wenn ja einfach eine 
entsprechende Tabelle anlegen, vll auch in einem Data-Bereich um ein 
wenig Ram zu sparen...

von Null C. (yah996)


Lesenswert?

kleiner Tipp

Print Asc("a")

von Wigbert P. (wigbert) Benutzerseite


Lesenswert?

Hi,
Schau Dir mal den Befehl "Lookupstr" an.

Wigbert

von Karl H. (kbuchegg)


Lesenswert?

Max wrote:
> Hexwert 00 dem Buchstaben "A" und nicht wie beim ASCII Zeichensatz dem
> Leerzeichen.


Na, ja.
Das Leerzeichen hat zwar im ASCII Code einen ganz anderen Wert, aber 
seis drum.

Dein Problem besteht darin, dass BASCOM anscheinend, ähnlich wie C, 
seine Strings mit 0 abschliesst.
Und da dein Gerät bei einem 'A' den Code 0 sehen will, ist damit das 
ganze Konzept des 'einen String in einen anders codierten String zu 
verwandeln' schon mal den Bach runter.

Da wird dir nichts anderes übrig bleiben, als die Codeumsetzung direkt 
bei der Ausgabe an das Gerät zu machen. Das erscheint mir jetzt 
einfacher, als dich in eine 'Na dann wirds wohl nichts mit Strings, da 
müssen dann Arrays als Stringersatz herhalten'-Strategie zu jagen.

von Dominique G. (dgoersch)


Lesenswert?

Karl heinz Buchegger wrote:
> Da wird dir nichts anderes übrig bleiben, als die Codeumsetzung direkt
> bei der Ausgabe an das Gerät zu machen. Das erscheint mir jetzt
> einfacher, als dich in eine 'Na dann wirds wohl nichts mit Strings, da
> müssen dann Arrays als Stringersatz herhalten'-Strategie zu jagen.

Niemand will hier Strings durch Arrays ersetzen. Er will ein Mapping 
zwischen einem Zahlenwert und einem Buchstaben herstellen, das macht man 
nunmal über eine Tabelle, in fachkreisen dann auch Array genannt.

von Karl H. (kbuchegg)


Lesenswert?

Dominique Görsch wrote:
> Karl heinz Buchegger wrote:
>> Da wird dir nichts anderes übrig bleiben, als die Codeumsetzung direkt
>> bei der Ausgabe an das Gerät zu machen. Das erscheint mir jetzt
>> einfacher, als dich in eine 'Na dann wirds wohl nichts mit Strings, da
>> müssen dann Arrays als Stringersatz herhalten'-Strategie zu jagen.
>
> Niemand will hier Strings durch Arrays ersetzen. Er will ein Mapping
> zwischen einem Zahlenwert und einem Buchstaben herstellen, das macht man
> nunmal über eine Tabelle, in fachkreisen dann auch Array genannt.

Yep. Und blöderweise ist sein Mapping so, dass er das Ergebnis dieser 
Umsetzung in einem BASCOM String nicht mehr speichern kann, damit er es 
dann seiner vorgefertigten (UART)-Schreibfunktion übergeben kann, die 
den so umgemappten String zum Gerät überträgt.

von Max (Gast)


Lesenswert?

Hallo!

Habe es noch nicht ausprobiert aber würde es in etwa so funktionierten:

1
dim text as string*10
2
dim char(10) as byte
3
dim i as byte
4
dim index(10) as byte
5
6
text = "ABCDEFGHIJ"
7
i = 1
8
9
Do
10
11
  'Einzelne Chars aus String ziehen
12
  char(i) = mid(text , i , 1)
13
14
  'Char in Tabelle data1 suchen und den Index speichern
15
  index(i) = lookdown(char(i) , data1 , 1)
16
17
  'Wert von Index in Tabelle data2 suchen
18
  char(i) = lookup(index(i) , data2)
19
20
loop until i = 10
21
22
printbin char(1) ; char(2) ; char(3) ; ...
23
24
25
data1:
26
data "A" , "B" , "C" , "D" , "E" , ...
27
28
data2:
29
data &H00 , &H01 , &H02 , &H03 , ...

Max

von D. S. (jasmin)


Lesenswert?

Hallo,

ich empfehle die karo einfach Methode.

Den String zeichen für Zeichen auslesen.
Dann einfach in einer CASE Anweisung das Mapping von Istzeichen zu 
Sollzeichen durchführen und diese dann einfach seriell ausgeben.
Brühwarm ins Senderegister kopieren.

Das ist trivial und rasend schnell.


Natürlich mußt du noch ein wenig Logik reinbringen was Stringende etc. 
betrifft.

Das ist aber sehr einfach, keine Interrupts, DO Loop und fertig.

von Dominique G. (dgoersch)


Lesenswert?

Ohne es getestet zu haben, aber aus dem Bauch heraus bezweifel ich, dass 
Schleife und Lookup langsamer sind als ein CASE. Denn Case wird doch im 
Endeffekt auch nur in haufenweise Verschachtelte If's aufgelöst und wenn 
du z.B. nach dem letzten Zeichen suchst, durchläufst du jede einzelne 
Entscheidung...

Das obige Beispiel ist schon nicht schlecht, allerdings braucht man 
"index" nicht als Array, da dort immer nur ein Wert beim 
Schleifendurchlauf zwischengespeichert wird. Was oben noch fehlt ist 
eine Logik zur Erkennung des Stringende, damit man nicht auf feste 
Längen angewiesen ist.

von MWS (Gast)


Lesenswert?

Warum einfach, wenn's auch kompliziert geht ;-)

Untenstehender Code sollte das Gewünschte wirtschaftlich und schnell 
erledigen, allerdings nicht getestet.

Damit würde man z.B. nur Buchstaben umzuwandeln. Man könnte auch den 
kompletten alten Zeichensatz übersetzen, muss dann aber auch eine 
vollständige Lookuptabelle mit allen 256 Einträgen erzeugen. Für diesen 
Fall die mit Sternchen bezeichneten Codeteile weglassen.
1
Const Strl = 20                                             ' Länge des Strings
2
Const Orig_char_start = 64                                  ' Dezimalwert bei dem die alten Zeichen beginnen
3
Const Orig_char_end = 91                                    ' Dezimalwert bei dem die alten Zeichen enden
4
Dim String_in As String * Strl
5
Dim String_char(strl) As Byte At String_in Overlay
6
Dim Char_ctr As Byte , Char_val As Byte
7
8
Char_ctr = 0
9
Char_val = String_char(char_ctr)
10
11
While Char_val > 0
12
  If Char_val >= Orig_char_start And Char_val <= Orig_char_end Then       ' ***
13
    Char_val = Char_val - Orig_char_start                   ' ***
14
      String_char(char_ctr) = Lookup(char_val , New_char_val)
15
        Incr Char_ctr
16
          Char_val = String_char(char_ctr)
17
  End If                                                    ' ***
18
Wend
19
20
End
21
22
New_char_val:
23
Data 12 , 22 , 44 , 18 , 5                                  ' usw.

von MWS (Gast)


Lesenswert?

Sorry, Fehler bemerkt:

Incr Char_ctr

muss natürlich unmittelbar nach If/Then stehen, sonst gibt's 'ne 
Endlosschleife.

von MWS (Gast)


Lesenswert?

Nachtrag, die Zweite:
1
...
2
  End If                                                    ' ***
3
        Incr Char_ctr
4
          Char_val = String_char(char_ctr)
5
Wend
6
...

von gast (Gast)


Lesenswert?

Array Indexe beginnen bei Bascom - blöderweise - bei 1.

Char_ctr = 0
Char_val = String_char(char_ctr)

Gruß

Rolf

von Dominique G. (dgoersch)


Lesenswert?

Find ich auch immer wieder nervig, bei andern Basic-Derivaten kann man 
es manchmal wenigstens konfigurieren.

von MWS (Gast)


Lesenswert?

@gast:

Ja, Danke, Du hast recht, hatte ich einen Moment nicht dran gedacht.

Würde ja für den OP viel zu leicht, wenn man wirklich fehlerfreien Code 
liefern würde. :D

Problem ist einfach zu lösen, indem statt mit 0:

Char_ctr = 1

initiert wird, weitere Änderungen sind nicht notwendig.

von Max (Gast)


Lesenswert?

@MWS

Vielen Dank für deinen Code. Ich habe ihn getestet und soweit 
funktioniert er auch, allerdings komme ich mit der lookup tabelle nicht 
ganz klar.

Hier nochmal der Code:
1
Const Strl = 20                                             ' Länge des Strings
2
Const Orig_char_start = 64                                  ' Dezimalwert bei dem die alten Zeichen beginnen
3
Const Orig_char_end = 91                                    ' Dezimalwert bei dem die alten Zeichen enden
4
Dim String_in As String * Strl
5
Dim String_char(strl) As Byte At String_in Overlay
6
Dim Char_ctr As Byte , Char_val As Byte
7
8
Char_ctr = 1
9
Char_val = String_char(char_ctr)
10
11
While Char_val > 0
12
  If Char_val >= Orig_char_start And Char_val <= Orig_char_end Then       ' ***
13
    Char_val = Char_val - Orig_char_start                   ' ***
14
      String_char(char_ctr) = Lookup(char_val , New_char_val)
15
  End If                                                    ' ***
16
17
  Incr Char_ctr
18
  Char_val = String_char(char_ctr)
19
20
Wend
21
22
End
23
24
New_char_val:
25
Data 12 , 22 , 44 , 18 , 5                                  ' usw.

string_in ="AAAAAAAAAABBBBBBBBBB"

Ich habe testweise den Wert von char_val mit print char_val am UART 
ausgegeben und es erscheinen auch die Dezimalwerte 65 und 66 (jeweils 
10x).

Wie löse ich das mit der lookup tabelle?

Ich bekomme ja für ein "A" als char_val 65. Muss ich die Tabelle jetzt 
mit mindestens 65 Werten füllen, damit per lookup der Wert für "A" 
gefunden wird.

Vielleicht kannst Du mir nochmal ein kurzes Beispiel geben.
Folgende Hexwerte sollen den Chars entsprechen
A = &H00
B = &H01
C = &H02
...
1 = &H1E
2 = &H1F
3 = &H20
...

Danke schonmal.

von Martha (Gast)


Lesenswert?

Max wrote:
>Ich bekomme ja für ein "A" als char_val 65. Muss ich die Tabelle jetzt
>mit mindestens 65 Werten füllen, damit per lookup der Wert für "A"
>gefunden wird.

Kommt drauf an, welche Zeichen du alle darstellen willst.
Großbuchstaben gehen von dezimal 65 - 90, Zahlen von 48-57.
Wenn das alles ist und du es so machen willst wie oben beschrieben, 
fängst du in deinem Data mit dem char_val des kleinsten Wertes an, also 
mit der 0.
Dieses hat dann den Index 0, also musst du immer 48 vom Byte-Wert des 
Zeichens abziehen.
Dazu hat MWS das hier eingefügt:
1
Char_val = Char_val - Orig_char_start                   ' ***
wobei du

Const Orig_char_start = 64 abändern musst in

Const Orig_char_start = 65

weil Lookup widerum bei 0 anfängt

Wenn du sonst keine anderen Zeichen darstellen willst, kannst du auf das 
ganze Lookup und Data Zeugs verzichten und schreibst einfach:

Char_ctr = 1
While String_char(char_ctr) > 0
  If String_char(char_ctr) > 64 Then       ' ***
    Char_val = Char_val - 65                  ' für die Großbuchstaben
  else
    Char_val = Char_val - 48                  'für die Zahlen
  End If                                                    ' ***
  Printbin char_val;
  Incr Char_ctr
Wend

Gruß

Martha

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.