Forum: Mikrocontroller und Digitale Elektronik BCD über die Serielle Schnittstelle ausgeben


von Alex (Gast)


Lesenswert?

Hallo
Habe da ein kleines Problem. Ich möchte gern meine 16Bit Hex- Werte
über die Serielle Schnittstelle ausgeben.
Die Umwandlung habe ich schon realisiert und mir liegt jetzt meine
16Bit Zahl in den 3 (BCD gepackten) Registern BCD0,BCD1,BCD2 vor.
Aber wie übertrage ich jetzt dieses Format? Mit Text-strings usw. komme
ich ja klar aber hier habe ich so meine Probleme.
Muss ich BCD0 usw. nach und nach einfach nur in einen pointer laden und
dann dem UART übergeben oder wie stelle ich das an ???
Danke schonmal im Voraus...

Gruß Alex

von Rahul (Gast)


Lesenswert?

Ein Textstring ist doch auch nichts anderes als ein Feld von Byte...
Die Idee mit dem Pointer solltest Du in die Tat umsetzen. Übrigens sind
Pointer nur Speicherstellen, die Adressen beinhalten, die auf die
eigentlichen Daten weisen... fertigkluggeschissenhat

von Stefan (Gast)


Lesenswert?

Entweder Du lässt das mit den gepackten BCD und speicherst es gleich
beim Konvertieren als String (einfacher)

oder

Du machst einen Index-Zähler zusätzlich zum Ptr, der von 0-5 die 6
BCD-Nibbles anspricht. Ist aber relativ komplex und erreicht nur 3 Byte
Speicherersparnis gegenüber einem normalen String ...

oder

Du schreibst (suchst) Dir eine Funktion Hex-Out, die ein Byte als 2
Hex-Werte an den UART ausgibt. Die rufst Du nacheinander mit BCD0, BCD1
und BCD2 auf. Da in jedem Nibble eine Dezimalziffer 0-9 steht, sollte
Deine Dezimalzahl 6-stellig korrekt ausgegeben werden.

Stefan

von Hannes Lux (Gast)


Lesenswert?

Hallo Alex...

Warum über BCD wenn du HEX ausgeben willst?

Du hast 16 Bit-Werte, also 2 Byte bzw. 4 Nibbles (je 4 Bit).
Jedes Nibble (Halbbyte) wird durch eine Hex-Ziffer repräsentiert.

Isoliere nacheinander die Werte deiner Nibbles (höherwertigste zuerst),
prüfe, ob sie unter 10 sind, also ob es noch Ziffern (0...9) oder schon
Buchstaben (a...f) sind, schau in die ASCII-Tabelle um die Codes von
Ziffern und Buchstaben zu ermitteln und addiere den jeweiligen Offset
für Ziffern bzw. Buchstaben und du hast den ASCII-Wert, den du per
Schnittstelle versenden kannst. Und das nacheinander für alle 4
Nibbles...

Kleiner Tip: Für Ziffern wirst du wohl die Konstante 48 addieren
müssen, bei Buchstaben kommt es darauf an, ob sie groß oder klein
dargestellt werden sollen.

Viel Erfolg...
Bit- & Bytebruch... - ...HanneS...

von Stefan (Gast)


Lesenswert?

Ich nehme mql an, er will eine 16-Bit Zahl dezimal ausgeben
(0 .. 65.000)
Sonst würde er ja nicht auf 6 Ziffern (= 3 gepackte BCDs) kommen.

Stefan

von Rahul (Gast)


Lesenswert?

vermute ich auch.
Umd die aber auf einem PC auszugeben wäre es sinnvoll, sie in Ascii zu
wandeln, weil es sonst nur Steuerzeichen wären...
Der einfachste Weg wäre, BCD-Zahl + 48 zu rechnen, da das die
"ASCII-0" ist.

von Stefan (Gast)


Lesenswert?

gepackt-BCD ist aber nochmal was anderes. Da sind 2 Ziffern (0-9) in
einem Byte zusammengepackt (in jedem Nibble eines).

Wenn man ein solches Byte als Pseudo-Hexwert ausgibt, dann bekommt man
beide Ziffern korret angezeigt.

Stefan

von Rahul (Gast)


Lesenswert?

hmmm...
das mit den gepackten BCDs habe ich überlesen.
Natürlich hat man in diesem Fall eine saubere Darstellung der Zahlen.
Mich würde schon interessieren, an wen er die schickt.
Gute Nacht
Rahul

von Hannes Lux (Gast)


Lesenswert?

Hallo Rahul & Stefan...

Völlig korrekt, was ihr da schreibt, ich bezog mich aber auf den
allerersten Beitrag dieses Threads, da steht:

"Ich möchte gern meine 16Bit Hex- Werte
über die Serielle Schnittstelle ausgeben."

In den Registern oder im RAM stehen aber nunmal keine Hex-Werte,
sondern Bits oder Bytes, die im allgemeinen eine 16-Bit-Ganzzahl
darstellen. Hex ist ja nur eine Darstellungsform des Zahlenwertes in
ASCII-Text, genau wie dezimal, oktal oder binär.

Und da Alex seine "16-Bit-Hex-Werte" (also eine vierstellige
Hex-Zahl) an die serielle Schnittstelle schicken wollte, nahm ich an,
dass dies in Hex am besten geht. Gut, ich empfahl ihm nicht, ein
Trennzeichen [z.B. chr$(32) oder chr$(13)] hinterher zu schicken, da
sollte er selbst drauf kommen...

Mit besten Grüßen, Bit- & Bytebruch... - ...HanneS...

von Alex (Gast)


Lesenswert?

Danke für die vielen Antworten.
Ja ich habe mich etwas blöd ausgedrückt.
Ich möchte meine 16Bit Messwerte so umformen (also in BCD) das ich sie
über die Serielle Schnittstelle senden kann um später im Hyperterminal
meine Werte von 0 bis 65000 ablesen kann.

gruß alex

von Rahul (Gast)


Lesenswert?

Dann solltest Du sie nicht in Richtung BCD wandeln, sondern in
(ascii)-Text. Wenn Du gepackte BCDs an Hyperrterminal sendest, macht
der daraus Buchstaben und da kann es vorkommen, dass da nur wirres Zeug
steht. Hyperterminal ist leider zu doof, um gepackte BCDs zu erkennen.
Besser ist es entweder jede Ziffer als Ascii-Text zu übermitteln, oder
ein kleines Programm auf dem PC zu erstellen, das die BCDs wieder
entpackt. Die zweite Variante ist bei der Übertragung chneller, die
erste erfordert weniger Aufwand auf der PC-Seite.
Jetzt musst Du halt entscheiden, was du eher brauchst bzw. realiseren
kannst.
Gruß Rahul

von Alex (Gast)


Lesenswert?

Aha wieder was gelernt...
Ich dachte das ich mit der umwandlung nach BCD all diese Probleme aus
dem weg geräumt hatte aber naja. Jetzt mal ne andere Frage...
wie wandle ich denn meine Hex Zahl in ASCII-Text um ????

von Hannes Lux (Gast)


Lesenswert?

Wenn Ziffernanzeige mit Führungsnullen erwünscht ist, dann ist der
Schritt über BCD schon sinnvoll, bei knappen Registern auch über
gepackte BCD. Dann jedes Nubble isolieren, 48 dazu und ab zur Post...

Ganz so einfach ist es denn aber auch wieder nicht, denn man darf der
seriellen Schnittstelle das nächste Byte erst anbieten, wenn sie mit
dem Vorherigen fertig ist...

Bit- & Bytebruch... - ...HanneS...

von Rahul (Gast)


Lesenswert?

dazu kann man die Bytes ja auch in ein String / Array schreiben...Das
Senden würde dann per Interrupt geschehen.
Ich bin leider gerade im Moment mit was anderem (wesentlich
dringenderem) beschäftigt, sonst würde ich dir ein Programm in C
basteln.
Vielleicht guckst du mal in der Lib-c nach, ob da eine Funktion zur
Umwandlung von long (2Byte) in Text beschrieben ist.

von Alex (Gast)


Lesenswert?

Vielen Dank für das Angebot aber "C" ist nicht notwendig da ich mit
reinem Assembler Code programmieren möchte..
Was ist eigentlich mit "jedes Bit einzeln isolieren" gemeint?
oder besser aus gedrückt wie addiere ich zu jedem nibble die 48 und wie
übergebe ich dann die einzelnen nibbles der schnittstelle?

von Stefan (Gast)


Lesenswert?

Na wenn Du doch die Umwandlung in gepackte BCD schon hast, dann brauchst
Du doch nur noch eine Routine, die 3 Bytes als Hex-Wert bzw. 2 Ziffern
auf die Schnittstelle ausgibt.
Keine Angst, Du siehst nachher keine Hex-Zahl auf dem Terminal, sondern
Deine Dezimalzahl mit 6 Stellen.

Leider hast Du noch nicht verraten, welche CPU Du benutzt.

Ich mache sowas immer mit einer Tabelle, in der die 16 Hex-Ziffern
drinstehen, und nehme jeweils 1 Nibble zum Indizieren auf diese
Tabelle.

Hab Dir mal nen Code angehängt für eine NEC-CPU, für Atmel habe ich es
leider noch nicht.

hextab  db
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'

send_hex                ;auszugebendes Byte steht in A:
        push    HL
        push    BC
        mov     C,A
        ror     A,1
        ror     A,1
        ror     A,1
        ror     A,1
        and     A,#15
        movw    HL,#hextab
        mov     B,A
        mov     A,[HL+B]
        call    send_txd_char
        mov     A,C
        and     A,#15
        mov     B,A
        mov     A,[HL+B]
        call    send_txd_char
        pop     BC
        pop     HL
        ret

Stefan

von Hannes Lux (Gast)


Lesenswert?

Hi Alex...

Nicht Bits isolieren, sondern Nibbles...

Jedes deiner gepackten BCD-Bytes enthält doch 2 Ziffern...
Eine davon im oberen Nibble (Halbbyte), eine im Unteren.
Nun willst du daraus ASCII machen, aus jedem Nibble ein Zeichen.
Also musst du aus dem Byte das gewünschte Nibble erstmal isolieren.
Dies geht am besten, indem du es in ein Hilfsregister (temp) kopierst,
wenn du das obere Nibble brauchst, dann tauscht du die Nibbles
(swap tmp), wenn das gewünschte Nibble unten ist, blendest du die
oberen aus (andi tmp,15). Tmp hat nun den Wert der Ziffer, also 0...9.
Da du aber nicht die Ziffern als Wert senden willst addiert du den Wert
48 hinzu, wodurch der ASCII-Code der Ziffer gebildet wird. Dieses
kannst du dann an die serielle Schnittstelle senden.
Für ADD Konstante gibt es keinen Befehl, da hilft subi temp, (-48).

Falls du im PC-Terminal nicht nur unformatiert aufeinanderfolgende
Ziffern sehen willst, solltest du nach der Übertragung jeder Zahl ein
Trennzeichen schicken.

Da 6 Halbbytes (Nibbles) mit BCD hast, deine Zahl (0...65535) aber
maximal 5-stellig wird, solltest du überlegen, ob du die Ziffer mit der
höchsten Wertigkeit überhaupt sendest, sie ist eh 0...

Wenn du genügend Rechenzeit hast, also wenn dein AVR während der
Datenübertragung sowiso nix Anderes zu tun hat, dann bietet sich an,
auf Schleifen und UART-Interrupt zu verzichten und für jede Stelle der
Zifferbildung separaten Code zu schreiben, dabei vor jedem Senden auf
die Fertigmeldung des UART zu warten. Das dürfte am einfachsten
sein...


Viel Erfolg...
Bit- & Bytebruch... - ...HanneS...

von Alex (Gast)


Lesenswert?

Aha das war eindeutig..Damit dürfte ich klarkommen. Ich nutze jetzt
gleich mal die Gelegenheit um noch eine weitere Frage zu stellen die
ihr mir evtl. ebenfalls beantworten könnt.
Also wie ich bereits schon erwähnt habe, möchte ich meine erfassten und
berechneten Messwerte über das Hyperterminal ausgeben.
(in meinem Fall eine Drehzahl)
ich möchte vermeiden das im Hyperterminal, die sich ständig ändernden
Werte in neuen Zeilen dargestellt werden

bsp.
DREHZAHL  8000
DREHZAHL  7867     so nicht...!!!!!
DREHZAHL  7834
DREHZAHL  6578
...
...
usw.

Sondern immer an der gleiche position
in etwa so:

Drehzahl:  .......

ist das möglich ?
gibt es da ein Steuerzeichen im ASCII CODE welches dieses ermöglicht?
Ich hoffe ihr versteht was ich meine und bedanke mich für die doch so
zahlreichen Antworten.

Gruß Alex

von Hannes Lux (Gast)


Lesenswert?

Hi Alex...

Sorry, da kann ich dir nicht helfen, da ich Hyper-Terminal nicht nutze.
Ich selbst habe auch noch keine serielle Verbindung PC-AVR realisiert,
es war bisher nicht notwendig.

Probieren könntest du mal mit chr$(10), das ist der Code für
"Wagenrücklauf". Es kommt nun darauf an, wie das Terminalprogramm das
interpretiert...

Als ich mit einen AVR (AT90LS8535) (eigentlich mit der am AVR
angeschlossene Smart-Media-Karte) kommunizieren musste, realisierte ich
das mit einer Nibble-orientierten Schnittstelle über den Druckerport
und schrieb in QB (QuickBASIC für M$-DOS) mein eigenes
Transferprogramm, das von einem eigenen Windows-Programm (VB) als
"Treiber" aufgerufen wird. Naja, sind große Umwege, aber aus VB kann
ich den LPT nicht ansprechen, dazu bin ich noch zu doof. Und mit
GFA-BASIC konnte ich mich noch nicht anfreunden, mit VB und QB klappts,
mit GFA müsste ich total von vorn beginnen...

Aber vielleicht hat ja jemand Anderes Erfahrungen mit dem Terminal und
kann sich hier mal äußern...

Viel Erfolg...
Bit- & Bytebruch... - ...HanneS...

von Rahul (Gast)


Lesenswert?

Mit Hyperterminal habe ich auch ewig nicht mehr gearbeitet (gibt ja
eigentliche keinen Grund mehr, da es kaum noch Mailboxen gibt). Eine
Anwendung in VB ist mir geringem Aufwand möglich, sofern man damit
schon mal gearbeitet hat.
Die Position des Cursors bei Hyperterminal zu verändern ist schon ein
interessantes Problem, das mich an die C64er-Zeiten erinnert, wo man
die entsprechende Anzahl an Pfeiltasten in einem String angeben musste.
Da wurden die Sonderzeichnen (alle Zeichem im ASCII-Code <32) noch
mitgespeichert.
Ich bin mir nicht ganz sicher, aber es gab einen Code für einen
Rückschritt. Den müsste man nur entsprechend häufig anwenden (ca. fünf
mal), um wieder die Schreibpostion zu erreichen.
Zumindest hat das bei Mailboxen damals so in etwa funktioniert.
Es könnte sein, dass es der CR-Code (chr(13)) war, der ist aber eher
mit einem Wagenrücklauf zu vergleichen. Wenn ich mich recht erinnere,
gibt es bei Hyperterminal die Möglichkeit die zum Zeilenumbruch
notwendigen Befehle festzulegen. Dabei unterscheidet man zwischen LF
(Line Feed = Chr(10)), CR (carrige return = chr(13) und LF+CR, wobei
ein Linefeed dafür sorgt, dass das "Blatt" eine Zeile hochgeschoben
wird, aber die Spalte des Cursors beibehält. CR sorgt für einen
Wagenrücklauf, sprich: der Cursor wird an den Anfang der Zeile gesetzt.
Je nach Einstellung wird das "Blatt" dann noch eine Zeile
hochgeschoben oder halt nicht.
Irgendwo müsste ich noch eine ASCII-Übersicht haben, in der das
beschriebenist (Applesoft-Basic).
So, gute Nacht
Rahul

von Hannes Lux (Gast)


Lesenswert?

Hallo...

@Rahul: Stimmt 10 iss Zeile, 13 iss Rücklauf, hatte ich in der Eile
verwechselt, kommen ja bei M$ immer gemeinsam vor...
Übrigens komme ich nicht vom C64 sondern von seinem schwarzen Bruder,
dem Plus/4. Hatten aber den gleichen Zeichensatz. C64 war besser zum
Spielen, Plussi hatte besseres BASIC, beide waren für ihre Zeit große
Klasse. Einen Plussi benutze ich noch gelegentlich zum Brennen von
EPROMs...
Mit VB4 gelang es mir mal vor 7 Jahren nicht, einen Rolley-Diaprojektor
per V.24 sauber anzusprechen, mal ging es, mal nicht. Seitdem habe ich
es nicht wieder versucht. Inzwischen nutze ich auch VB6. Das probiere
ich aber bei Gelegenheit mal, ich muss mir mal einen Pegelwandler mit
MAX232 bauen, den ich an AVR-Schaltungen anstecken kann.


@Alex: Die Rücktaste ist chr$(8)...
Ich halte es aber für möglich, dass diese als "Klotz" dargestellt
wird. WINDOOF ist da manchmal etwas unflexibel.

Viel Erfolg...
Bit- & Bytebruch... - ...HanneS...

von Alex (Gast)


Lesenswert?

Danke nochmal für die Antworten..
Mein Programm läuft jetzt genauso wie ich es mir vorgestellt habe.
Das von mir gesuchte ASCII Steuerzeichen ist chr(8)..--> Hannes du
hattest recht.
Na denn bis zum nächsten Problem...



Gruß Alex

von Hannes Lux (Gast)


Lesenswert?

Hi Alex...

Mir greht es nicht ums "Rechthaben", bin selbst AVR-Anfänger.

Aber es freut mich, dass ich helfen konnte...

Viel Erfolg...

Bit- & Bytebruch... - ...HanneS...

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.