Forum: Mikrocontroller und Digitale Elektronik Timer: Display EINMAL alle x ms aktualisieren.


von Elektrotiger (Gast)


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 ;).

von Elektrotiger (Gast)


Lesenswert?

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.

von Peter II (Gast)


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
}

von Elektrotiger (Gast)


Lesenswert?

Autsch Danke :D.

von Karl H. (kbuchegg)


Lesenswert?

das flag volatile machen  nicht vergessen.

von W.S. (Gast)


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.

von Joachim B. (jar)


Lesenswert?

Peter II schrieb:
> einfach ein Flag in der ISR setzen.

hihi, genauso (mache ich es auch)

aber alle 330ms also 3x pro Sekunde weil die Sekunde ja nicht syncron 
mit dem Timer laufen muss, RTC vs. Timer ;-)


ISR
1
      if(lcd_updatetime) 
2
        lcd_updatetime--;

LOOP
1
  if(!lcd_updatetime)
2
    lcd_update();

LCD
1
void lcd_update(void)
2
{ 
3
.....
4
  lcd_updatetime=33;
5
}

von Elektrotiger (Gast)


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 ;).

von Elektrotiger (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von Elektrotiger (Gast)


Lesenswert?

Karl Heinz schrieb:
> Nur das die
> Einzelcountermethode auf Anhieb funktioniert und deine Kopfstände eben
> nicht.

Warum funktioniert mein System nicht ?

von Holger L. (max5v)


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).

von spess53 (Gast)


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

von Holger L. (max5v)


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.

von isidor (Gast)


Lesenswert?

Holger L. schrieb:
> Ist aber gut zu wissen das der Compiler den Wert in diesem Fall von dem
> Maximum abzieht,

Naj, warum einfach wenn's umständlich auch geht.

von Peter II (Gast)


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.

von Rudolph (Gast)


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.

von npn (Gast)


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.

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.