Hallo All! Wahrscheinlich ein Anfängerproblem... Folgendes: Habe zwei Variablen, die ich ich in meinem Hauptprogramm miteinander verarbeten will. Die eine ist global als volatile deklariert: volatile uint16_t iGuthaben = 0; Die andere im Hauptprogramm Lokal als flaot: float fTemp2 = 0; Im Hauptprogramm bezieht sich folgender Code auf die Variablen: fTemp2 = (iGuthaben/3600); Wenn ich diese Zeile lösche ist mein Speicher zu etwa 16% belegt (Optimierung 0s), wenn ich die Zeile drin hab ist der Speicher zu ca. 61% belegt!!! Wieso? Danke und Gruß Waldemar
weil eine Division auf in Software gemachert werden muss und dabei auch etwas code benötigt. Divisionen sollte man vermeiden und erst recht mit float. Wir vermuten mal alles das es um ein Atmel geht, richtig?
Ja, richtig... ATMega8... Es liegt nicht an der Division... Wenn ich den Gode so schreibe: fTemp2 = iGuthaben; cStunden = fTemp2/3600; und dann die obere Zeige weglösche und kompiliere geht die Auslastung von 60,4% --> 18,3%. Es muss irgendwie an der zwischen einer Volatile und einer float liegen oder so...
> Es liegt nicht an der Division... > Wenn ich den Gode so schreibe: > fTemp2 = iGuthaben; > cStunden = fTemp2/3600; wenn der compiler gut optimiert, dann macht er keine Division mehr.
> Was willst du damit sagen?
das man an den bisschen code sehr wenig ablesen kann, wenn der compiler
feststellt das die Division eh nur mit Konstanten ausgeführt wird, dann
passiert es schnell mal das er die division komplett weglässt.
Aha... Wenn ich das richtig sehe, sind die beiden keine Konstanten... Außerdem funktioniert die division (zumindest teils, aber das ist eine andere Sache). Das ist aber keine Antwort auf meine Frage... Ich wollte vorest mal nur wissen, wieso ich plötzlich so viel code habe???
Im ersten Beispiel wird eine Integer-Division und eine Konvertierung von Integer nach Float gemacht. Letztere braucht besonders viel Flash- Speicher, weil du beim Linken das -lm weggelassen hast. Im zweiten Beispiel wird nur eine Integer-Float-Konvertierung gemacht, da du cStunden im weiteren Verlauf des Programm nicht mehr benutzt, so dass die Division wegoptimiert wird. Löscht du die Zeile fTemp2 = iGuthaben; bleibt von den beiden Zeilen gar nichts mehr übrig, deswegen wird das Programm deutlich kürzer.
dann schau ins map file oder die asm datei. Vergleiche die Dateien mit und ohne dem volatile.
Ok ich hol mal ein bisschen weiter aus... Das Programm dient dazu eine 16Bit-Zahl (Sekunden) in Stunden und Minuten umzurechnn um dann den Wert auf einem Display auszugeben (in dem Fall als Timer-Funktion) Hier der Relevante Teil des Codes:
1 | // Variablendefinitionen Global
|
2 | volatile uint16_t millisekunden = 0; |
3 | volatile uint16_t iGuthaben = 3670; |
4 | |
5 | .
|
6 | .
|
7 | .
|
8 | |
9 | // Variable Headerdateien
|
10 | #include <subs/interrupt.c> // Alle Interruptroutinen |
11 | |
12 | .
|
13 | .
|
14 | .
|
15 | |
16 | // Programmstart
|
17 | int main () |
18 | |
19 | {
|
20 | //----------------------------------------------------------------------
|
21 | // Variablendefinitionen lokal
|
22 | char cBuffer[20]; |
23 | float fTemp2 = 0; |
24 | uint16_t temp1 = 0; |
25 | uint8_t cSekunden = 0; |
26 | uint8_t cMinuten = 0; |
27 | uint8_t cStunden = 0; |
28 | |
29 | .
|
30 | .
|
31 | .
|
32 | |
33 | // main loop
|
34 | |
35 | do
|
36 | {
|
37 | |
38 | .
|
39 | .
|
40 | .
|
41 | |
42 | temp1++; |
43 | |
44 | if (temp1 == 0x0FFF) |
45 | {
|
46 | temp1 = 0; |
47 | |
48 | fTemp2 = iGuthaben; |
49 | cStunden = fTemp2/3600; |
50 | cMinuten = (fTemp2-(3600*cStunden))/60; |
51 | cSekunden = (fTemp2-(60*cMinuten))/60; |
52 | lcd_clear(); |
53 | _lcd_string("Zeit = "); |
54 | |
55 | itoa(cStunden, cBuffer, 10); |
56 | _lcd_string(cBuffer); |
57 | |
58 | _lcd_data(58); // 58 = : |
59 | |
60 | itoa(cMinuten, cBuffer, 10); |
61 | _lcd_string(cBuffer); |
62 | |
63 | _lcd_data(58); // 58 = : |
64 | |
65 | itoa(cSekunden, cBuffer, 10); |
66 | _lcd_string(cBuffer); |
67 | |
68 | _lcd_string("s"); |
69 | |
70 | |
71 | }
|
72 | |
73 | }
|
74 | }
|
Im Timer2 werden die Millisekunden gezählt, und bei Tausend wird von iGuthaben halt eins abgezählt. So sollte es eigentlich funktionieren... Ich hoffe der Code ist nicht zu lang um ihn hier reinzuschreiben... gruß Waldemar
habe jetzt hier keine Möglichkeit zu testen aber ich versteht nicht
warum du überhaupt float verwendest?
Versuche es mal ohne float,
auch geht soetwas bestimmt etwas schöner
>(fTemp2-(3600*cStunden))/60;
schau dir mal das %(modulo) an.
mhh, ja, kann sein... Für vorschläge bin ich gerne offen! Allerdings liegt es ja nicht an der Division! Habs ausprobiert... Wenn ich diese Zeile auser Kraft setze schrumpft mir mein Code auf 16% Auslastung!!!
1 | fTemp2 = iGuthaben; //Auslastung = 61% |
2 | |
3 | // fTemp2 = iGuthaben; //Auslastung = 16%
|
... Bin ratlos ...
Waldemar T. schrieb: > mhh, ja, kann sein... Für vorschläge bin ich gerne offen! Allerdings > liegt es ja nicht an der Division! Es gibt eine int->float Konvertierung. Das geht nicht in Hardware sondern in Software und braucht eben Platz. Übrigens ist float hier Overkill, das geht alles mit int-Arithmetik. float ist bequem, aber eben auch platzfressend...
> Wenn ich diese Zeile auser Kraft setze schrumpft mir mein Code auf 16% > Auslastung!!! Klar, dann ist nämlich fTemp2=0. Das weiß auch der Compiler, berechnet die Ausdrücke in den folgenden drei Zeilen selbst und lässt nur noch folgendes stehen:
1 | cStunden = 0; |
2 | cMinuten = 0; |
3 | cSekunden = 0; |
Das braucht nicht viel Speicher :)
So geht's übrigens ohne Float und ohne Temporärvariable:
1 | cStunden = iGuthaben / 3600; |
2 | cMinuten = iGuthaben / 60 % 60; |
3 | cSekunden = iGuthaben % 60; |
Hey, es geht! :) Ohne Platzfressen! :)) Könntest du mir bitte erklären, was der code macht, oder wo ich das nachlesen könnte (war mir bisher nicht bekannt...)
yalu schrieb: > Klar, dann ist nämlich fTemp2=0. Das weiß auch der Compiler, berechnet > die Ausdrücke in den folgenden drei Zeilen selbst und lässt nur noch > folgendes stehen: > cStunden = 0; > cMinuten = 0; > cSekunden = 0; > Das braucht nicht viel Speicher :) Johann L. schrieb: > Es gibt eine int->float Konvertierung. Das geht nicht in Hardware > sondern in Software und braucht eben Platz. Jetzt versteh ich das ganze auch... Wusste nicht, wie der Compiler das handhabt... Habe früher in Assembler programmiert, da wurde eben befehl für befehl abgearbeitet... ;) Gruß waldemar
> Könntest du mir bitte erklären, was der code macht, oder wo ich das > nachlesen könnte (war mir bisher nicht bekannt...) iGuthaben ist die Zeit in Sekunden, also z.B. 10000. Eine Stunde hat 3600 Sekunden, also muss iGuthaben durch 3600 dividiert werden, um die Anzahl der Stunden zu erhalten:
1 | cStunden = iGuthaben / 3600; |
Da sowohl iGuthaben als auch 3600 Integer-Werte sind, wird auch die Division in Integer durchgeführt und damit die Nachkommestellen abgeschnitten, was in diesem Fall auch erwünscht ist. Im Beispiel ist das Ergebnis 10000/3600=2. Entsprechend ergibt iGuthaben / 60 die Anzahl der Minuten, im Beispiel also 10000/60=166. Davon müssen aber noch die 2 Stunden (=120 Minuten) von oben abgezogen werden, so dass 46 Minuten übrig bleiben. Statt von den 166 Minuten die 120 Minuten abzuziehen, kann man auch die Modulo- funktion (%-Operator in C) verwenden: 166%60 berechnet den Rest der Division von 166 durch 60, was ebenfalls 46 ergibt. Das führt dann zu dem zweiten Ausdruck:
1 | cMinuten = iGuthaben / 60 % 60; |
Die übrigen Sekunden, die noch nicht in den berechneten Stunden und Minuten berücksichtigt sind, ergeben sich aus dem Rest der Division der Gesamtsekundenanzahl durch 60, im Beispiel also 10000%60=40:
1 | cSekunden = iGuthaben % 60; |
Also sind 10000 Sekunden = 2 Stunden 46 Minuten und 40 Sekunden.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.