Forum: Compiler & IDEs Wie Arbeitstakte des Prozessors zählen?


von Erik H. (agutanus)


Angehängte Dateien:

Lesenswert?

Hallo,

ich schreibe gerade ein etwas umfangreicheres Programm für einen ATmega8 
(Belichtungstimer mit Auswahlmenü für eine DSLR-Kamera)
Dabei lasse ich über den Timer2 jede Millisekunde einen Interrupt 
durchführen, welcher eine Menge Abfragen nach sich zieht.
(Tastenabfrage, diverse Zähler mit volatile-Variablen, Vergleiche von 
structs mit 40 bit Größe, Ausgabe über LCD ...)

Nun bin ich mir nicht sicher, wie viele Arbeitsschritte ich durchführen 
kann, bis die Abarbeitung länger dauert, als die Zeit bis zum nächsten 
Aufruf...
Vor allem die Ausgabe von bis zu 32 Zeichen über das LCD macht mir 
Gedanken - wie viele Takte braucht sowas?

Der Controller läuft momentan auf 8 MHz - was also 8000 Takte für den 
Interrupt und angeschlossene Berechnungen lässt.

Wie kann ich die benötigten Takte für einen Durchlauf meines Programmes 
(also je interrupt) berechnen?
Ich dachte auch schon daran zu Beginn den Zähler 1 (16 bit) zu starten 
und am Ende den Stand auszulesen - warte aber noch auf eine eventuell 
allgemeinere Lösung.

Dazu habe ich mein (momentan nicht lauffähiges weil nicht fertiges) 
Programm hochgeladen. Das ist allerdings etwas unübersichtlich, da 
bisher kein PaP existiert...

vG,
Erik

von Floh (Gast)


Lesenswert?

Erik Her schrieb:
> Nun bin ich mir nicht sicher, wie viele Arbeitsschritte ich durchführen
> kann, bis die Abarbeitung länger dauert, als die Zeit bis zum nächsten
> Aufruf...

Wenn du ein Oszi hast, setz zu Beginn des Interrupts einen Pin auf high 
und beim Verlassen wieder auf Low.
Am Oszibild kannste dann abschätzen wieviel Zeit dir bleibt.

von Grrrr (Gast)


Lesenswert?

Im Simulator des AVRStudio gibt es einen Zyklenzähler.
Also den Zähler bei Eintritt in den Interrupts ablesen und dann am Ende 
der Verarbeitung.

Aber Du hast noch ein grundsätzliches Problem mit dem Verständnis von 
Interrupts. Im Interrupt werden grundsätzlich nur die allernotwendigsten 
Dinge erledigt. Im allgemeinen nur ein Flag gesetzt, das der Interrupt 
aufgetreten ist und das Flag dann in der main-Schleife abgefragt.

Ausserdem sehe ich da im Interrupt noch Tastenabfragen. Das ist 
kontraproduktiv, da die Entprellung fehlt.

Bitte das nächste Mal den Code mit "c"-Extension posten und nicht "txt".

von Peter D. (peda)


Lesenswert?

Erik Her schrieb:
> Vor allem die Ausgabe von bis zu 32 Zeichen über das LCD macht mir
> Gedanken - wie viele Takte braucht sowas?

Schau einfach mal ins Datenblatt des LCD.

Typisch dauert ein Zeichen ~50µs, also 32 Zeichen ~1,6ms.
Ist also die vollkommen falsche Stelle, etwas auszugeben.

Ganz abgesehen davon, daß kein Mensch innerhalb 1ms etwas ablesen kann.
Alle 0,2 .. 0,5s Text auszugeben, reicht völlig.


Peter

von Floh (Gast)


Lesenswert?

Erik Her schrieb:
> Vor allem die Ausgabe von bis zu 32 Zeichen über das LCD macht mir
> Gedanken - wie viele Takte braucht sowas?

Ich mach das gern so, dass ich ein char-Feld habe, das ich mit dem 
gewünschten Inhalt beschreibe.
In jedem Interrupt wird dann immer 1(!) Zeichen ausgegeben, damit 
kommste bei 32 Zeichen und 1ms auf ne ordentliche Framerate und der 
Interrupt bleibt schön klein.

von Lord Z. (lordziu)


Lesenswert?

Und warum nicht den einfachsten Weg wählen, der bewährt ist? Nämlich im 
Interrupt nur ein Flag setzen, dass in der Endlosschleife der main 
ausgewertet wird?
So kannst du deine Programmlogik zeitlich wunderbar von der LCD-Ausgabe 
trennen.

von Erik H. (agutanus)


Lesenswert?

@Floh: habe leider kein Oszi

@Grrrr: den Zyklenzähler werde ich mal ausprobieren, wenn ich Zeit habe.
Grrrr schrieb:
> Ausserdem sehe ich da im Interrupt noch Tastenabfragen. Das ist
> kontraproduktiv, da die Entprellung fehlt.
das IST meine Tastenentprellung! habe ich im gcc-Tutorial so in der Art 
gesehen...
(ich frage alle 10 ms den Tastenzustand ab, und wenn eine Taste 10 
Abfragen in Folge gedrückt war ist der Tastendruck gültig)

Peter Dannegger schrieb:
> Ganz abgesehen davon, daß kein Mensch innerhalb 1ms etwas ablesen kann.
> Alle 0,2 .. 0,5s Text auszugeben, reicht völlig.
ich gebe maximal ein Mal je Sekunde etwas aus - aber diese Ausgabe 
dauert halt dann länger als 1 ms...

Lord Ziu schrieb:
> Und warum nicht den einfachsten Weg wählen, der bewährt ist? Nämlich im
> Interrupt nur ein Flag setzen, dass in der Endlosschleife der main
> ausgewertet wird?

ich werde mich dann demnächst ran setzen und das Programm umschreiben um 
alles Rechen-/Zeitaufwändige ins main() zu verlegen... (im Interrupt nur 
flags setzen)
(dauert aber bis meine Prüfungsphase beendet ist)

obwohl ich mit der Funktion bisher sehr zufrieden bin... Aber sinnvoller 
ist es sicherlich mit den flags.

von Karl H. (kbuchegg)


Lesenswert?

Erik Her schrieb:

> obwohl ich mit der Funktion bisher sehr zufrieden bin... Aber sinnvoller
> ist es sicherlich mit den flags.

In deinem Programm kann man noch vieles machen. Hör nicht mit den Flags 
auf.

Da du Zeiten 'logarithmisch' erhöhen bzw. erniedrigen möchtest, wäre es 
zb überlegenswert, ob man nicht programmintern die Unterteilung in 
Millisekunden, Sekunden, Minuten, Stunden fallen lässt und für alles 
ganz einfach einen uint32_t nimmt, der generell eine Zeit in 
Millisekunden abgibt.
Dazu noch ein Array, indem Zeitstufen enthalten sind.
Eine Zeit besteht dann aus einem Zahlenwert und einer Stufennummer. Die 
Zeit erhöhen heisst dann ganz einfach: Die Stufe um 1 erhöhen (falls das 
noch geht) und aus dem Array den entsprechenden Wert in Millisekunden 
holen. Die riesigen switch-case lösen sich in Luft auf. Genauso wie die 
Spezialfunktionen für Zeitvergleichen bzw. prüfen auf 0. Wenn du die 
laufende Belichtungszeit nicht von 0 bis zur Vorgabe hochzählst sondern 
von der Vorgabe runterzählst, bis 0 erreicht ist, vereinfacht sich der 
Code in der ISR noch weiter.

Die ganze Menüsteuerung im main(), also der Teil mit state und den 
Buttons, lässt sich auch in einem kurzen Array von Strukturen abbilden. 
Die 3 Seiten Code dampfen sich dann auf ein paar Zeilen (weniger als 20) 
ein.

Und dann möchtest du noch in deinem C-Buch nachlesen, wie man Strkturen 
per Pointer übergibt. So etwas
1
uint8_t compareTime(TIME a, TIME b)    //vergleicht 2 Zeiten
2
{
3
  if ((a.mseconds == b.mseconds)
4
    && (a.seconds == b.seconds)
5
    && (a.minutes == b.minutes)
6
    && (a.hours == b.hours))
7
    return 1;
8
  else
9
    return 0;
10
}
11
12
uint8_t compareTime_zero(TIME a)    //vergleicht eine Zeit mit 0
13
{
14
  if ((a.mseconds == 0)
15
    && (a.seconds == 0)
16
    && (a.minutes == 0)
17
    && (a.hours == 0))
18
    return 1;
19
  else
20
    return 0;
21
}

muss dann wirklich nicht sein. Genau das ist der klassische Stil, an dem 
sich die C#/Java Jünger aufreiben. Ein Musterbeispiel dafür, wie man 
einen Rechner unnötig Zusatzaufwand zuschanzt der nicht sein muss.

von sebastians (Gast)


Lesenswert?

Klar, ein Makro mit memcmp wär weniger Schreibaufwand gewesen.

Aber bist du sicher dass Zeiger so viel effizienter sind? Sind doch auch 
16 bit-Werte, oder ist das beim ATmega8 anders als beim ATmega16?

Und wenn die Vergleichsfunktionen inline sind könnte es sogar in den 
Registern bleiben wenn man nicht mit Zeigern arbeitet!

--> Wenn mans genau wissen will bleibt wohl nur, die Zyklen im Simulator 
zu messen (mit Compileroption -O3) und zu vergleichen.

von Karl H. (kbuchegg)


Lesenswert?

sebastians schrieb:

> Aber bist du sicher dass Zeiger so viel effizienter sind? Sind doch auch
> 16 bit-Werte, oder ist das beim ATmega8 anders als beim ATmega16?

Hast du dir seine TIME Struktur angesehen?
Tu das und die Frage stellt sich nicht mehr.
Von 16 Bit kann da keine Rede mehr sein.

> Und wenn die Vergleichsfunktionen inline sind könnte es sogar in den
> Registern bleiben wenn man nicht mit Zeigern arbeitet!

Wenn der Compiler inlined, fallen die Zeiger genauso weg. Wenn der 
Compiler aber nicht inlined ....

Und das mit den Registern vergiss gleich mal wieder. Eine TIME Struktur 
hat 4 Member. Einen uint16_t und 3 Stück uint8_t. Die kriegt der 
Compiler noch nicht einmal wenn er will in die Register rein.

Die hier
1
TIME resetTime(TIME time)        //setzt übergebene Zeit zurück

ist besonders schön. Ist nicht nur in der Verwendung mies

(Oder findest du
   currentTime = resetTime( currentTime );
 besonders intuitiv)

sondern auch noch mit 2 potentiellen 5 Byte Kopieraktionen besonders 
effizient.

von Erik H. (agutanus)


Lesenswert?

Also zu allererst: vielen Dank für die vielen Tipps!

Karl heinz Buchegger schrieb:
> Da du Zeiten 'logarithmisch' erhöhen bzw. erniedrigen möchtest, wäre es
> zb überlegenswert, ob man nicht programmintern die Unterteilung in
> Millisekunden, Sekunden, Minuten, Stunden fallen lässt und für alles
> ganz einfach einen uint32_t nimmt, der generell eine Zeit in
> Millisekunden abgibt.
> Dazu noch ein Array, indem Zeitstufen enthalten sind.

  Das macht natürlich auch Sinn - vor allem für die Vergleiche. 
Allerdings erschwert es die Ausgabe auf dem Display:
Zeiten sollen nur in EINER Einheit (h, m, s, ms) dargestellt werden.
(eine Belichtungszeit von 3600000 ms scheint mir nicht 
Benutzerfreundlich)
Ganze Sekunden lassen sich noch durch Division darstellen. Aber die 
Brüche entsprechen nicht den realen Zeiten. So werden 17 ms als 1/60 s 
ausgegeben. (eigentlich: 1/58,8...)
Ich müsste also noch ein weiteres Array mit den entsprechenden 
Ausgabezeiten erstellen...
Das würde dann wiederum die Ausgabe stark vereinfachen. (einfach nur den 
Wert des jeweiligen Arrays ausgeben - ohne große Abfragen)

Die Funktion zum Auslösen und Lösen des Spiegels werde ich aber trotzdem 
im ISR belassen - bei einer Belichtungszeit von 1 ms machen sich 
Verzögerungen doch bemerkbar...

Karl heinz Buchegger schrieb:
> Wenn du die
> laufende Belichtungszeit nicht von 0 bis zur Vorgabe hochzählst sondern
> von der Vorgabe runterzählst, bis 0 erreicht ist, vereinfacht sich der
> Code in der ISR noch weiter.
  das habe ich so gelöst, damit die Funktion nach Beendung der 
Belichtungszeit noch eine weitere Sekunde wartet bevor das Display 
zurück gesetzt wird. (um dem Benutzer die Chance zu geben die 
eingestellt Zeit abzulesen)

Karl heinz Buchegger schrieb:
> Und dann möchtest du noch in deinem C-Buch nachlesen, wie man Strkturen
> per Pointer übergibt
  Ich werde mir wohl erst ein Buch besorgen müssen... Habe nur nach dem 
gearbeitet, was ich aus dem Tutorial und meinen bescheidenen C++ 
Kenntnissen (für PC) konnte.
Aber das würde sicherlich einiges beschleunigen!

Karl heinz Buchegger schrieb:
> Die hier
>   TIME resetTime(TIME time)        //setzt übergebene Zeit zurück
> ist besonders schön.
  das war eine Übergangslösung, da ich keine bessere Möglichkeit 
gefunden habe, den struct zurück zu setzen...
Hat sich aber erledigt, wenn alles in ms gespeichert wird.

Karl heinz Buchegger schrieb:
> Die ganze Menüsteuerung im main(), also der Teil mit state und den
> Buttons, lässt sich auch in einem kurzen Array von Strukturen abbilden.
  wie mache ich sowas?

von Karl H. (kbuchegg)


Lesenswert?

Erik Her schrieb:

>   Das macht natürlich auch Sinn - vor allem für die Vergleiche.
> Allerdings erschwert es die Ausgabe auf dem Display:

Ausgabe machst du aber viel seltener.
Und soviel erschwert es die Ausgabe dann auch wieder nicht.

> Ganze Sekunden lassen sich noch durch Division darstellen. Aber die
> Brüche entsprechen nicht den realen Zeiten. So werden 17 ms als 1/60 s
> ausgegeben. (eigentlich: 1/58,8...)

Das ist natürlich schon ein Argument. Daran hab ich wiederrum nicht 
gedacht.
Ist aber so schlimm auch wieder nicht.

> Ich müsste also noch ein weiteres Array mit den entsprechenden
> Ausgabezeiten erstellen...

Genau.
Dazu noch die Stufennummer der Zeit. Wenn die kleiner als eine Grenze 
ist, dann wird die Ausgabe nicht aus der Millisekundenzahl errechnet, 
sondern aus diesem Stringarray geholt.
Dieses "Stringarray" hast du ja jetzt im Grunde auch schon - versteckt 
in den switch-cases

> Die Funktion zum Auslösen und Lösen des Spiegels werde ich aber trotzdem
> im ISR belassen - bei einer Belichtungszeit von 1 ms machen sich
> Verzögerungen doch bemerkbar...

Das ist ok.
Sind ja nur ein paar Port Bits umsetzen.
Aber die Ausgaben aufs LCD dauern!


>>   TIME resetTime(TIME time)        //setzt übergebene Zeit zurück
>> ist besonders schön.
>   das war eine Übergangslösung, da ich keine bessere Möglichkeit
> gefunden habe, den struct zurück zu setzen...
> Hat sich aber erledigt, wenn alles in ms gespeichert wird.

Man würde das so machen

void resetTime( TIME * time )
{
  time->Millisekunden = 0;
  time->Sekunden      = 0;
  time->Minuten       = 0;
  time->Stunden       = 0;
}

Aufruf:

   resetTime( &irgendeine_Time_Variable );

'Pass per Pointer' ist in C eine wichtige Technik. So wie in C++ ein 
'pass per reference' wichtig ist, wenn du vermeiden willst, dass von 
allem und jedem ständig eine Kopie erzeugt werden muss.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Erik Her schrieb:

>> Die ganze Menüsteuerung im main(), also der Teil mit state und den
>> Buttons, lässt sich auch in einem kurzen Array von Strukturen abbilden.
>   wie mache ich sowas?

So.
Ich habe den Code noch nicht kompiliert, da können daher noch ein paar 
Tippfehler drinnen sein.

Das Prinzip ist einfach.
Alles was es zu einem Menüpunkt zu sagen gibt, findet sich im Array Menu 
wieder. Dort ist verzeichnet, welche Texte ausgegeben werden sollen, 
welche Menüpunkte beim Drücken einer Taste 'aktiviert' werden sollen, ob 
es Funktionen gibt, die auf Tastendruck ausgeführt werden sollen etc.
Einfach alles, was es zu einem Menüpunkt gibt, ist dort hinterlegt.

Jeder Menüpunkt ist im Array und wenn ein Menüpunkt dazu kommt, bedeutet 
das lediglich eine neue Zeile im Array, in dem die Tasten mit den 
anderen Menüpunkten (über deren Index) verknüpft werden und eventuell 
(in seltenen Fällen) noch eine Spezialfunktion aufgerufen wird.

Die Funktion HandleMenu ist die 'eierlegende Wollmilchsau' die abhängig 
vom aktuellen Menüpunkt (in state) und der gedrückten Taste (die kriegt 
sie mit) die in diesem Array gespeicherten Informationen auswertet und 
abarbeitet.

OK. In Summ ist es dann doch ein wenig länger geworden. Allerdings hast 
du
* das komplette Menü an einer Stelle beisammen (im Array)
* bei Erweiterungen musst du nur einen neuen Eintrag im Array machen
  und ein paar Zahlen (die Indizes) anpassen um den Punkt in die
  logische Struktur des Menüs einzubinden. Mehr ist nicht notwendig

von Erik H. (agutanus)


Lesenswert?

wow! ich bin beeindruckt! in dieser kurzen Zeit eine Menüstruktur zu 
schreiben...

Ich habe mir gerade auch Gedanken darüber gemacht und dachte zu erst 
auch an etwas ähnliches - allerdings wusste ich nicht, dass ich in einem 
struct auch Funktionen speichern kann.
Das eröffnet ja ganz neue Möglichkeiten! ;-)
dieses
1
typedef void (*MenuFunc)( void );
 habe ich noch nie gesehen...
aber hier ist es erklärt: http://en.wikipedia.org/wiki/Typedef

Die Belichtungszeiten in ms werden nun in einem Array "uint32_t 
steps[28] = ..." gespeichert.
Zur Ausgabe der Zeiten werde ich nun ein Array mit JEDER Stufe (28) 
erstellen, in dem der Wert (zB 15 oder 500) und die Einheit (0-3 = 1/ - 
h) enthalten ist. Benötigt zwar mehr Speicherplatz (2 Byte je Stufe) als 
die Division der Millisekunden - aber ich denke das es weniger 
Rechenaufwand ist.
Belichtungszeiten selber (zB lzbTime) werden dann nur als int 
gespeichert (0...27) was dann dem Speicherort in einem der Arrays 
entspricht.

Gerade wollte ich das Menü noch folgendermaßen aufbauen:
2-dimensionales Array: menu[x][y]
x: Hauptmenü-Punkt
y: Unterpunkte
Jedes Element enthält ein int-Wert und 2 strings (Display Ausgabe)
in den y=0 Feldern ist die Zahl der Unterpunkte enthalten
in allen anderen je nach Bedarf zB Zeitstufen
Bei Tastendruck (zB "down") wird dann nur der y-Wert des gespeicherten 
states zu 1 addiert... (sofern y kleiner als die Zahl der Unterpunkte)

-> Aber das funktioniert nur solange sämtliche gespeicherten Werte 
Belichtungszeiten sind...

Also werde ich es wohl so ähnlich machen, wie Karl heinz Buchegger 
bereits vorgeschlagen hat.
Das mit den gespeicherten Funktionen erleichtert einiges!

von Karl H. (kbuchegg)


Lesenswert?

Erik Her schrieb:
> allerdings wusste ich nicht, dass ich in einem
> struct auch Funktionen speichern kann.
> Das eröffnet ja ganz neue Möglichkeiten! ;-)
> dieses
1
typedef void (*MenuFunc)( void );
 habe ich noch nie
> gesehen...
> aber hier ist es erklärt: http://en.wikipedia.org/wiki/Typedef

http://www.mikrocontroller.net/articles/FAQ#Funktionszeiger

von Erik H. (agutanus)


Lesenswert?

Was bedeutet eigentlich das
1
const char* guiText1;
im struct für die einzelnen Zustände?

Warum definiert man das nicht einfach als string?
1
char guiText1[];

welche Vorteile bring das?
Wie kann ich den String ausgeben?
Muss ich ihn als Zeiger oder als Variable übergeben?
1
lcd_puts(menuState[0].guiText);
oder:?
1
lcd_puts(menuState[0].*guiText);

von Rolf Magnus (Gast)


Lesenswert?

Erik Her schrieb:
> Was bedeutet eigentlich das
1
const char* guiText1;
im struct für die einzelnen Zustände?

Einen Zeiger auf einen konstanten char, der in diesem Fall der Anfang 
einer Zeichenkette ist.

> Warum definiert man das nicht einfach als string?
1
char guiText1[];

Diese Definition ist falsch. Ein String braucht eine Länge. Die muß hier 
zwingend angegeben werden.

> welche Vorteile bring das?

Daß nicht in allen Instanzen der Struktur ein String stecken muß, der so 
lang ist, wie der längste und daß man nicht darauf achten muß, daß man 
die Stringlänge immer an die größte Länge anpaßt.

> Wie kann ich den String ausgeben?
> Muss ich ihn als Zeiger oder als Variable übergeben?
1
lcd_puts(menuState[0].guiText);
oder:?
1
lcd_puts(menuState[0].*guiText);

Vergleiche mal den Typ, den lcd_puts übegeben haben will mit dem Typ von 
guiText.
Übrigens: Die zweite Zeile ist Quatsch. Du solltest in deinem C-Buch 
auch nachlesen, wie Arrays und Zeiger funktionieren.

von Erik H. (agutanus)


Lesenswert?

in der lcd.c ist die Ausgabe der Strings so definiert:
1
 void lcd_puts(const char *s)
2
/* print string on lcd (no auto linefeed) */
3
{
4
    register char c;
5
6
    while ( (c = *s++) ) {
7
        lcd_putc(c);
8
    }
9
10
}/* lcd_puts */

Dann kann ich die Zeiger also direkt übergeben:
1
 void printState(const uint8_t state)
2
{
3
  lcd_puts(menuState[state].guiText1);
4
  //u.s.w.
5
}
___________
edit: wer lesen kann ist klar im Vorteil:
im menu.c von Karl heinz Buchegger war es bereits genau so definiert... 
Hab ich erst jetzt gesehen. shame on me

von Karl H. (kbuchegg)


Lesenswert?

Erik Her schrieb:

> edit: wer lesen kann ist klar im Vorteil:
> im menu.c von Karl heinz Buchegger war es bereits genau so definiert...
> Hab ich erst jetzt gesehen. *shame on me*


Auch wenns nicht so gewesen wäre:

Arrays werden grundsätzlich so an Funktionen übergeben, dass die 
Startadresse des Arrays in Form eines Pointers übergeben wird.

Für die Funktion spielt es daher gar keine Rolle, ob du ein Array hast 
oder ob du 'nur' einen Pointer hast :-)

Aber in dem Fall ist ein Pointer besser. Der Compiler soll den Text 
irgendwo in den Speicher packen und die Startadresse des Textes in den 
Pointer packen. Wo der Text genau steht, ist dir ziemlich egal. Und da 
der Text auch nicht verändert/vergrößert werden soll, braucht auch nur 
der tatsächlich notwendige Speicher dafür bereitsgestellt werden. Ein 
Array wäre einfach Overkill gewesen. Vor allen Dingen deshalb, weil dann 
alle Menüpunkte immer dieselbe Arraygröße für ihre Texte hätten benutzen 
müssen.

von Erik H. (agutanus)


Angehängte Dateien:

Lesenswert?

ich habe mich mal dran gesetzt und das komplette Programm neu 
geschrieben...
Dabei habe ich mich stark an dem Beispiel von Karl heinz Buchegger 
gehalten.
(vielen Dank dafür!)

Allerdings hat sich nun die Speicherplatz-Verteilung stark verändert:
Version2:
Program:    3042 bytes (37.1% Full)
Data:        617 bytes (60.3% Full)

vorher:
Program:    3766 bytes (46.0% Full)
Data:        227 bytes (22.2% Full)

getestet habe ich es noch nicht, da noch einige Kleinigkeiten fehlen... 
(Anzeige während der Belichtung, usw)

von Karl H. (kbuchegg)


Lesenswert?

Erik Her schrieb:
> ich habe mich mal dran gesetzt und das komplette Programm neu
> geschrieben...
> Dabei habe ich mich stark an dem Beispiel von Karl heinz Buchegger
> gehalten.
> (vielen Dank dafür!)
>
> Allerdings hat sich nun die Speicherplatz-Verteilung stark verändert:
> Version2:
> Program:    3042 bytes (37.1% Full)
> Data:        617 bytes (60.3% Full)

Damit war, llogisch gesehen, zu rechnen. Bei dir war die Menülogik 
ausprogrammiert. Jetzt liegt die komplette Logik in Form von Daten im 
Speicher.

Die kriegst du noch runter, indem du zb die Texte ins Flash legst

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmspeicher_.28Flash.29

Auch die restlichen Menükonstanten kann man ins Flash auslagern.

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.