Timer: Display EINMAL alle x ms aktualisieren.

Gast #4001180
Lesenswert?
• ▲
▼
Ich habe Timer0 so implementiert, so dass alle 10ms ein Interrupt 
ausgelöst wird. Nun möchte ich nach einer bestimmten Zeit z.B. , dass 
alle 0.5 Sekunden das Display EINMAL aktualisiert wird. Wie 
implementiere ich dies richtig?
1
uint8_t counter = 0;
2

3
void timer0()
4
{
5
  TCCR0 = (1<<CS02)|(1<<CS00);         // divide by 1024
6
  TCNT0 = (-72);  // preload for 10ms
7
  TIMSK |= 1<<TOIE0;                   // enable timer interrupt
8
}
9

10
ISR( TIMER0_OVF_vect )                            // every 10ms
11
{
12
  static uint8_t ct0, ct1, rpt;
13
  uint8_t i;
14
 
15
  TCNT0 = (-72);  // preload for 10ms
16
  counter++;
17
  if(counter==100)  // 1 Sekunde
18
  {
19
  sekunden++;
20
  counter=0;
21
  }  
22

23

24
uint8_t ms_Zehn(uint16_t n)
25
{
26
  uint8_t status=0;
27
  if((counter%n==0)&&(TCCR0-old_tccr0 != 0))return status=1;
28
  else return status=0;  
29
}
30

31
int main( void )
32

33
while(1)
34
{
35
if ((ms_Zehn(50))==1) aktualisiere();
36
}

Mein Problem liegt vorallem darin, dies nur einmal auszuführen. Aktuell 
aktualisiert der das quasi 10ms konsiquent durch und dass alle 500ms.

PS: Aktuell ist counter mit bis 100 begrenzt, mir ist schon bewusst,dass 
meine aktuelle Funktion nur bis 100*ms_Zehn sinn ergibt ;).
Gast #4001191
Lesenswert?
• ▲
▼
Elektrotiger schrieb:
> Mein Problem liegt vorallem darin, dies nur einmal auszuführen. Aktuell
> aktualisiert der das quasi 10ms konsiquent durch und dass alle 500ms.

einfach ein Flag in der ISR setzen.
1
if ( ..) {
2
  flag_update_display = 1
3
}
4

5

6

7
//main
8

9
if ( flag_update_display ) {
10
   flag_update_display = 0;
11
   UpdateDisplay();
12
}
Gast #4001215
Lesenswert?
• ▲
▼
Elektrotiger schrieb:
> Nun möchte ich nach einer bestimmten Zeit z.B. , dass
> alle 0.5 Sekunden das Display EINMAL aktualisiert wird

Und warum?
Am sinnvollsten ist es doch, das Display nur dann zu aktualisieren, wenn 
einerseits eine sinnvolle Zeit (z.B. 50 ms) verstrichen ist UND du 
irgend etwas am Displayinhalt geändert hast. Sonst ist das Ganze doch 
überflüssig.

W.S.
Gast #4001249
Lesenswert?
• ▲
▼
W.S. schrieb:
> Am sinnvollsten ist es doch, das Display nur dann zu aktualisieren, wenn
> einerseits eine sinnvolle Zeit (z.B. 50 ms) verstrichen ist UND du
> irgend etwas am Displayinhalt geändert hast. Sonst ist das Ganze doch
> überflüssig.

Da es sich hier um das Anzeigen der ADC Werte der Eingänge des 
Mikrocontroller handelt, die die Lichtintensitäten der Lichtwellenleiter 
dauerhaft prüfen, muss quasi wirklich permanent das Display aktualisiert 
werden ;).
#4001262
Lesenswert?
• ▲
▼
Elektrotiger schrieb:
> Joachim B. schrieb:
>> ISR      if(lcd_updatetime)
>>         lcd_updatetime--;
>
> Sinnvoll wenn man nicht gerade 10 verschiedene Timer braucht ;).
> Da lass ich anstelle von 10 Countern runterzählen lieber einen Counter
> hochzählen und bei gewissen Werten ein Flag setzen.


Bringt dir aber nichts.

Am Beispiel einer Uhr und Sekundenzeiger
Selbst wenn du an der Sekunde 12, 28, und 37 jeweils einen Schaltkontakt 
anbringst, schalten die trotzdem alle im 60 Sekunden Intervall. Sie 
schalten zu verschiedenen Zeiten, aber das Schaltintervall ist immer 
dasselbe, da dieses nur davon abhängt, wie lange der Zeiger für einmal 
rundum benötigt.

Für nicht verbrauchtes SRAM gibt es kein Geld zurück. Ob du da besonders 
clevere Kopfstände machst, oder einfach für jeden periodischen Vorgang 
einen eigenen Counter machst ist so gesehe egal. Nur das die 
Einzelcountermethode auf Anhieb funktioniert und deine Kopfstände eben 
nicht.
#4001273
Lesenswert?
• ▲
▼
Elektrotiger schrieb:
> Des Weiteren möchte ich dies nicht in den Interrupt packen, da dies nur
> ein Bruchteil meines gesamten Projektes beinhaltet. Der Interrupt sollte
> so leer wie nur möglich sein.

SO leer wie möglich bedeutet nicht, dass man gar nichts machen darf. 
Einen Counter decrementieren (speziell wenn es ein uint8_t ist) kostet 
praktisch nichts. Wenn du die paar Taktzyklen nicht hast, hast du ein 
ganz anderes Problem.
#4001322
Lesenswert?
• ▲
▼
Hätte da noch eine kleine Anmerkung zu TCNT0 der in dem Codeausschnitt 
mit einem negativen Wert vorgeladen wird.

Elektrotiger schrieb:
> TCNT0 = (-72);  // preload for 10ms

Ich weiß nun nicht welcher µC dort verwendet wird, aber laut 
Datenblättern ist der untere Wert von TNCT0 0x00 und demnach sollte eine 
negative Zahl nicht funktionieren ?!

The counter simply overruns when it passes its maximum 8-bit value (TOP 
= 0xFF) and then restarts from the bottom
(0x00).
Gast #4001380
Lesenswert?
• ▲
▼
Hi

>Ich weiß nun nicht welcher µC dort verwendet wird, aber laut
>Datenblättern ist der untere Wert von TNCT0 0x00 und demnach sollte eine
>negative Zahl nicht funktionieren ?!

Na und? Da schreibt der Compiler einfach 184 rein. Aber das Vorladen ist 
generell unnötig. Die Timer der AVRs können alle CTC.

MfG Spess
#4001416
Lesenswert?
• ▲
▼
Das mit dem CTC Modus ist klar, es ging nur darum das er sich wohl was 
dabei gedacht hatte diesen Wert zu verwenden, bzw. hätte es auch einen 
Trick geben können den Timer auch mit negativen Zahlen zu verwenden.
Ist aber gut zu wissen das der Compiler den Wert in diesem Fall von dem 
Maximum abzieht, das kann bestimmt irgendwann einmal nützlich seien.
Gast #4001422
Lesenswert?
• ▲
▼
Holger L. schrieb:
> Ist aber gut zu wissen das der Compiler den Wert in diesem Fall von dem
> Maximum abzieht, das kann bestimmt irgendwann einmal nützlich seien.

das macht er nicht wirklich. er scheibt einfach die 8bit in die Variable 
und gut ist. Er rechnet nichts um.

Binär sehen beide Zahlen gleich aus.
Gast #4001428
Lesenswert?
• ▲
▼
Warum willst Du alle 0,5 ms das komplette Display aktualisieren?
Damit ist der Controller doch eine kleine Ewigkeit beschäftigt in der 
nichts anderes mehr passiert.

Schick dem Display doch einfach alle xx ms das nächste Zeichen aus dem 
Puffer oder den Zeilenwechsel.
Die Operation ist in wenigen µs gelaufen.

Ich spendiere meinen Displays auch immer einen Puffer weil ich den von 
beliebigen Programm-Teilen aus beliebig oft beschreiben kann ohne auf 
irgendwas warten zu müssen.
Und je nach Anforderung wird der Output dann so abgestimmt das genug 
Wechsel pro Sekunde auf dem Display ankommen.

Schnell ist so ein LCD ja ohnehin nicht.
Gast #4001431
Lesenswert?
• ▲
▼
Peter II schrieb:
> Holger L. schrieb:
>> Ist aber gut zu wissen das der Compiler den Wert in diesem Fall von dem
>> Maximum abzieht, das kann bestimmt irgendwann einmal nützlich seien.
>
> das macht er nicht wirklich. er scheibt einfach die 8bit in die Variable
> und gut ist. Er rechnet nichts um.
>
> Binär sehen beide Zahlen gleich aus.

Richtig.

@Holger:
Und technisch gesehen machst du ja bei der Berechnung des Vorladewertes 
auch nichts anderes. Du bekommst heraus, daß der Timer 72 Takte 
benötigt, um auf die gewünschte Frequenz bzw. Zeit zu kommen. Dann 
ziehst du die 72 vom maximalen Wert (255) ab und bekommst die Zahl, mit 
der du den Timer vorlädtst. Statt dessen kannst du auch gleich -72 
schreiben.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.