Forum: Mikrocontroller und Digitale Elektronik [C][AVR] - Speicherschonende long zu BCD Konversation


von Rubelus (Gast)


Lesenswert?

Ich bin auf der Suche nach einer Resourcenschonenden Möglichkeit aus 
einer 'unsigned long' Variablen eine BCD Variable zu erzeugen. Im Grunde 
eine ltoa Anweisung würde schon reichen, jedoch bietet dies mir mein 
MicroC nicht an.

Oder noch einfacher wäre dies zu berechnen, jedoch scheitere ich dann 
schon an einer dreistelligen zahl :D Bis zwei Stellen kann man ja 
einfach noch den HEX mit einer 6 addieren, dann hörts aber irgendwie 
schon auf.

Jemand was parat?!

Jede einzelne Stelle herrauszusubtrahieren ist wahrscheinlich nicht die 
feine Englische Art oder?!

von Frank B. (foobar)


Lesenswert?

Also was genau möchtest du denn jetzt? ltoa wandelt in dezimal um, aber 
nicht im BCD-Format (zwei Ziffern pro Byte, im high-nibble und 
low-nibble codiert), sondern als Zeichenkette.

Hier mal ein Beispiel aus einem meiner Programme, direkt mit Ansteuerung 
einer 7-Segment Anzeige:
1
void showNumber(long number)
2
{
3
  long tests[] = { 100000, 10000, 1000, 100, 10 };
4
  unsigned char i;
5
  for (i = 0; i < 5; i++) {
6
    unsigned char c = 0;
7
    long test = tests[i];
8
    while (number > test) {
9
      c++;
10
      number -= test;
11
    }
12
    ledSetDigit(i, c);
13
  }
14
  ledSetDigit(5, number);
15
}

Kann man noch eleganter und kompakter schreiben. Kommt ganz drauf an, ob 
dein Microcontroller auch Multiplikation oder Division kann und wie 
schnell es sein muß. Auf einem kleinen 16fxx'er PIC, mit einigem anderen 
drumherum, ist das schon wieder fast zu langsam (nur maximal ein paar Hz 
Anzeigerate, mit Division, statt der Tabelle).

von Rubelus (Gast)


Lesenswert?

Frank Buss schrieb:
> Also was genau möchtest du denn jetzt? ltoa wandelt in dezimal um, aber
> nicht im BCD-Format (zwei Ziffern pro Byte, im high-nibble und
> low-nibble codiert), sondern als Zeichenkette.

Ja im Grunde schon, jedoch ist ja bis 1-0-0-1 je nibble das BCD Format 
identisch mit dem Hex Format, also eine 9 ist im Hex auch eine 9 - 
zumindest im Low/High Nibble. Momentan wandel ich die Daten z.b. 12345 
als in ein Char Array um 1-2-3-4-5 und sende diese dann zur 
Anzeige/Treiber. Quasi so ähnlich wie es deine Lösung ist, (itoa macht 
ja im Grunde auch nichts anderes)

Jedoch frage ich mich halt ob man es auch errechnen kann...

von Frank B. (foobar)


Lesenswert?

Ja, bis 9 stimmt das schon, daß das mit dem Hex-Format im Low-Nibble 
identisch ist. High-Nibble sehe ich jetzt nicht, da "1" im High-Nibble 
ja schon 16 dezimal bedeutet. Was meintest du mit 6 addieren im ersten 
Posting?

Aber wenn du Rechenleistung zuviel hast, kannst du natürlich auch jede 
Ziffer direkt berechnen. Hier mal eine nicht so sinnvolle Umsetzung, 
aber zumindest auch mit Unterdrückung von führenden Nullen :-)
1
char* itoaMalAnders(long value)
2
{
3
  static char buf[10];
4
  int i = -1;
5
  for (int j = 8; j >= 1; j--) {
6
    int p = (int) powf(10.0f, (float) j);
7
    int digit = (value % p) / (p / 10);
8
    if (i < 0) if (digit || j == 1) i++;
9
    if (i >= 0) buf[i++] = digit + '0';
10
  }
11
  buf[i] = 0;
12
  return buf;
13
}

von Entwickler (Gast)


Lesenswert?

> Resourcenschonenden

Willst Du den Regenwald schützen? Trinkwasser sparen? Erderwärmung 
stoppen?

Du bist ein junger Mensch und hast offensichtlich eine gewisse Scheu in 
der Codesammlung oder hier im Forum nach Beiträgen zu suchen die älter 
als fünf Jahre sind. Da wurde das Thema schon hinreichend verkaut. Die 
kürzeste Wandlungszeit betrugt 0,3761µs.
Ist es das, was Du suchst?

von Falk B. (falk)


Lesenswert?


von Frank B. (foobar)


Lesenswert?

Falk Brunner schrieb:
> Siehe Festkommaarithmetik

Ist aber noch verbesserungsfähig. Warum werden die führenden Nullen 
nicht direkt bei der Konvertierung unterdrückt? Ein ziemliches Gemurkse, 
erstmal prüfen, ob das Vorzeichen da ist, dann die folgenden führenden 
Nullen unterdrücken und dann erst die Ziffern ausgeben. Das ganze 
braucht man dann auch noch redundant je nach Ausgabekanal.

von Falk B. (falk)


Lesenswert?

@  Frank Buss (Firma: IT4 Systems GmbH & Co. KG) (foobar)

>> Siehe Festkommaarithmetik

>Ist aber noch verbesserungsfähig. Warum werden die führenden Nullen
>nicht direkt bei der Konvertierung unterdrückt?

Lies den Artikel. Ausserdem geht es um Lehrzwecke, nicht die 1001. Kopie 
eines ultrakompakten printf().

MFG
Falk

von 900ss (900ss)


Lesenswert?

Frank Buss schrieb:
> Was meintest du mit 6 addieren im ersten
> Posting?

Er meint vermutlich, direkt BCD-Arithmetik. Z.B. bei der Addition zweier 
BCD-Zahlen muß jedes Nibble evtl. mit 6 addiert werden um eine 
BCD-Korrektur durchzuführen. Viele Mikrocontroller bieten einen 
Assembler-Behehl für die BCD-Korrektur an (für BCD Arithmetik). Das 
ganze in 'C' zu machen ist aber mehr als unnötig.

Beispiel:

  0x09  BCD 9
 +0x03  BCD 3
------
 =0x0C  <-- Fehler, kein BCD Wert mehr
 +0x06  BCD Korrektur
------
 =0x12  Ergebnis wieder BCD

von eProfi (Gast)


Lesenswert?

Wenn man Rubelus' letzten Beitrag ansieht, weiß man, dass eigentlich gar 
kein BCD notwendig ist.
Beitrag "Mal wieder: C, AVR und das Bitshiften"

Nimm Peter Daneggers Ausgaberoutine und sende jeweils 4 Bits auf einmal.
Dann sparst Du Dir das kompaktieren von 2 Digits in ein Byte..

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.