Hiho zusammen, mein erstes etwas größeres uC-Projekt und irgendwie hakt es dauernd... Mein aktuelles Problem ist, das das Programm zu groß geworden ist, nachdem ich alle Einzelteile zusammen gebaut habe. Ich habe 1k Flash zur Verfügung, das Programm ist aber ca. 3k groß. Liegt es an meiner umständlichen/ineffizienten Programmierung oder ist der Flash einfach nur zu klein für den Funktionsumfang? Ich habe die '.c' mal angehängt. Vielleicht hat ja jemand kurz Zeit, sich das Gewurstel mal anzusehen... Danke schonmal...
Welchen MSP verwendest du hier ? Optimizer angeschmissen ? Welcher C Compiler ?
Sorry, falscher Stand der '.c'!!! Hier noch einmal der aktuelle Stand.
Wenns ein einzelstück sein soll: nimm nen größeren µC (wird vmtl. dann 4kb werden) Wenns Massenware sein soll: versuchs auf 2kb zu kriegen und nimm ne 2kb µC Wenn du nicht grade mit debug-Optimierung und nur floating point berechnung gearbeitet hast, dann wirst du nie aus 3kb eines machen, da sind 2 schon sportlich.
Bernd N schrieb: > Welchen MSP verwendest du hier ? Optimizer angeschmissen ? Welcher C > Compiler ? MSP ist der G2131, Optimierer auf kleinste Größe und Compiler ist der vom CCS.
Ich kann mir nicht vorstellen, dass diese paar Zeilen 3k erzeugen. Schau mal dein MAP-File an, was da noch alles drin ist. Irgendwelche Libs dazugelinkt, die nicht gebraucht werden? Ausserdem fehlt das While(1){} in der main.
:
Bearbeitet durch User
Daniel V. schrieb: > Ich kann mir nicht vorstellen, dass diese paar Zeilen 3k erzeugen. So gings mir auch, ich habe auch mal kurz quer überflogen und habe weder floating point gefunden noch printf oder andere Dinge, die viel Platz brauchen. Ich kenne die MSPs nicht, aber das bischen C Code gibt doch keine 3K? Also MAP File, im Zweifel mal posten.
Ich habe zuletzt die "Dauermessung" mit dem WDT als Status-LED-Timer eingebaut. Vorher hatte ich knapp 1k, jetzt bekomme ich 'ne Fehlermeldung, dass das Programm nicht in den Speicher passt und wenn ich die angegebene HEX-Zahl umrechne, bin ich bei gut 3kByte. Andere LIBs hab ich nicht eingebunden... Und die Endlosschleife habe ich weg gelassen, weil die bei den TI-Beispielen auch nicht da war, aber daran liegt es glaube ich auch nicht...
Schreib das hier um
1 | uint16_t wert10 = (uint16_t)(tarawert*0.1); |
2 | uint16_t wert90 = (uint16_t)(tarawert*0.9); |
so dass keine Floating Point Berechnung mehr auftaucht und dein Speicherverbrauch wird wieder sinken. Du musst ja nicht mit 0.1 multiplizieren! Mal 10 durch 100 tuts auch. Mal 1 durch 10, bzw. mal 9 durch 10 ist noch besser, weil es die Gefahr eines Overflows während der Berechnung kleiner macht. Aber diese beiden Multiplikationen ziehen einen ganzen Rattenschwanz mit ins Programm hinein.
:
Bearbeitet durch User
Karl Heinz Buchegger schrieb: > Schreib das hier um >
1 | > uint16_t wert10 = (uint16_t)(tarawert*0.1); |
2 | > uint16_t wert90 = (uint16_t)(tarawert*0.9); |
3 | >
|
> so dass keine Floating Point Berechnung mehr auftaucht und dein > Speicherverbrauch wird wieder sinken. > > Du musst ja nicht mit 0.1 multiplizieren! Mal 10 durch 100 tuts auch. > Mal 1 durch 10, bzw. mal 9 durch 10 ist noch besser, weil es die Gefahr > eines Overflows während der Berechnung kleiner macht. > Aber diese beiden Multiplikationen ziehen einen ganzen Rattenschwanz mit > ins Programm hinein. Das werde ich nachher ausprobieren. Hätte nicht gedacht, das *0.9 was anderes macht als /10 *9...
Dominik R. schrieb: > Das werde ich nachher ausprobieren. Hätte nicht gedacht, das *0.9 was > anderes macht als /10 *9... sogar *9/10 ist noch was anderes!
Dominik R. schrieb: > Das werde ich nachher ausprobieren. Hätte nicht gedacht, das *0.9 was > anderes macht als /10 *9... 0.9 ist eine Gleitkommazahl, also muß die Bibliothek für Gleitkomma-Berechneungen bemüht werden. 10 und 9 sind dagegen nur Integers, brauchen das also nicht.
Dominik R. schrieb: > Das werde ich nachher ausprobieren. Hätte nicht gedacht, das *0.9 was > anderes macht als /10 *9...
1 | 23 / 10 -> 2 |
2 | 2 * 9 -> 18 |
3 | |
4 | |
5 | 23 * 9 -> 207 |
6 | 207 / 10 -> 20 |
7 | |
8 | 23 * 0.9 -> 20.7 |
9 | |
10 | |
11 | 18 != 20 != 20.7 |
12 | 3 verschiedene Ergebnisse, je nachdem wie man rechnet |
Die Grundlagen der Datentypen und ihre Verwendung bzw. wie sie Berechnungen beeinflussen solltest du aber schon kennen, wenn du was programmierst.
:
Bearbeitet durch User
Dominik R. schrieb: > Hier ist noch das MAP. .text ist nur 0x3d4 gross, also 980 Byte. Wie kommst du auf 3k? Eventuell ist dein Hexfile 3k gross. Lade doch das Programm einfachmal auf deinen uC....
Dominik R. schrieb: > Ich habe zuletzt die "Dauermessung" mit dem WDT als Status-LED-Timer > eingebaut. > > Vorher hatte ich knapp 1k, jetzt bekomme ich 'ne Fehlermeldung, dass das > Programm nicht in den Speicher passt und wenn ich die angegebene > HEX-Zahl umrechne, bin ich bei gut 3kByte. > Andere LIBs hab ich nicht eingebunden... > > Und die Endlosschleife habe ich weg gelassen, weil die bei den > TI-Beispielen auch nicht da war, aber daran liegt es glaube ich auch > nicht... Hab ich jetzt erst gesehen. Ich tippe: Map-File und C-File passen nicht zusammen.
Kann sein, dass das map-file noch eins von dem stand ist, wo ich die "dauermessung" noch nicht drin hatte. Ich überprüfe das nachher noch einmal und lade die aktuelle map noch mal hoch. Sorry. Das ein integer etwas anderes ist als ein float ist mir bewusst. Ich war nur davon ausgegangen, dass eine implizierte konvertierung durchgeführt wird, wenn man zwei integer dividiert, bei denen ein Rest übrig bleibt. Ich werde nachher die ...*0.9 durch (.../9)*10 und die ...*0.1 durch .../10 ersetzen. Damit müsste ich ja Platz schaffen können. Vielleicht passt es dann ja schon wieder.
Bei manchen C-Compilern muss man die Bibliotheken, die plötzlich nicht mehr benötigt werden explizit aus den Listen entfernen. Sonst werden sie weiterhin unnötig hinzu gelinkt, zumindest der Rumpf.
Ralf G. schrieb: > Dominik R. schrieb: >> (.../9)*10 > > *9/10 > > Außer, du willst da jetzt was ganz anderes ausrechnen... Ja, klar. *9/10 meinte ich. Ich habe das jetzt auch geändert und bin somit auf 1258 Byte. Leider immer noch knapp 270 Byte zuviel... mal davon abgesehen, dass ich bisher immer dachte, 1 kByte wären 1024 Byte. Platz ist aber nur 992 Byte. Noch irgend jemand 'ne Idee, wo man noch etwas optimieren kann? Ach ja, hier noch das aktuelle Map-File.
> timerCount = (timerCount + 1) % 120; //ca. 1 Min.
Mach da mal
timerCount = (timerCount + 1) % 128; //ca. 1 Min.
draus. Wird wohl egal sein obs etwas mehr als 1 Minute ist.
volatile uint8_t m;
for(m = 0; m < 60; m++){
Was soll das volatile da? Mach das weg.
Wenn du deine Werte für ledstatus ein wenig intelligenter vergeben würdest, anstatt einfach von 0 beginnend durchzuzählen, dann würdest du dir hier
1 | switch(ledStatus){ |
2 | case 1: |
3 | P1OUT ^= LED_GREEN; |
4 | P1OUT |= LED_YELLOW + LED_RED; |
5 | break; |
6 | case 2: |
7 | P1OUT &= ~LED_GREEN; |
8 | P1OUT |= LED_YELLOW + LED_RED; |
9 | break; |
10 | case 3: |
11 | P1OUT &= ~LED_YELLOW; |
12 | P1OUT |= LED_GREEN + LED_RED; |
13 | break; |
14 | case 4: |
15 | P1OUT &= ~LED_RED; |
16 | P1OUT |= LED_GREEN + LED_YELLOW; |
17 | break; |
18 | case 5: |
19 | P1OUT ^= LED_RED; |
20 | P1OUT |= LED_GREEN + LED_YELLOW; |
21 | break; |
zb schon eine ganze Menge sparen. Denn deine LED sind am Port sowieso an benachbarten Pins angeordnet, so dass du im Grunde nichts anderes tun musst, als ledStatus genau den binären 3-Bit Wert zu geben, den du ganz einfach am Port ausgeben kannst.
:
Bearbeitet durch User
Irgendwie verteilst du volatile mit dem Gießkannanprinzip. Z.B. ist / messwert/ volatile und dann sowas. Das muß zu ineffizientem Code führen!
1 | if(messwert < 0){ |
2 | ledStatus = 1; |
3 | }
|
4 | else if((messwert > 0) && (messwert < wert10)){ |
5 | ledStatus = 2; |
6 | }
|
7 | else if((messwert > wert10) && (messwert < wert90)){ |
8 | ledStatus = 3; |
9 | }
|
10 | else if((messwert > wert90) && (messwert < tarawert)){ |
11 | ledStatus = 4; |
12 | }
|
13 | else if(messwert < tarawert){ |
14 | ledStatus = 5; |
15 | }
|
>Irgendwie verteilst du volatile mit dem Gießkannanprinzip.
Genau. Einfach einmal messwert in eine lokale Variable
holen und den ganzen Klimbim dann damit ausführen.
Sonst muss messwert ja jedesmal neu aus dem Speicher gelesen werden.
So ganz hab ich noch nicht durchschaut, wozu du den Watchdog Timer benötigst. Wenn ich das richtig sehe, dann ist der Watschdog doch sowieso nur an einer einzigen Programmsequenz aktiv - nämlich der Schleife in der die Messungen gemacht werden. An deren Ende steht aber ein delay. Da frage ich mich: Hä? Wozu der ganze Klimbim mit dem Watchdog - mach doch den Update der LEDs gleich in dieser Schleife und spar dir den ganzen Hackmack mit Watchdog aktivieren, konfigurieren und eigener ISR. Oder übersehe ich da jetzt was?
:
Bearbeitet durch User
Johann L. schrieb: > Irgendwie verteilst du volatile mit dem Gießkannanprinzip. Z.B. ist / > messwert/ volatile und dann sowas. Das muß zu ineffizientem Code > führen! Ja, stimmt schon.Ich bin mir halt unsicher, wann der Compiler vielleicht wichtige Dinge "wegoptimiert"... Karl Heinz Buchegger schrieb: > Denn deine LED sind am Port sowieso an benachbarten Pins angeordnet, so > dass du im Grunde nichts anderes tun musst, als ledStatus genau den > binären 3-Bit Wert zu geben, den du ganz einfach am Port ausgeben > kannst. da stehe ich jetzt etwas auf dem Schlauch. ledStatus 2 wäre dann z.B. 0xC0 (also P1.7 HI, P1.6 HI, alles andere auf LO) oder wie muss ich mir das vorstellen?
Karl Heinz Buchegger schrieb: > So ganz hab ich noch nicht durchschaut, wozu du den Watchdog Timer > benötigst. > > Wenn ich das richtig sehe, dann ist der Watschdog doch sowieso nur an > einer einzigen Programmsequenz aktiv - nämlich der Schleife in der die > Messungen gemacht werden. An deren Ende steht aber ein delay. Da frage > ich mich: Hä? Wozu der ganze Klimbim mit dem Watchdog - mach doch den > Update der LEDs gleich in dieser Schleife und spar dir den ganzen > Hackmack mit Watchdog aktivieren, konfigurieren und eigener ISR. > Oder übersehe ich da jetzt was? Ja, stimmt... vorher hatte ich den WDT auch noch für was anderes. Das ist aber irgendwann geändert worden und ich habe nicht daran gedacht, dass ich die LED-Anzeige dann ja auch ohne WDT machen kann...
>Ja, stimmt schon.Ich bin mir halt unsicher, wann der Compiler vielleicht >wichtige Dinge "wegoptimiert"... Wer eine globale Variable "i" anlegt sollte sich um ganz andere Dinge sorgen machen. Und diese ganzen Delays in den Interrupts. Ganz klares NoGo.
Das mit dem globalen i war nur ein Versuch, aus zwei Variablen, die ja auch etwas Speicher brauchen, eine zu machen, da ich an zwei Stellen eine Zähler-Variable brauchte, aber beide Stellen nie gleichzeitig zählen. Dass es das nicht gebracht hat, ist mir inzischen auch schon klar ;-) Wo sollen die Delays denn sonst hin? Anbei noch einmal die '.c' ohne WDT. Leider fehlen mir immer noch 148 Bytes...
Man lese diesen Beitrag: Beitrag "Re: MSP430G211 analoge Eingänge" Der Code ist für ein Kundenprojekt. lol Dem ganzen Projekt fehlt es an Struktur. Erst wurde die HW verbastelt, jetzt ist die SW dran. Das bisschen Gefrickele passt doch locker in den 1k. Ein Blick in die Projektkonfiguration kann helfen.
ich kann lesen schrieb: > Dem ganzen Projekt fehlt es an Struktur. Erst wurde die HW verbastelt, > jetzt ist die SW dran. Für die Hardware kann ich nunmal nichts, die habe ich so vorgegeben bekommen. Und ja, jetzt ist die Software dran. Aber da ich wie gesagt noch ein ziemlicher Anfänger im Bereich uC bin und das eher als Hobby sehe, mit dem ich mir ein paar Euros dazu verdienen kann, weiss ich nicht, wo dein Problem ist. Aber wenn du mir jetzt noch sagst, was ich in der Projektkonfiguration einstellen muss, damit das bisschen gefrickel auch in die 1k passt, wäre ich echt ein ganzes Stück weiter.
Daniel V. schrieb: > Ausserdem fehlt das While(1){} in der main. gute Frage, Dominik R. schrieb: > Und die Endlosschleife habe ich weg gelassen, weil die bei den > TI-Beispielen auch nicht da war, aber daran liegt es glaube ich auch > nicht... falsche Antwort. Besser wäre: Aus dem LPM kommt der MSP nur per Interrupt. Nach Abarbeitung der ISR wird das Statuswort restauriert und damit wieder in den LPM geschaltet. Karl Heinz Buchegger schrieb: > spar dir den ganzen > Hackmack mit Watchdog aktivieren, konfigurieren und eigener ISR. > Oder übersehe ich da jetzt was? Der Watchdog kann beim MSP als einfacher Timer genutzt werden.
>Aber wenn du mir jetzt noch sagst, was ich in der Projektkonfiguration >einstellen muss, damit das bisschen gefrickel auch in die 1k passt Du kannst in den Projektoptionen nichts einstellen was deinen vergurkten Code verbessert. Die meisten deiner volatiles sind überhaupt nicht notwendig. DA holst du dir dein Flash zurück.
holger schrieb: >>Aber wenn du mir jetzt noch sagst, was ich in der Projektkonfiguration >>einstellen muss, damit das bisschen gefrickel auch in die 1k passt > > Du kannst in den Projektoptionen nichts einstellen > was deinen vergurkten Code verbessert. > > Die meisten deiner volatiles sind überhaupt nicht notwendig. > DA holst du dir dein Flash zurück. Die volatiles sind in der aktuellen Version gar nicht mehr drin. ich kann lesen schrieb: > Der Watchdog kann beim MSP als einfacher Timer genutzt werden. Ich hatte den WDT als einfachen Timer genutzt, war aber - wie kbuchegg schrieb - gar nicht mehrnötig, also auch entfernt.
Sind noch irgendwelche unnötigen Bib's drin? Welche Variablen können vom Datentyp kleiner werden? Auf gleiche Konstanten bei den Wartezeiten gehen!? Delay über Timer? Inlinefunktionen? Anderer Algorithmus überlegen? ...
holger schrieb: > Du kannst in den Projektoptionen nichts einstellen > was deinen vergurkten Code verbessert. :-D Das stimmt zu 100%! Aber man kann einmal nachsehen, was noch so alles zum Kraut und Rüben Programm dazu kommt. ;-)
>> Die meisten deiner volatiles sind überhaupt nicht notwendig. >> DA holst du dir dein Flash zurück. > >Die volatiles sind in der aktuellen Version gar nicht mehr drin. Ich habe nicht gesagt ALLE sollten kein volatile sein. Wo ist denn der derzeitige Flash Bedarf?
>Wo ist denn der derzeitige Flash Bedarf? >Leider fehlen mir immer noch 148 >Bytes... Ok Frage selber beantwortet;)
Ich verstehe nicht wirklich, wann der Compiler ggf. eine Variable wegoptimiert und diese somit als volatile gekennzeichnet werden muss...
Jetzt habe ich zum Spaß das Programm unverändert mit den Standardeinstellungen MAKEn lassen und
1 | 984 bytes of CODE memory |
2 | 62 bytes of DATA memory (+ 20 absolute ) |
3 | 3 bytes of CONST memory |
4 | |
5 | Errors: none |
6 | Warnings: none |
Geht doch!
Dominik R. schrieb: > Ich verstehe nicht wirklich, wann der Compiler ggf. eine Variable > wegoptimiert und diese somit als volatile gekennzeichnet werden muss... Der Compiler wird nur Variablen "wegoptimieren", die nicht verwendet werden. Hier aber wird er optimieren (nicht "wegoptimieren"): Johann L. schrieb: > if(messwert < 0){ > ledStatus = 1; > } > else if((messwert > 0) && (messwert < wert10)){ > ledStatus = 2; > } > else if((messwert > wert10) && (messwert < wert90)){ > ledStatus = 3; > } > else if((messwert > wert90) && (messwert < tarawert)){ > ledStatus = 4; > } > else if(messwert < tarawert){ > ledStatus = 5; > } "messwert" wird EINMAL in ein Register eingelesen und dann wird mit dem Register gerechnet. Falls du "messwert" als volatile definiert hast, wird der Compiler "messwert" bei jedem Vergleich neu in ein Register lesen. Das macht die Kiste langsamer und den Code grösser. Falls sich "messwert" während diesem Vergleich ändern kann (z.B. wenn die Variable in einem Interrupt verändert wird) UND du möchtest, dass immer mit dem aktuellen Wert gerechnet wird, dann ist "volatile" angesagt. Ansosnten kannst du dir "volatile" sparen.
>Ja, stimmt schon.Ich bin mir halt unsicher, wann der Compiler vielleicht
wichtige Dinge "wegoptimiert"...
Sowas gibt es gar nicht, resp darf es nicht geben. Das ist das
Wichtigste. Man muss sich drauf verlassen koennen, dass das geschieht,
was man will. Deswegen ist Debuggen auch Teil des Entwicklungsprozesses,
und nicht etwas Unerwuenschtes, das man leider nachher noch anfuegen
muss.
Hallo nochmal, ich habe es leider immer noch nicht geschafft, das Programm so weit zu verkleinern, dass es in den uC-Speicher passt. Auch diese Aussage hilft nicht wirklich weiter: ich kann lesen schrieb: > Jetzt habe ich zum Spaß das Programm unverändert mit den > Standardeinstellungen MAKEn lassen und 984 bytes of CODE memory > 62 bytes of DATA memory (+ 20 absolute ) > 3 bytes of CONST memory > > Errors: none > Warnings: none > > Geht doch! 984+62+3 = 1049 Bytes => zu groß für den 992 Byte großen Speicher (oder wird DATA und CONST nicht im Flash abgelegt?) Vielleicht kannst du mir auch noch sagen, was du für ein Compiler benutzt hast, denn wenn ich den Code mit CCS 5.5 und den Standardeinstellungen kompiliere, ist das Programm doch noch etwas größer. Ich habe den Code noch weiter bearbeitet, so dass ich mit meinen Einstellungen auf 1060 Byte komme. So sind es aber leider immer noch 68 Byte zuviel. Ich habe den aktuellen Stant noch einmal angehängt. Gibt es noch weiteres Einsparungspotential? Da ich noch nicht so lange in C und mit Mikrocontrollern arbeite, würde ich auch gerne wissen, was strukturell vielleicht noch verbessert werden könnte. Ja, ich weiss, dass man von Interrupt-Routinen aus keine Methoden aufrufen sollte, schon gar nicht mit Delays, aber wenn ein Interrupt verschluckt wird, ist das hier nicht sooo tragisch. Außerdem weiss ich nicht, wie ich es besser machen sollte. Ist es ok, erst das Flag zu clearen und dann eine Methode aus der ISR heraus aufzurufen? Was mir an meinem Code gar nicht gefällt ist diese if ... 3x else if ... else Katastrophe, aber ich habe auch keine Idee, wie ich das eleganter lösen sollte... Danke schonmal.
Dominik R. schrieb: > Was mir an meinem Code gar nicht gefällt ist diese if ... 3x else if ... > else Katastrophe, aber ich habe auch keine Idee, wie ich das eleganter > lösen sollte... Das ist nun wirklich das allerkleinste Problem an dem Code ... Ganz ernst gemeinter Rat: Lösch den Murks und schreib es nochmal. Nimm es auch nicht als Vorlage für ein neues Programm. Fang nochmal mit einer leeren Datei an und schreib es ohne Interrupts und volatile, einfach geradeaus mit Polling. Danach ist das Programm nur noch halb so groß, verständlich und funktioniert auch sauber.
Der Gedanke das obige Programm ins Flash zu bekommen, wo scheinbar nur noch so wenig "abzuschneiden" ist, ist aus sportlicher Sicht bestimmt reizvoll. Bedenke aber bitte folgendes: - Durch trickreiche Konstrukte kann man einiges an Speicher sparen, aber die Wartbarkeit auf null drücken. - Bist Du Dir 100% sicher, das, kaum dass es passt, nicht noch irgendwas nachgerüstet werden muss? Dann landest Du nämlich auf direktem Weg in der Abteilung: "Typischer Fall von Denkste". Die liegt übrigens gleich neben der Abteilung: "Außer Spesen nix gewesen".
Ganz ohne Interrupts wird es nicht gehen, da sich der uC im LPM befinden soll, wenn gerade nich gemessen wird. Ich hab da keinen Schimmer, wie ich das umsetzen sollte. Und nur, damit ich es das nächste Mal besser machen kann - was ist denn besonderer Murks (mal abgesehen von den Delays, die aus den ISR aufgerufen werden)? - vielleicht habe ich die rosarote Brille auf oder noch zu wenig Plan von C, aber ist es echt soo schlimm?
:
Bearbeitet durch User
Dominik R. schrieb: > wird DATA und CONST nicht im Flash abgelegt? Richtig, DATA ist RAM. Das Ganze wurde mit dem IAR erstellt. Aber auch das hilft dir nicht. Das Programm ist bestimmt noch nicht fertig, du brauchst mehr Speicher. Dominik R. schrieb: > Gibt es > noch weiteres Einsparungspotential? Sind die ganzen delays nötig? In einer ISR wird 5s gewartet! Da würde ich dringend den Ablauf und die Struktur überdenken.
ich kann lesen schrieb: > In einer ISR wird 5s gewartet! Die LED soll 5s leuchten, bevor der Wert gespeichert wird. Und da in der Zeit weder auf Taster noch auf Timer reagiert werden soll, dachte ich, das das Delay in der ISR ok ist. Aber wenn das Programm auf biegen und brechen nicht in den uC passt, hilft das alles nichts...
>Gibt es noch weiteres Einsparungspotential?
Ja, gibt es. Mach keine Berechnungen oder Vergleiche
mit volatile Variablen. Vermeide überflüssige Berechnungen.
1 | uint16_t tmptara = tarawert; |
2 | uint16_t tmpnullwert = nullwert; |
3 | |
4 | uint16_t wert10 = (tmptara-tmpnullwert)/10; // wert10 = Schwelle 1 (10% Tara) |
5 | uint16_t wert90 = ((tmptara-tmpnullwert)*9)/10; // wert90 = Schwelle 2 (90% Tara) |
6 | |
7 | for(m=60; m > 0; m--) |
8 | { // 15 Sek. messen (alle 1/4 Sek.) |
9 | int16_t messwert = messung(2)-tmptara; |
10 | P1OUT |= LED_GREEN + LED_YELLOW + LED_RED; // alle LEDs aus |
11 | if(messwert < 0) |
12 | {
|
13 | if(++b == 2) |
14 | { // bei jedem 2. Durchlauf LED an (blinken) |
15 | P1OUT &= ~LED_GREEN; |
16 | b = 0; |
17 | }
|
18 | }
|
19 | else if(messwert < wert10) |
20 | {
|
21 | P1OUT &= ~LED_GREEN; |
22 | }
|
23 | else if(messwert < wert90) |
24 | {
|
25 | P1OUT &= ~LED_YELLOW; |
26 | }
|
27 | else if(messwert < tmptara) |
28 | {
|
29 | P1OUT &= ~LED_RED; |
30 | }
|
31 | else if(messwert > tmptara) |
32 | {
|
33 | if(++b == 2) |
34 | {
|
35 | P1OUT &= ~LED_RED; // bei jedem 2. Durchlauf LED an (blinken) |
36 | b = 0; |
37 | }
|
38 | }
|
39 | else
|
40 | {
|
41 | P1OUT |= LED_GREEN + LED_YELLOW + LED_RED; |
42 | }
|
43 | delay_ms(250); |
44 | }
|
Danke für den Hinweis. Natürlich muss wert10 und wert90 nicht 60 mal berechnet werden. Hätte ich auch früher mal sehen können. Hat 8 Byte gebracht. Bleiben leider immer noch 60 über. Ich denke, das wird nichts mehr. Ist volatile bei den beiden Variablen überhaupt notwendig? Ich bin mir da nicht so ganz sicher. Normalerweise muss man ja volatile deklarieren, wenn sich der Wert einer Variablen während der Verarbeitung durch eine andere ISR ändern könnte, oder? Aber eigentlich kann / soll sich der Wert der beiden Variablen an der Stelle der Berechnung gar nicht ändern. Also ist Volatile hier notwendig?
:
Bearbeitet durch User
Dominik R. schrieb: > Ganz ohne Interrupts wird es nicht gehen, da sich der uC im LPM > befinden > soll, wenn gerade nich gemessen wird. Ich hab da keinen Schimmer, wie > ich das umsetzen sollte. Ich kenne den Controller nicht, aber es sollte doch ausreichen, wenn er per Interrupt geweckt wird und dadurch wieder in die Hauptschleife springt? Der Interrupt selber muss dann gar nichts machen. > Und nur, damit ich es das nächste Mal besser machen kann - was ist denn > besonderer Murks (mal abgesehen von den Delays, die aus den ISR > aufgerufen werden)? - vielleicht habe ich die rosarote Brille auf oder > noch zu wenig Plan von C, aber ist es echt soo schlimm? Äußerlich: - Unsaubere Codeformatierung (fehlende Leerzeichen vor Klammern und teilweise in Ausdrücken) - Unheitliche Bezeichner (timerCount, daycount), Deutsch und Englisch gemischt - Unklare Bezeichner (interval15, praktisch alle Funktionsnamen) Technisch: - Kein static vor den Hilfsfunktionen (hier: alle außer main) und den Modulvariablen (hier: alle globalen Variablen). Alleine das könnte schon zur Größenreduktion reichen. - Globale Variablen statt lokale (statische) Variablen. Z.B. wird timerCount nur in der ISR Timer_A benutzt, würde also als static-Variable in diese Funktion gehören. - Unsinnige volatiles. Wie gesagt, ohne Interrupts bräuchte man überhaupt keine. Falls man eine volatile-Variable in einer Funktion mehr als einmal benutzt, lohnt es sich, sie in eine lokale Variable umzukopieren und nur mit der lokalen Variable zu arbeiten. Das kann der Compiler dann optimieren. - Unklarer Programmfluss durch willkürliche Funktionen mit unklaren Namen. Normalerweise sollte alleine durch den Prototyp einer Funktion (Name, Rückgabewert, Parameter) klar sein, was sie tut und möglichst keine globalen Variablen verändern. Bei der Funktion "void dauerMessung(void)" ist exakt das Gegenteil der Fall ... Ich weiß, gerade letzteres ist als Anfänger nicht so einfach zu erreichen, dazu braucht man Erfahrung. Bevor man aber willkürlich irgendwelche Funktionen definiert, halte ich es dann immer noch für besser, zunächst mal den kompletten Kontrollfluss in eine Funktion zu packen und die einzelnen Abschnitte sinnvoll zu kommentieren. Wenn man darin dann einen Teil erkennt, der eine in sich geschlossene Funktionalität darstellt, am besten mit wenigen Eingabeparametern, ohne Nebenwirkungen und mit einem Ergebnis, das man zurückgeben kann, dann macht man daraus eine Funktion. Deren Name sollte mit einem Verb beginnen und genau das beschreiben was sie tut. Und sie darf dann auch nur genau das machen und nichts anderes. Nur so erhält man sinnvolle Funktionen, die beim Verständnis des Codes helfen. Zuletzt dann noch die Delays ... Die will man eigentlich auch nicht haben, schon gar nicht im Interrupt. In einem einfachen Programm, das sonst nichts machen muss, als eine lineare Befehlsfolge abarbeiten, sind sie aber OK. Nur dann wie gesagt bitte keine Interrupts, das passt schlichtweg nicht zusammen.
Danke für die Hinweise. Ich werde die Ratschläge beherzigen und noch einmal versuchen, eine Poll-Version zu machen, die dann evtl. auch etwas kleiner ausfällt. Ich wünsche noch eine gute Nacht.
Probier mal statt X &= ~BUTTON_T; X &= ~(unsigned char) BUTTON_T Das ergibt bei manchen Prozessorn aus einer "Oder" Operation eine Bitoperation
Martin H. schrieb: > Probier mal statt ... Das sollte ein guter Compiler von selbst erkennen und optimieren.
Dann frage ich mich, warum moderne Kompiller wie Keil für ihre Konstanten stets Typen für ihre Konstanten angeben.
1 | // Flash Control Register definitions
|
2 | #define FLASH_PG ((unsigned int)0x00000001)
|
3 | #define FLASH_SER ((unsigned int)0x00000002)
|
Mein Tip war also vieleicht nicht hifreich, aber sicherlich nicht unnötig.
Martin H. schrieb: > für ihre > Konstanten stets Typen für ihre Konstanten angeben ??? Martin H. schrieb: > sicherlich nicht > unnötig Wo besteht der Zusammanhang mit Konstanten? Oder meinst du, dass daraus durch den Cast eine Variable wird? ;-)))
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.