Forum: Mikrocontroller und Digitale Elektronik Kurze Frage zu Codeoptimierung


von Lukas B. (Gast)


Lesenswert?

Hallo,

ich habe nur eine kleine Frage zur Codeoptimierung einer Uhr. Und zwar 
rufe ich alle mithilfe einer ISR die main-Funktion alle 50ms auf und 
frage mich nun, ob es Sinn macht mit größeren Intervallen von z.B. 500ms 
zu arbeiten, da die Uhr nicht sonderlich genau geht. (ca. 5 Sekunden in 
einer Woche; oder ist das in Ordnung für einen AtMega 8, der mit einem 
4MHz Quarz getaktet ist?)

Folgender Code regelt den Aufruf:
1
if(millisekunden == 950 || millisekunden == 900 || millisekunden == 850 || 
2
     millisekunden == 800 || millisekunden == 750 || millisekunden == 700 ||  
3
       millisekunden == 650 || millisekunden == 600 || millisekunden == 550 ||  
4
     millisekunden == 500 || millisekunden == 450 || millisekunden == 400 ||  
5
     millisekunden == 350 || millisekunden == 300 || millisekunden == 250 || 
6
     millisekunden == 200 || millisekunden == 150 || millisekunden == 100 ||  
7
     millisekunden == 50  || millisekunden == 0)
8
      updateTime = 1; //setzen des Aktualisierungsflags

Alternativ kann ich das Hauptprogramm (solange man nicht im Menü ist) 
auch nur alle 500ms aufrufen. Doch hat man dadurch einen Vorteil 
gegenüber der ersten Variante oder kostet das "auswerten" der 
if-Bedingung genausoviel Zeit als ob ich dauerhaft im 50ms-Intervall 
arbeite?
1
if(mode != 0 && 
2
    (millisekunden == 950 || millisekunden == 900 || millisekunden == 850 || 
3
     millisekunden == 800 || millisekunden == 750 || millisekunden == 700 ||  
4
       millisekunden == 650 || millisekunden == 600 || millisekunden == 550 ||  
5
     millisekunden == 500 || millisekunden == 450 || millisekunden == 400 ||  
6
     millisekunden == 350 || millisekunden == 300 || millisekunden == 250 || 
7
     millisekunden == 200 || millisekunden == 150 || millisekunden == 100 ||  
8
     millisekunden == 50  || millisekunden == 0))
9
      updateTime = 1; //setzen des Aktualisierungsflags
10
11
  //ist der Anzeige-Modus aktiv, nur alle 500ms aktualisieren
12
  if(millisekunden == 500)
13
      updateTime = 1;

von Εrnst B. (ernst)


Lesenswert?

Lukas B. schrieb:
> if-Bedingung genausoviel Zeit als ob ich dauerhaft im 50ms-Intervall
> arbeite?

Uh.... hast du noch ein Byte RAM übrig? Bau damit einen zweiten Zähler, 
der nur dein Aktualisierungsinteral abmisst. So sparst du dir deine 
if-or-or-or-ORgie.

Dann:

Lukas B. schrieb:
> (ca. 5 Sekunden in
> einer Woche; oder ist das in Ordnung für einen AtMega 8, der mit einem
> 4MHz Quarz getaktet ist?)

Jo, ganz normal. Kannst entweder versuchen den Quarz mit einem Dreko zu 
ziehen, oder per Software ausgleichen.

AVR - Die genaue Sekunde / RTC

von Michael A. (Gast)


Lesenswert?

Lukas B. schrieb:
> ... da die Uhr nicht sonderlich genau geht. (ca. 5 Sekunden in
> einer Woche

Das läßt sich besser hinkriegen, wenn der Quarz nicht wilden 
Temperaturschwankungen ausgesetzt ist.
Beitrag "Die genaue Sekunde / RTC"

von Ralf G. (ralg)


Lesenswert?

Die Intervalle dürften keinen Einfluss auf die Genauigkeit haben. Außer: 
sind die 50ms rechnerisch wirklich exakt 50ms?

von crazy horse (Gast)


Lesenswert?

if ((millisekunden%50)==0)   //Rest der Division=0?

von Lukas B. (Gast)


Lesenswert?

Wenn die Ungenauigkeit normal ist, stört sie mich nicht. Auf ein Jahr 
hochgerechnet sind das ja gerade mal ~4 Minuten pro Jahr, damit kann ich 
leben, zumal der Wecker sowieso alle 6 Monate gestellt werden muss 
(Sommer-, Winterzeit).
Für eine RTC habe ich leider keinen Port mehr frei, zumindest keinen von 
den Interrupt-Ports.

@crazy horst: Danke, das sieht besser aus.

von Εrnst B. (ernst)


Lesenswert?

Lukas B. schrieb:
> @crazy horst: Danke, das sieht besser aus.

Das sagst du jetzt, bevor du gesehen hast, wieviel Code der Compiler aus 
dem harmlos aussehenden '% 50' macht und wie lang er dann in deiner ISR 
rechnet...

Lukas B. schrieb:
> Für eine RTC habe ich leider keinen Port mehr frei

Sowohl der von mir verlinkte Artikel als auch Michaels Forums-Link (aus 
dem der Artikel hervorgegangen ist) enthalten Beispiel-Code wie man 
ohne extra RTC-Chip rein softwaremäßig den falsch Laufenden Quarz 
ausgleicht.

von rudi (Gast)


Lesenswert?

Lukas B. schrieb:
> Wenn die Ungenauigkeit normal ist, stört sie mich nicht.
zumal der Wecker sowieso alle 6 Monate gestellt werden muss
(Sommer-, Winterzeit)
Warum "hängst" du dich nicht an die Netzfrequenz? Die EVUs sorgen schon 
dafür, dass Uhren, die die Netzfrequenz als Normal nutzen, nicht "falsch 
gehen".

von Lukas B. (Gast)


Lesenswert?

@Εrnst B✶: Also doch wieder if(...||...,usw.)? Oder wie sieht deine 
Lösung in der Praxis aus? Ich kann mir das nicht so ganz vorstellen.

@RTC: Ich gucke es mir mal an.

von Peter II (Gast)


Lesenswert?

braucht du denn die Millisekunden überhaupt? Wenn nein warum arbeits du 
nicht in 50 Millisekunden schritten. Also in Vielfachen von 50ms.

von Lukas B. (Gast)


Lesenswert?

Nein, ich brauche die Millisekunden nicht. Also müsste ich den Timer 
anders einstellen, sodass er nur alle 50ms aufgerufen wird, richtig?

von Peter II (Gast)


Lesenswert?

Lukas B. schrieb:
> Also müsste ich den Timer
> anders einstellen, sodass er nur alle 50ms aufgerufen wird, richtig?

ja oder wenn das nicht geht (wegen teiler) dann kannst du auch im timer 
bis 50 zählen und dann erst die 50ms-Variable hochzählen.

Dann kannst du auch gleich aus dem 16bit wert ein 8bit wert machen, dann 
rechnet sich dann für den µC einfacher.

von Lukas B. (Gast)


Lesenswert?

Peter II schrieb:
> Dann kannst du auch gleich aus dem 16bit wert ein 8bit wert machen, dann
> rechnet sich dann für den µC einfacher.

Wie mache ich das denn?

von Peter II (Gast)


Lesenswert?

Lukas B. schrieb:
> Wie mache ich das denn?

u_int18 millisekunden  -> u_int8 millisekunden

von Lukas B. (Gast)


Lesenswert?

Momentan ist der Datentyp unsigned int, aber wenn ich ihn auf uint8_t 
(etwas anderes erkennt der Compiler nicht) ändere, wird nichts mehr 
hochgezählt.

von Murx (Gast)


Lesenswert?

Lukas B. schrieb:
1
> if(millisekunden == 950 || millisekunden == 900 || millisekunden == 850 || 
2
>      millisekunden == 800 || millisekunden == 750 || millisekunden == 700 ||  
3
>        millisekunden == 650 || millisekunden == 600 || millisekunden == 550 ||  
4
>      millisekunden == 500 || millisekunden == 450 || millisekunden == 400 ||  
5
>      millisekunden == 350 || millisekunden == 300 || millisekunden == 250 || 
6
>      millisekunden == 200 || millisekunden == 150 || millisekunden == 100 ||  
7
>      millisekunden == 50  || millisekunden == 0)

ist schon deswegen ungünstig, weil die Laufzeit für
den Fall "millisekunden == 950" anders ist als für den Fall
"millisekunden == 0" (wegen "short-circuit evaluation" von logischen 
Ausdrücken in C).

Spielt vielleicht im vorliegenden Fall nicht so die Rolle, aber hässlich
aussehen tut´s in jedem Fall.

Murx

von Michael A. (Gast)


Lesenswert?

Lukas B. schrieb:
> Für eine RTC habe ich leider keinen Port mehr frei, zumindest keinen von
> den Interrupt-Ports.

Seit wann braucht Software eine Port?
Ein Click ...

von Lukas B. (Gast)


Lesenswert?

@Michael: Das war nur ein Missverständnis, ich dachte bei RTC an einen 
externen Baustein.

@Murx: Ich habe es jetzt so gelöst, dass die ISR nur alle 50ms 
aufgerufen wird, ich denke, das ist die eleganteste Lösung. Nur das 
Problem mit den 16-bit Variablen ist irgendwie seltsam.

von Peter II (Gast)


Lesenswert?

Lukas B. schrieb:
> Momentan ist der Datentyp unsigned int, aber wenn ich ihn auf uint8_t
> (etwas anderes erkennt der Compiler nicht) ändere, wird nichts mehr
> hochgezählt.

uint8_t geht ja auch nur bis 255 - da passen deine 1000ms nicht rein. 
Aber wenn du in 50ms schritten arbeitets dann brauchst du nur 0-200 und 
das passt rein.

Zeig uns doch mal das ganze programm, wenn du immer int verwendest, hast 
du noch viel mehr optimierungsmöglichkeiten als die IF abfrage.

von Lukas B. (Gast)


Angehängte Dateien:

Lesenswert?

Stimmt, du hast recht, jetzt funktioniert es. :D

Der gesamte Code befindet sich im Anhang. Wenn ihr noch Fehler oder 
Optimierungspotential findet, sagt Bescheid.

P.S. Das ist mein erstes richtiges Programm, ich bitte um Nachsicht. ;)

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.