Routinensammlung und Gewusst-wie für Mikrocontroller
Hornerschema
Betrachtet wird hier die Anwendung zur Konvertierung von Zahlensystemen
und zur menschenlesbaren Zahlendarstellung.
0. Grundlagen
Die Zahlenkonvertierung in Zeichen ist eigentlich nicht schwer:
- Division durch 10
- Rest = Ziffer, ausgeben
- weiter mit Quotient bei Punkt 1, bis gleich Null.
Dummerweise entstehen dabei die Ziffern von rechts nach links.
Das mag für rechtsbündige Ausgabe in einen Speicherbereich
ganz zweckmäßig sein.
Zum Vertauschen der Reihenfolge wird gern der Stack verwendet,
so wie auch im ATmega-Beispiel (SendNumber) angegeben.
1. Vorzeichen - Glückssache?
Die Ausgabe negativer Zweierkomplementzahlen erfordert die Negation
der Zahl. Dummerweise existiert bei keinem bekannten Mikrocontroller
ein NEG-mit-Carry-Befehl, deshalb lässt sich NEG nicht kaskadieren,
und man muss „zu Fuß“ von Null subtrahieren. Deshalb das Makro negc:
.macro negc ;Register
ldi r16,0
sbc r16,@0
mov @0,r16
.endm
2. Feldbreite, führende Nullen
Führende Leerzeichen sorgen für rechtsbündige Ausgabe, und löschen ggf.
Zeichenmüll einer zuvor ausgegebenen Zahl.
Führende Nullen werden für Uhrzeit-Ausgaben sowie für Hexadezimalzahlen
gern verwendet.
3. Festkomma-Ausgabe
C-Programmierer verwenden oftmals Gleitkommazahlen nur für die Ausgabe
mit printf(). Make Program Look Big.
Clevere C-Programmierer geben Festkommazahlen schon so aus:
printf("%d,%u", Zahl/10, Zahl%10);
printf("%d,%02u", Zahl/100, Zahl%100); //usw.
Das Punkt-Komma-Problem wird gleich mit erschlagen.
Aber Vorsicht! Was passiert bei negativen Zahlen?
In der Regel ist Handarbeit angesagt.
Diese Vorgehensweise erspart das Einbinden einer Gleitkomma-Bibliothek,
wobei die printf-Unterstützung einen großen Teil ausmacht.
Division mit Rest - das macht die Ausgaberoutine sowieso.
Deshalb ist es besser, die Komma-Ausgabe nach oder in die Ausgabe
einzubauen.
4. ATmega-Implementation
Weil man's doch öfter braucht, habe ich einige Include-Dateien
zusammengestellt, mit denen man die typischen Problemchen
per Rückgriff lösen kann.
Um das Rad nicht jedesmal neu erfinden zu müssen
und trotz Low-Level (Assembler) voran zu kommen.
Die Ausgaberoutine SendNumber hat folgende Features:
- 32-bit-Ausgabe
- vorzeichenbehaftet, vorzeichenlos wählbar
- beliebige Zahlenbasis (2..35)
- Feldbreite angebbar (0..255)
- Breite für führende Nullen extra angebbar (0..15)
- Festkomma-Ausgabemöglichkeit, 0..15 Nachkommastellen
- Zwangs-Plus wählbar
- Geringer Übergabeaufwand: Parameter in 3 Bytes gepackt
- Von außen DEFINierbare Zeichen für Minus, Komma usw.
- Ausgabe-Ziel je nach
putchar-Routine
- Seiten-Einsprünge für häufige Parameter, bspw. SendNumberDez für Zahlenbasis 10
Einfach
.include "itoa.i90"
und anschließend
;R2..R5, R18, R19 laden
rcall SendNumberDez
aufrufen.
(Na gut, putchar muss noch irgendwo aufrufbar sein.)
haftmann#software, 22.12.2005