Forum: Mikrocontroller und Digitale Elektronik ADC-Wert auf 4 7-Segmentanzeigen darstellen ohne viel Rechenleistung


von Martin (Gast)


Lesenswert?

Hey Leute,

ich benötige mal eine kleine Hilfe bzgl. der Ansteuerung einer 7 
Segmentanzeige.

Konkret möchte ich den Wert der vom ADC (0-1023) eingelesen wird auf 4 
7-Segmentanzeigen ausgeben.

Jetzt habe ich Beispiele gesehen, wo der eingelesene Wert mittelels 
Modulodivision in Tausender-, Hunderter-, Zehner- und Einerstellen 
zerlegt wird und diese dann auf an Display gesendet werden.

Dies kostet allerdings Rechenleistung und Zeit

Daher meine Frage:
Könnte man nicht einfach den ADC Wert in ein Array einlesen und dann 
einfach die ensprechenden Felder des Arrays an das Display senden und 
sich die ganze rechnerei sparen oder habe ich da einen Denkfehler?

Und, wie müsste man dies programmieren. Über ein Beispiel wäre ich sehr 
Dankbar, da sich meine Programierfähigkeiten noch in Grenzen halten.

Falls ich auf dem falschen Dampfer bin, hat jemand vielleicht einen 
anderen Lösungsansatz parat, der die ganze Rechnerei überflüssig macht?

Gruß Martin

von H.Joachim S. (crazyhorse)


Lesenswert?

Das braucht nur lächerlich wenig Rechenleistung.
Und wenn du dir Umrechnerei im MC zu aufwändig ist (binär und dezimal 
passen nun mal nicht gut zusammen) bau dir eine Hex-Anzeige und rechne 
im Kopf um :-).
3E8 sind übrigends 1000 :-)

von Stefan S. (chiefeinherjar)


Lesenswert?

Und wie willst du die einzelnen Zahlen trennen, um sie in ein Array zu 
schreiben?

Dass die Modulo-Operationen zu langsam sind und zu viel Speicher 
verbrauchen glaube ich dir nicht.

Du musst ja nur alle XXX Millisekunden mal ein  Update des Displays 
machen - und nur dann musst du die Zahlen umrechnen.

Einerseits sagst du, dass du vom Programmieren wenig Ahnung hast, 
andererseits meinst du beurteilen zu können, ob diese Lösung zu 
rechenintensiv ist - irgendwie passt das nicht. Wenn, dann liegt die 
Ursache für Probleme garantiert woanders in deinem Code.

von Martin (Gast)


Lesenswert?

OK, dann war der Gedanke halt falsch und ich mach es halt doch mit 
Division. Wollte ja nur wissen, ob es eine bessere Lösung gibt.

von Sascha_ (Gast)


Lesenswert?

"
Daher meine Frage:
Könnte man nicht einfach den ADC Wert in ein Array einlesen und dann
einfach die ensprechenden Felder des Arrays an das Display senden und
sich die ganze rechnerei sparen oder habe ich da einen Denkfehler?"

Tjo, dann tust du den Integer in ein Array:

adc_wandlungen[0] = ADC; //Vom Typ uint16

und das sind dann 10 Bits die entweder 0 oder 1 sein können.

Wie du jetzt ohne Umwandlung vom Binär- auf das Dezimalsystem kommen 
willst sodass man diese Zahl dann auf den 7seg Anzeigen lesen kann: Der 
Vorgang nennt sich Magie.
Binär und Dezimal sind halt komplett unterschiedliche Dinge, daher 
braucht man eine Umwandlung.

Du kannst alternativ auch boolesche Algebra bemühen wenn dir Modulo 
Aufrufe zu teuer sind. Ob das dann weniger Rechenleistung kostet ist 
fraglich, mit ziemlicher Sicherheit wird sich das simple Problem dann 
von wenigen Zeilen auf mehrere DINA4 Seiten aufblähen.

von Noch einer (Gast)


Lesenswert?

Im Prinzip ist da schon was dran. Frühere Generationen hatten sich mit 
BCD-Code rumgeärgert, um die Division einzusparen. Ist man von 
abgekommen. Bei den Hardwarepreisen lohnt sich der Aufwand nicht mehr.

Ausserdem sind die Compiler inzwischen so gut; für Divisionen mit 
Konstanten puzzlen die den optimalen Maschinencode zusammen.

von Michael B. (laberkopp)


Lesenswert?

Martin schrieb:
> Dies kostet allerdings Rechenleistung und Zeit

Oje oje, wie schnell kannst du denn gucken ?
Erkennt dein Auge mehr als 32000 Zahlen pro Sekunde ?

> Daher meine Frage:
> Könnte man nicht einfach den ADC Wert in ein Array einlesen

Einlesen, was soll hier einlesen ? Ein Indexwert ist es, also 
indizieren.

> und dann
> einfach die ensprechenden Felder des Arrays an das Display senden und
> sich die ganze rechnerei sparen oder habe ich da einen Denkfehler?

Klar kann man, wenn man einen uC mit 4k Speicher hat.

Der ewige space vs. speed tradeoff, man tauscht Rechenzeit durch 
vorausgerechnete Tabellenwerte.
1
char bcd[1024][4]=
2
{
3
    {0,0,0,0},
4
    {0,0,0,1},
5
    :
6
    {1,0,2,4}
7
};
8
9
  x=AnalogRead(0);
10
  digit3=bcd[x][0];
11
  digit2=bcd[x][1];
12
  digit1=bcd[x][2];
13
  digit0=bcd[x][3];

Sinnvoll ist das sicher nicht, bei der langsamen Beobachtungsgabe hat 
der uC 1 Million Befehle übrig um den Analogwert in Ziffern zu wandeln, 
da kann man sogar gnadenlos zählen statt dividieren.
1
  x=AnalogRead(0);
2
  digit[0]=digit[1]=digit[2]=digit[3]=0;
3
  while(x-->0) for(i=0;++digit[i]>9;i++) digit[i]=0;
Das dürfte dann der Code mit dem geringsten Speicherbedarf sein.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Martin schrieb:

> OK, dann war der Gedanke halt falsch und ich mach es halt doch mit
> Division. Wollte ja nur wissen, ob es eine bessere Lösung gibt.

Die gibt es tatsächlich. Im Prinzip geht es um eine Wandlung der rein 
binär codierten Darstellung einer Zahl in eine BCD-Darstellung. Dafür 
gibt es hochoptimierte Asm-Routinen, die das in einem klitzekleinen 
Bruchteil der Zeit einer dümmlichen Implementierung in Plain-C 
erledigen.

Das "Problem" ist nur: Das ist für deine Anwendung überhaupt nicht 
relevant. So schnell, wie du das Ergebnis vom Display ablesen kannst, 
kann das der Controller mit Links und 40 Fieber die Wandlung in eine 
BCD-Darstellung erledigen, selbst wenn er nur mit 32kHz Takt läuft (z.B. 
mit einem Uhrenquarz als Taktgeber) und die dümmstmögliche 
C-Implementierung des Algorithmus ackert...
Im Gegenteil: Deine nächste Frage würde dann sowieso sein: Wie sorge ich 
dafür, daß es in der letzten Stelle nicht so schrecklich wackelt, das 
Geflimmere kann ja keiner ablesen...

Sprich: du darfst das Pferd nicht vom Schwanz aufzäumen. Sinnvolle 
Aktualisierungsraten eines 7-Segment-Displays liegen so bei etwa 2Hz, 
wesentlich schneller kann nämlich kein Mensch das angezeigte Zeug 
erfassen. Die Wandlung in das Anzeigeformat muss also höchstens zwei mal 
pro Sekunde erfolgen und nicht so oft, wie du den Messwert gewinnst. 
Wobei dann sowieso noch zu klären wäre, ob die gewählte Samplerate für 
die Messung überhaupt sinnvoll ist, aber das ist schon wieder ein ganz 
anderes Thema...

von Noch einer (Gast)


Lesenswert?

>Dafür
>gibt es hochoptimierte Asm-Routinen, die das in einem klitzekleinen
>Bruchteil der Zeit einer dümmlichen Implementierung in Plain-C
>erledigen.

Dürfte wohl nur wenige Programmierer geben, die so eine trickreich 
optimierte Division hinbekommen:

https://blog.fefe.de/?ts=a922623d

von Martin (M.) (Gast)


Lesenswert?

Sind nicht die LEDs deutlich langsamer als die modulo Berechnung?

von Time to Live (Gast)


Lesenswert?

Martin schrieb:
> Könnte man nicht einfach den ADC Wert in ein Array einlesen und dann
> einfach die ensprechenden Felder des Arrays an das Display senden und
> sich die ganze rechnerei sparen oder habe ich da einen Denkfehler?

Kein Denkfehler, das kann man so machen.

Allerdings ist bei kleinen Controllern der Speicherplatz ohnehin meist 
knapp. Aber wenn du davon genug hast, warum nicht?
Man kann theoretisch sogar direkt die 7-Segment Darstellung ins Array 
packen 3x7 + die Eins = 22Bit pro Feld. Praktisch eher 3 x 8 Bit und die 
dann direkt auf 3 Ports raus, wenn man diese denn frei hat.
Schön! Kein Multiplexgedöns, keine schwierige Rechnerei, alles schön 
glatt und übersichtlich. Bau das doch so, egal was hier noch für "Profis 
auftauchen".
Man muß auch mal etwas anderes tun als nur dem Mainstream zu folgen. 
Jeder programmiert so wie er es für richtig hält und am schnellsten ans 
Ziel kommt, einzig das Ergebnis zählt.
Auch lustig ist natürlich die Idee mit dem Zählen von Laberkopp...

von H.Joachim S. (crazyhorse)


Lesenswert?

Time to Live schrieb:
> Auch lustig ist natürlich die Idee mit dem Zählen von Laberkopp...

das dürfte sich auch mit damit
https://de.wikipedia.org/wiki/Brainfuck
gut programmieren lassen

von Time to Live (Gast)


Lesenswert?

H.Joachim S. schrieb:
> das dürfte sich auch mit damit
> https://de.wikipedia.org/wiki/Brainfuck
> gut programmieren lassen

Jaja, mein Post war sooo ironisch nicht gemeint... Habe etwas in der art 
nämlich vor vielen vielen Jahren in Hardware zusammengetüddelt.
Seinerzeit ist mir ein wirklich wunderschönes ic BURR-BROWN ADC80 
zugelaufen dem ich mangels anderer Ideen unbedingt ne 7-Segmet Anzeige 
spendieren wollte. Also die 12 Bit in 3 74193 laden, bis 0 abwärts 
zählen und mit gleichen Takt 4 74192 aufwärts zählen lassen...et voilà! 
Daher meine Sympathie für exentrische Ideen;-)

von H.Joachim S. (crazyhorse)


Lesenswert?

Damit rennste bei mir offene Türen ein...
Aber es ist sicher nicht die richtige Idee für jemanden, der Angst davor 
hat, dass 3 läppische Divisionen die performance seines MC ins 
unterirdische abgleiten lassen .

von Lurchi (Gast)


Lesenswert?

Wenn man die Division nicht mag, kann man die Wandlung auch mit 
Multiplikationen machen:
Erst den ADC wert passend skalieren, das der Wert für die oberste Ziffer 
oben steht (z.B. oberstes byte, obere 4 Bits) und dann für die weiteren 
Stellen jeweils die oberen Bits Löschen und den Rest mit 10 
Multiplizieren, so dass dann die nächste Stelle nach oben kommt.

Bei der ersten Multiplikation gibt es ggf. einen kleinen Rundungsfehler, 
der aber auch nicht größer ist als bei einer normalen Skalierung mit 
einem krummen Wert, etwa von der Umrechnung der Ref. Spannung oder 
Taktfrequenz.

Das kann vor allem dann hilfreich sein, wenn der µC Hardware 
Multiplikation kann, oder eine Multiplikations-routine sowieso schon da 
ist.

von m.n. (Gast)


Lesenswert?

Man kann die Wandlung auch ohne Division erledigen, indem man 
wiederholte Subtraktionen ausführt. Ein Beispiel für eine max. 
6-stellige Zahl:

// Wandelroutine bin -> String
void long2a(int32_t l, int8_t *s, int8_t nachkomma)
{
uint32_t tab[] = {100000, 10000, 1000, 100, 10, 1};
uint32_t temp;
int8_t i = 0, j , n = (sizeof(tab)/sizeof(tab[0])-nachkomma);

    if(l < 0) {
      l = -l;
      *s++ = '-';
    }
    while((i < n-1) && (tab[i] > l)) {
      i++;
    }
    do {
      if(i == n) {*s++ = '.';}
      temp = tab[i];
      j = '0';
      while(l >= temp) {
        j++;
        l -= temp;
      }
      i++;
      *s++ = j;
    } while(temp > 1);
    *s = 0;                               // String abschließen
}

c-hater schrieb:
> Sinnvolle
> Aktualisierungsraten eines 7-Segment-Displays liegen so bei etwa 2Hz,
> wesentlich schneller kann nämlich kein Mensch das angezeigte Zeug
> erfassen.

Zum einen kann ein Mensch deutlich schneller ablesen und zum anderen 
bestimmen die Anforderungen, was sinnvoll ist.
Kürzlich wollte jemand bei einer Hochgeschwindigkeitskamera mit bis zu 
400 Bildern/s die Zeit nebst Bildnummer (frame) einblenden. Da muß die 
Wandlung erheblich schneller passieren. Gleiches gilt, wenn die 
BCD-Daten z.B. an einen PC übertragen werden sollen.

von Harald W. (wilhelms)


Lesenswert?

Michael B. schrieb:

> da kann man sogar gnadenlos zählen statt dividieren.

Das könnte man sogar in Hardware ganz ohne uC machen:
Ein Binärzähler wird mit dem AD-Wert geladen und zählt
mit einem festen Takt bis Null. Mit diesen Impulsen
lässt man einen BCD-Zähler mit 7-Segment-Ausgang hoch-
zählen. Das könnte man z.B. mit 4000-ICs mehrmals in
einer Sekunde machen

von m.n. (Gast)


Lesenswert?

Harald W. schrieb:
> Das könnte man z.B. mit 4000-ICs mehrmals in
> einer Sekunde machen

4000? Das sind aber ganz schön viele ;-)

von Harald W. (wilhelms)


Lesenswert?

m.n. schrieb:
> Harald W. schrieb:
>> Das könnte man z.B. mit 4000-ICs mehrmals in
>> einer Sekunde machen
>
> 4000? Das sind aber ganz schön viele ;-)

Naja, damit kann man eine 1000-stellige 7-Segment-Anzeige bauen.

von Jobst M. (jobstens-de)


Lesenswert?

In C ist das sicherlich nicht der erste Weg. Aber in C würde ich die 
Frage auch gar nicht stellen.
Für Assembler ist das die Lösung:
https://en.wikipedia.org/wiki/Double_dabble


Gruß

Jobst

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Time to Live schrieb:
> Man muß auch mal etwas anderes tun als nur dem Mainstream zu folgen.

Wie wärs damit:
Ein 10-bit ADC mit parallelem Ausgang wird an Adresse A2 - A12 eines 
EPROM/Flash Speichers gelegt, in dem die passenden 7-Segment Muster als 
4er Gruppen programmiert wurden, und an A0-A1 kommt ein Zähler bis 4 
(0b00 - 0b11) der die 4 Digits durchklappert und die Digits 
durchschaltet. Der Datenausgang des EPROM geht an die 7 Segmente der 
Multiplex Anzeige. Sollte recht einfach aufzubauen sein und braucht auch 
keinen Assembler :-P
Der Gehirnschmalz liegt in den EPROM Mustern, das sollte aber zu 
automatisieren sein.
Allerdings sind 16kB EPROMs/Flashs nicht üblich, also einen 32k nehmen 
und A13 als Umschalter auf einen andere Darstellung nehmen oder 
totlegen.

: Bearbeitet durch User
von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Martin schrieb:
> Dies kostet allerdings Rechenleistung und Zeit

Hm, ist das eine Vermutung von dir, oder hast du das irgendwo gehört / 
gelesen?

von Peter D. (peda)


Lesenswert?

Martin schrieb:
> Dies kostet allerdings Rechenleistung und Zeit

Ein AVR läuft ab Werk mit 1MHz, da ist das bissel Rechnen nur wenige 
Promille CPU-Last.
Selbst wenn Du alles in float rechnest, wirst Du nicht in der Lage sein, 
es so schnell abzulesen.
Du mußt absichtlich noch Delays einfügen, damit es nicht flackert. Ich 
nehme dafür 200ms Delay (= 5 Messungen/s).

von Harald W. (wilhelms)


Lesenswert?

Matthias S. schrieb:

> Allerdings sind 16kB EPROMs/Flashs nicht üblich, also einen 32k nehmen
> und A13 als Umschalter auf einen andere Darstellung nehmen oder
> totlegen.

Oder statt BCD gleich 7-Segment ausgeben.

von m.n. (Gast)


Lesenswert?

Matthias S. schrieb:
> Wie wärs damit:
> Ein 10-bit ADC mit parallelem Ausgang
....

Ich glaube, Du bist so jung, daß Du das nie machen mußtest.
10 Bit ADC mit Parallelausgang? Ein Ferranti ZN432? Oder womöglich ein 
Flash-Wandler mit 10 ns?
Bitte nicht!

Dann schon lieber ein ATtiny25/45/85 mit serieller Datenausgabe auf 
Schieberegister.

von Noch einer (Gast)


Lesenswert?

> Oder statt BCD gleich 7-Segment ausgeben.

Oder statt Mikrocontroller einen ADC für Voltmeter nehmen :-)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Harald W. schrieb:
> Oder statt BCD gleich 7-Segment ausgeben.

Habe ich doch geschrieben - ins EPROM/Flash kommen direkt die 7-Segment 
Daten, nix BCD oder so.

m.n. schrieb:
> Ich glaube, Du bist so jung, daß Du das nie machen mußtest.

Im Gegenteil, ich bin so alt, das ich früher oft mit Parallelwandlern zu 
tun hatte. Und das waren dann z.B. ADC0844/0848, ADC7802 oder im 
Videobereich der AD9048.
Und es ging ja darum, das mit so wenig Rechenleistung wie möglich zu 
machen - voila, das ist die Lösung ganz ohne MC.
Hier ein paar aktuelle 10-Bit ADC mit Parallelausgang:
TI:
http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=slas170&fileType=pdf
AD:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7938_7939.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/AD7938_7939.pdf

: Bearbeitet durch User
von Paul B. (paul_baumann)


Lesenswert?

Matthias S. schrieb:
> Habe ich doch geschrieben - ins EPROM/Flash kommen direkt die 7-Segment
> Daten, nix BCD oder so.

Genau so.
Ich habe das vor Jahrzehnten schon für mehrere Temperaturanzeigen in 
einer Galvanik so gemacht. Die Eproms mit ihren Adressleitungen auf den 
AD-Wandler und auf den Datenleitungen direkt 7-Segment Code ausgegeben. 
Dann noch ein paar Leitungstreiber dran, weil die Eproms nicht "bullig" 
genug waren, die Anzeigen selber anzusteueren. Der Einzige, der rechnen 
mußte, war ich (vorher, für die Tabelle in den Eproms)

MfG Paul

von m.n. (Gast)


Lesenswert?

Matthias S. schrieb:
> Und es ging ja darum, das mit so wenig Rechenleistung wie möglich zu
> machen - voila, das ist die Lösung ganz ohne MC.

Du meinst also den ICL7106/07.

> Hier ein paar aktuelle 10-Bit ADC mit Parallelausgang:

'aktuelle' bitte durch 'teure' ersetzen ;-)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

m.n. schrieb:
> Du meinst also den ICL7106/07.

Nein, den meine ich nicht. Mit der alten Schüssel kannst du mir nicht 
mehr kommen. Steinzeit, langsam und keine 4 Stellen. Du denkst eben 
einfach zu konventionell und es ging ja um 'Denken ausserhalb der 
Kiste'.

Nur, weil du keine Parallelwandler einsetzt, heisst das nicht, das der 
Rest der Welt es auch nicht tut.

von Peter D. (peda)


Lesenswert?

Matthias S. schrieb:
> Und es ging ja darum, das mit so wenig Rechenleistung wie möglich zu
> machen

Nö, es ging darum, daß der OP fälschlicher Weise dachte, das kleine 
bischen Rechnen würde eine merkbare CPU-Last ausmachen.

von m.n. (Gast)


Lesenswert?

Matthias S. schrieb:
> Nur, weil du keine Parallelwandler einsetzt, ...

... biete ich zu Versandkosten einige AD574AKN und AD667JN an.
Die sind nach 30 Jahren gut gereift ;-)

von Stefan F. (Gast)


Lesenswert?

Besser lesbar ist das:
1
char buffer[6];
2
sprintf(buffer,"%u",adcvalue);

Aber das ist auch die uneffizienteste Lösung, printf() ist ein Monster. 
Andererseits, wenn du ohnehin auch an anderen Stellen printf gebrauchen 
kannst, ist es unterm Strich betrachtet gar nicht mal so verkehrt.

Abgesehen davon: Scheiß auf Effizienz, solange das Programm tut was es 
soll und in den Speicher passt. Die gesparte Zeit kann man woanders 
gewinnbringender einsetzen.

Ich muss jeden Tag in Java programmieren, mit SOAP und dreifachen 
Datenbank-Abstraktionslayern. Da habe ich mir das feilschen um Effizienz 
abgewöhnt. Ich müsste meine Werke sonst ununterbrochen beweinen.

Ansonsten: utoa() ist eventuell ein heißer Tip.

von Christoph db1uq K. (christoph_kessler)


Lesenswert?


von Wolfgang (Gast)


Lesenswert?

Martin (M.) schrieb:
> Sind nicht die LEDs deutlich langsamer als die modulo Berechnung?

Eher nicht. Die Schaltzeit der LEDs dürfte im sub-µs-Bereich liegen. ;-)

Wie lange die Modulo Operation dauert, hängt sicher davon ab, welcher µC 
dafür eingesetzt wird, insbesondere, ob sie durch die Hardware 
unterstütz wird.
Allerdings ist die Modulo-Berechnung u.U. ganz überflüssig, wenn man 
statt dessen mit Subtraktionen arbeiten und sich von den Tausendern zu 
den Einern durcharbeitet.

von eProfi (Gast)


Lesenswert?


von Michael B. (laberkopp)


Lesenswert?

Stefan U. schrieb:
> Da habe ich mir das feilschen um Effizienz
> abgewöhnt. Ich müsste meine Werke sonst ununterbrochen beweinen

Na ja, so ist es die Kundschaft, die jeden Tag erneut die grottenlahmen 
Programme beweint.

Kollektive übereinstimmende Menung gerade beim grossen Essenstisch: alle 
jammerten daß WebSeiten von Onlinezeitschriften und Smartphone Apps auch 
von Google wie z.B. Google Maps inzwischen allesamt eine Zumutung sind 
und wegen Langsamkeit weitgehend unbrauchbar.

von Stefan F. (Gast)


Lesenswert?

Leider durfte ich in 30 Jahren nur einmal die gute Qualität abliefern, 
die ich mochte.

In der Realität zählt eher: Schnell gemacht und möglichst billig. Je 
billiger du eine Software entwickelst, umso mehr wir deine Leistung vom 
Geldgeber gewürdigt - sofern sie denn die Anforderungen erfüllt.

Qualität bezahlt kaum jemand. Wenn du mal einen Murks-Code refactorn 
willst, musst du es entweder einfach heimlich machen (und einen riesen 
Anschiss riskieren) oder den Geldgeber mühsam vom Sinn der Aktion 
überzeugen. "Läuft doch schon" ist schwer, mit Argumenten zu überbieten.

Das Problem trifft Handwerker sicher ebenso.

von W.S. (Gast)


Lesenswert?

Martin schrieb:
> Jetzt habe ich Beispiele gesehen, wo der eingelesene Wert mittelels
> Modulodivision in Tausender-, Hunderter-, Zehner- und Einerstellen
> zerlegt wird und diese dann auf an Display gesendet werden.

In der vagen Hoffnung, daß nach all den Diskussionen der TO hier 
überhaupt noh mitliest, sag ich man folgendes:

Die Rechnerei mit Modulo geht extrem gut bei Architekturen, die über 
eine Hardware-Division verfügen. Ist dem nicht so, wie z.B. auf allen 
üblichen 8 Bit Architekturen, macht man es eben auf die Weise, die wir 
mal alle in der Schule gelernt haben.

Also: so oft 1000 abziehen, bis Zahl eben noch nicht kleiner als 0 ist, 
Anzahl merken. Das ist die 1000er Stelle.

Dann dasselbe mit 100, dann mit 10, dann der Rest ist die Einerstelle.

ist doch simpel und kommt mit ein paar einfachen Subtraktionen und 
Additionen aus.

Das Umsetzen so einer Stelle in ein Bitmuster für die 7 Segment-Anzeige 
macht man mit einer kleinen Tabelle. Wie die aufgebaut ist, hängt von 
der Beschaltung ab.

So. und jammert nicht, wenn ihr bei eurem System kein sprintf findet. 
Ist in 99.9% aller Fälle überflüssig. Ich halte nichts von Leuten, die 
ohne vorgekaute printf Bibliotheken auf dem Schlauche stehen und selber 
ne einfache Konvertierung nicht zuwege bringen.

W.S.

von hinz (Gast)


Lesenswert?

Stefan U. schrieb:
> "Läuft doch schon" ist schwer, mit Argumenten zu überbieten.
>
> Das Problem trifft Handwerker sicher ebenso.

Insbesondere Automechaniker, die dürfen die Bremse immer nur an einem 
Rad reparieren: "Bremst doch schon!"

von m.n. (Gast)


Lesenswert?

W.S. schrieb:
> ist doch simpel und kommt mit ein paar einfachen Subtraktionen und
> Additionen aus.

Programm siehe hier: 
Beitrag "Re: ADC-Wert auf 4 7-Segmentanzeigen darstellen ohne viel Rechenleistung"
Guten Morgen!

eProfi schrieb:
> Ich habe vor 8 Jahren so etwas mit Hilfe von Tabellen gemacht:

Wenn man 100 Byte für eine Tabelle mit den Werten 0x00 ... 0x99 übrig 
hat, reicht bei vierstelligen Zahlen eine einzige Division: Zahl/100.
Das Ergebnis (Quotient) liefert den Index auf die Tabelle für die beiden 
oberen Stellen. Für die beiden unteren Stellen nimmt man den Rest als 
Index.

Beispiel für 0x2694 und 0x64 (100) als Divisor:
0x2694/0x64 ergibt 0x62 mit Rest 0x4c.
0x62 als Index liefert aus der Tabelle '98' und 0x4c den Wert '76'.
Als BCD-Ergebnis erhält man: '9876'.

Bei µCs, die 32/16 Bit per Hardware rechnen können, kann man gleiches 
Verfahren für achtstellige Ergebnisse verwenden, indem zunächst 
Zahl/10000 ausgeführt wird. Quotient und Rest werden dann nochmals wie 
gezeigt /100 geteilt. Effizient programmiert man soetwas am besten in 
Assembler ;-)

von Frank (Gast)


Lesenswert?

embeddedgurus.com/stack-overflow/2011/02/efficient-c-tip-13-use-the-modu 
lus-operator-with-caution

von Leo C. (rapid)


Lesenswert?

Frank schrieb:
> 
http://embeddedgurus.com/stack-overflow/2011/02/efficient-c-tip-13-use-the-modulus-operator-with-caution/

Sorry, aber der Typ schreibt Nonsens.
Zitat:
1
In this case I have replaced three mods with three subtractions and three 
2
multiplications. Thus although I have replaced a single operator (%) with 
3
two operations (- *) I still expect an increase in speed because the 
4
modulus operator is actually three operators in one (- * /).  Thus 
5
effectively I have eliminated three divisions and so I expected a 
6
significant improvement in speed.

Modulo liefert den Rest, der bei einer Division ohnehin anfällt. Der 
Aufwand für Division (/) und Modulo (%) ist also normalerweise gleich.
Was er gemacht hat, ist den Aufwand für 3 Divisionen durch 3 
Multiplikationen und 3 Subtraktionen zu ersetzen.

1
The results however were a little surprising:

Kein Wunder, wenn man von falschen Voraussetzungen ausgeht.

von c-hater (Gast)


Lesenswert?

Stefan U. schrieb:

> Das Problem trifft Handwerker sicher ebenso.

Natürlich, was denn sonst. Programieren ist doch letztlich genauso ein 
Handwerk wie jedes andere auch, nur dass die Werkstücke keine Entitäten 
der pysischen Welt sind.

Aber ansonsten ist alles ziemlich gleich: grober Pfusch fällt sofort 
auf, gemäßigter Pfusch etwas später. Und das optimale Ergebnis ist nur 
mit überproportional hohem Aufwand zu erzielen. Und Erfahrung ist durch 
nichts zu ersetzen.

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.