www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer für Zeitbasis vorladen: Denkfehler?!


Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Forum!

Ist mir zwar n bissl peinlich, aber ich muß hier mal eine Anfängerfrage 
in die Runde stellen, weil ich irgendwie glaube einen Denkfehler zu 
haben. Ich dachte das hätte ich hinter mir... ;).

Also, ich möchte gern eine Zeitbasis von 1 ms erzeugen. Dafür hab ich 
einen Mega8, mit 8 MHz Quarz. Aus verschiedenen Gründen ist es nun so, 
daß ich das mit Timer2 im, bitte nicht wundern, PWM-Modus mache.

So, der Prescaler ist auf 32 gestellt, läuft der Timer also mit einem 
Takt von 250 kHz. Und das heißt ja, daß er alle 250 Takte/Zählschritte 
einen Interrupt schmeißen muß, damit ich 1 ms bekomme.

Wenn des Timers Obergrenze 255 ist und er beim nächsten hochzählen 
überläuft und wieder auf 0 springt, wäre das also der 256ste 
Zählschritt. Also lade ich den Timer in der ISR immer mit 6, weil 256 
- 6 = 250. Dachte ich...

Jetzt hab ich aber innerhalb von 24 Stunden eine Differenz von ca. -5,5 
Minuten. Das sind rund 330000 ms, die das Teil innerhalb von 86400000 ms 
(24 Stunden) verliert.

Dann wollte ich errechnen innerhalb von wieviel Millisekunden mein 
Controller eine Millisekunde verliert. Also:
86400000 / 330000 = 262 (ca.).

Da hat mich zum einen verduzt, daß der Wert recht klein ist (alle 262 ms 
um eine ms falsch zu gehen ist schon echt mal doof), und zum anderen, 
daß der Wert bedenklich nah an 0xFF liegt. Ich konnte mir aber noch 
nicht erklären, warum!
Weil es sich also fast genau um 1 / 256stel handelt könnte ich den 
Fehler wohl stark reduzieren, wenn ich den Timer immer mit 7 vorlade. 
Aber DAS versteh ich nicht, weil ich doch dann eigentlich einen 
Zählschritt zu wenig habe, oder?!

Würde mich echt freuen, wenn ihr mir helft meinen gedanklichen Knick zu 
finden!

MfG,
Joachim

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

meine Vermutung: Weil es ein bisschen dauert, bis die ISR anläuft.

Gruß
Lasse

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hättest nicht den Quelltext verbal beschreiben müssen, denn sowas ist 
nutzlos.

Am besten ein auf den Fehler reduziertes Testprogramm als Anhang.
Zumindest aber die Initialisierung und den Interrupthandler.

Dabei natürlich die vordefinierten Bitnamen verwenden, denn keiner hat 
Lust, erstmal alle Hexwerte umzurechnen, um den Code zu verstehen.


Peter

Autor: Timo D. (lorvorne)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

dachte auch zuerst an einen delay, aber der sollte annähernd fix sein
und sich nicht aufsummieren. Heißt, er käme nur einmal zum Tragen.

Aber:
5.5min nach 24h sind lediglich 0.4% Fehler. Ist denn Deine Zeitbasis
(Quarz) so exakt oder läuft er einfach nur mit 8MHz -0.4%?

Gruß,
Timo

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter:
ok, stimmt natürlich. Das Prog ist aber schon sehr umfangreich, aber der 
relevante Code nur ein Bruchteil davon. Aber ok, ich zeige mal das 
"wichtigste":
// initial value for counter -> 250 counting steps
TCNT2 = 6;

// fast non-inverting PWM mode, count till 0xFF
TCCR2 |= ( (1<<WGM21) | (1<<WGM20) );

// activate timer 2 overflow interrupt
TIMSK |= (1<<TOIE2);

/*
ganz viel code
*/

ISR(TIMER2_OVF_vect)
{
TCNT2 = 6;
    
ms_counter++;

ms_correction++;

/* soll zur Korrektur dienen, irgendwann mal
if(ms_correction == 269)
{
  ms_correction = 0;
  //ms_counter++;
}*/

@Timo:
hm, ich finde einen Fehler von 0,4% für ein zeitgebendes Teil eigentlich 
arg viel. Darum hab ich den Fehler erstmal pauschal auf die Software und 
nicht auf die Hardware geschoben...

Autor: Timo D. (lorvorne)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, sorry. Hast ja QUARZ geschrieben.
Ist also eher unwahrscheinlich, dass der generell 0.4% zu langsam
wäre.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Joachim A. (jojo84)

>hm, ich finde einen Fehler von 0,4% für ein zeitgebendes Teil eigentlich
>arg viel. Darum hab ich den Fehler erstmal pauschal auf die Software und
>nicht auf die Hardware geschoben...

Richtig! Denn 0,4% von 250 Takten sind exakt 1 Takt. Dein Vorladewert 
ist falsch. Dein Zähler zählt 6..255, 0, 6. Das sind 251 Takte ;-) Also 
eher Vorladewert 7.

Sinnvollerweise nimmt man beim AVR den CTC-Modus. Dort mit dem 
Vergleichswert 249, denn der zählt dann von 0..249. Siehe auch

AVR - Die genaue Sekunde / RTC

MfG
Falk

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da fehlt noch das Setzen des Prescalers.
Hast Du es mal simuliert?

Lt. Datenblatt wird der Overflow im PWM-Mode schon gesetzt bei 0xFF und 
nicht erst bei 0x00.

Ich bin mir auch ziemlich sicher, daß PWM und Reload des Timers im 
Interrupt Probleme machen:

"Writing to the TCNT2 Register blocks (removes) the Compare
Match on the following timer clock. Modifying the counter (TCNT2) while 
the counter is running,
introduces a risk of missing a Compare Match between TCNT2 and the OCR2 
Register."


Du hast doch 3 Timer, dann nimm besser unterschiedliche Timer als PWM 
und als Zeitbasis.


Peter

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk:
danke für deine Antwort. Daß da irgendwas mit meinem Vorladewert nicht 
stimmt habe ich ja auch schon erkannt. Wenn auch etwas ausschweifend hab 
ich oben ja schon angemerkt, daß ein Vorladen von 7 wohl was bringen 
würde.
ABER: ich will ja wissen, warum das so ist!

Der Interrupt wird ja ausgelöst, wenn der Timerwert durch eine 
Überschreitung von 0xFF wieder auf 0 springt. Aber ich lade den Wert ja 
in der ISR sofort wieder mit 6. Da hab ich mir das so vorgestellt, daß 
der nicht so zählt, wie du geschrieben hast (6...255, 0, 6), sondern 
"quasi" 6...255, 6...255 usw, weil ja sofort beim erreichen von 0, also 
direkt in der ISR, da die 6 reingeschrieben wird...

Wo kommt bei dir die 0 her, die du effektiv mitzählst?

P.S.: Daß dafür Normalerweise der CTC-Mode benutzt wird war mit bewußt. 
Aber ich hab an OC2 eine Led hängen, die gedimmt wird, und da hielt ich 
es für schlau die Trägerfrequenz der PWM auf 1 kHz zu stellen, weil ich 
dann nur einen einzigen Timer für die PWM und die Zeitbasis brauche...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim A. schrieb:

> P.S.: Daß dafür Normalerweise der CTC-Mode benutzt wird war mit bewußt.
> Aber ich hab an OC2 eine Led hängen, die gedimmt wird, und da hielt ich
> es für schlau die Trägerfrequenz der PWM auf 1 kHz zu stellen, weil ich
> dann nur einen einzigen Timer für die PWM und die Zeitbasis brauche...

Deine Uhr wird sowieso nie genau gehen, weil dein Quarz nun mal nicht 
exakt 8000000 Schwingungen/Sekunde macht. Genau deshalb nimmt man den 
CTC. Weil es dort am einfachsten ist, den Timer eine exakte Anzahl an 
Taktzyklen abzählen zu lassen. Und zwar auf den Zyklus genau.

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Peter
ups, ich glaub da bin ich in der Tabelle in der Zeile verrutscht. 
Stimmt, da steht ja "TOV2 Flag Set" bei MAX (0xFF). Aber das würde ja 
heißen, daß er einen Zählschritt weniger macht, als ich ganz oben 
angenommen habe -> also quasi zu schnell laufen, und nicht nachgehen 
(was er aber tut).

Warum ich das mit dem Timer und dem PWM-Mode gemacht habe habe ich ja 
grad beschrieben. Das Schreiben ins TCNT-Register dürfte doch aber dann 
trotzdem auf das stumpfe Zählverhalten keinen einfluß nehmen. Und ob bei 
der gedimmten LED dann ein Compare Match ausbleibt ist in der Anwendung 
total egal...

Trotzdem Danke für den Tip!

@Karl Heinz
danke für den Hinweis. Der Ungenauigkeit bin ich mir bewußt. Ist aber in 
dem vorliegenden Projekt egal und zu vernachlässigen. Der Drift wird 
auch später noch per SW weitestgehend minimiert =)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Joachim A. (jojo84)

>Überschreitung von 0xFF wieder auf 0 springt. Aber ich lade den Wert ja
>in der ISR sofort wieder mit 6. Da hab ich mir das so vorgestellt, daß
>der nicht so zählt, wie du geschrieben hast (6...255, 0, 6), sondern
>"quasi" 6...255, 6...255 usw, weil ja sofort beim erreichen von 0, also
>direkt in der ISR, da die 6 reingeschrieben wird...

Und was glaubst du, wie schnell deine CPU in der ISR landet und den 
Timer mit dem Vorladewert beschreiben kann? Egal wie schnell es ist, 
erst auf dem Wechsel von 0xFF nach 0x00 wird der Interrupt ausgelöst, 
die Null steht somit IMMER im Timer drin. Das Anspringen der ISR und 
scheiben des Timers dauert in C rund ein Dutzend Takte, selbst in ASM 
wären es min. 4 + 2.

>Wo kommt bei dir die 0 her, die du effektiv mitzählst?

Die zähle ich nicht effektiv mit, die ist real ;-)

>P.S.: Daß dafür Normalerweise der CTC-Mode benutzt wird war mit bewußt.
>Aber ich hab an OC2 eine Led hängen, die gedimmt wird, und da hielt ich
>es für schlau die Trägerfrequenz der PWM auf 1 kHz zu stellen, weil ich
>dann nur einen einzigen Timer für die PWM und die Zeitbasis brauche...

Du bekommst für nicht benutzte Timer kein Geld von Atmel zurück. Ich bin 
zwar auch der Typ, der es möglichst kompakt und clever (tm) anstellen 
will, aber auf Krampf Timer sparen ist sinnlos.

MFG
Falk

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk:
nun mach mir doch mal die Idee nicht so madig... ;) ich fand das so 
geschickt, als ich mir das ausgedacht hab ;) ...

Ich bin fast Lipper, und die sind ja bekanntlich geizig ;) ! Wenn ich 
den CTC-Mode hätte verwenden wollen, dann hätte ich das ja mit dem 
16-Bit-Timer1 machen müssen, aber für so eine "einfache" Sache wollte 
ich keinen 16-Bit-Timer mit zwei PWM-Kanälen und so opfern. Purer Geiz 
eben...

Kannst du mir vielleicht sagen, wie du auf die Anzahl der benötigten 
Takte gekommen bist? Ich möchte das gern selbst auch nachvollziehen 
können.

Aber so ganz check ich das immer noch nicht. Angenommen beim Wechsel von 
0xFF auf 0x00 wird die ISR angesprungen. Das dauert dann in C z.B. 15 
Takte. Das Nächste ist doch dann direkt das Schreiben von 6 ins TCNT. 
Das kann doch aber kaum 17 Takte dauern -_o !
Selbst wenn es auch 15 Takte dauern würde, dann stünde nach 30 Takten 
dann 6 in dem Register. Zwei Takte später, also direkt beim nächsten 
Timertakt (Prescaler 32) wird der Timer dann um 1 erhöht, also auf 7.
Auf dieser Vorstellung basierte meine Frage, wo du die 0 wegnimmst, die 
du effektiv mitzählst, und die da auch real zu sein scheint ...

MfG

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Interrupt wird beim Wechsel von 255->0 ausgelöst. Da es effektiv 
keine halben Takte gibt hat der Timer also bestenfalls den Wert 0 wenn 
du die ISR betrittst (je nach prescaler und setup code).

Ansonsten ist es einfach so: Wozu sparen wenn die HW sonst brach liegt? 
Und wenn es der 16bit Timer ist sowhat? Das "sparen" was du beschreibst 
hat dich jetzt schon einige Stunden an Zeit und Mühe gekostet (und nicht 
nur dich!).

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich hab es doch eingesehen, daß es mit einem weiteren Timer 
vielleicht geschickter gewesen wäre!
Aber darum geht es mir doch gar nicht! Ich will meine Lösung doch 
überhaupt nicht rechtfertigen oder verteidigen.
Ich wollte doch einfach nur wissen, wo der Unterschied zwischen meiner 
Denkweise/Rechnung und dem realen Verhalten des Controllers liegt.
Ich will keinen von meiner Sache überzeugen, und auch nicht, daß hier 
457 Leute meinen Code nach Fehlern analysieren.

@Läubi:
daß ich deine Zeit in Anspruch genommen habe hast du dir ausgesucht ;)
Aber mental bin ich immer noch nicht weiter, als vorher. Ich weiß ja, 
daß ich n bissl sehr ausführlich schreibe. Das mach ich aber, weil ich 
mein Problem und die Gedanken, die ich mir über gemacht hab, im Vorfeld 
möglichst genau erläutern möchte. Das müßte aber aus meinen Romanen auch 
hervor gehen ;) ...

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wollte nur andeuten das einem das sparen manchmal doch recht teuer 
kommt ;) Warum es Abweichungen geben kann wurde ja nun schon einige 
Beispiele genannt. Im Zweifel ASM Listing analysieren, simulieren oder 
Takte per Hand zählen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob man jetzt sagt, der Timer zählt
    254, 255, 6, 7, 8 ...

oder

    254, 255, 0,    7, 8, ...
                 ^
                 |
             hier wird die 0 gegen eine 6 ausgetauscht

kommt taktmässig aufs selbe raus. Von einer 255 bis zur nächsten 
vergehen 250 Zählertakte.

  248 Takte um von 7 bis 255 zu zählen
+   1 um von 255 auf 0 zu zählen
+   1 um von der getürkten 6 (die eine 0 war) auf 7 zu zählen
-----
  250 Takte

Was gerne übersehen wird: Auch der Vorgang von 255 auf 0 ist ein ganz 
normaler Zähltakt.

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl Heinz:
*verbeug.* echt nett, daß du dir die Mühe machst mir den Kram 
auseinander zu klamüsern.
Halt mich jetzt nicht für vollkommen beschränkt. Aber entspricht die 
Rechnung, die du aufgestellt hast, nicht auch meiner aus Post #1?
- Ich lade da ne 6 rein
- dann dauerts 249 Takte, bis er bei 255 ankommt
- und dann noch ein Takt (250), um über zu laufen, den Interrupt aus zu 
lösen und wieder bei 0 anzufangen bzw. mit 6 geladen zu werden?!
Deinen Hinweis mit dem mitzurechnenden Zählertakt von 255 auf 0 hab ich 
ja von anfang an mit berücksichtigt.
Tut mir echt Leid, normalerweise stell ich mich nicht so blöd an, aber 
ich check grad echt nicht den Unterschied von deinem Zählweise im obigen 
Post zu meiner Zählweise *seufz.*

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Joachim A. (jojo84)

>Kannst du mir vielleicht sagen, wie du auf die Anzahl der benötigten
>Takte gekommen bist? Ich möchte das gern selbst auch nachvollziehen
>können.

Siehe Datenblatt unter Interrupt Response Time. Der AVR braucht 4 
Takte zum Ereichen der ISR, dann braucht man halt min. 2 Befehle/Take, 
um den Timer neu zu schreiben.

>Aber so ganz check ich das immer noch nicht. Angenommen beim Wechsel von
>0xFF auf 0x00 wird die ISR angesprungen.

Erst mal AUSGELÖST. Gesprungen wird einen Takt später.

> Das dauert dann in C z.B. 15
>Takte. Das Nächste ist doch dann direkt das Schreiben von 6 ins TCNT.
>Das kann doch aber kaum 17 Takte dauern -_o !

Bist du sicher? Schau dir den Assemblercode deines Programms an. Steht 
im *.lss File. Kannst du ja mal posten. Als Anhang.

>Selbst wenn es auch 15 Takte dauern würde, dann stünde nach 30 Takten
>dann 6 in dem Register. Zwei Takte später, also direkt beim nächsten
>Timertakt (Prescaler 32) wird der Timer dann um 1 erhöht, also auf 7.
>Auf dieser Vorstellung basierte meine Frage, wo du die 0 wegnimmst, die
>du effektiv mitzählst, und die da auch real zu sein scheint ...

AFAIK ist Timer2 etwas anders, weil er auch asynchron arbeiten kann. 
Deshalb ist der Timerzugriff dort nicht direkt und sofort! Erst mit dem 
nächsten oder gar übernächtsten Timertakt werden deine Werte übernommen, 
welche zwischendurch in einem (unsichtbaren) Zwischenpuffer landen. Das 
ist zumindest im asynchronen Betrieb so (Taktung mit ext. 32 kHz Quarz). 
Ich kann mir vorstellen, dass es im synchronen Betrieb ähnlich ist.

MFG
Falk

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk Brunner schrieb:
> @  Joachim A. (jojo84)
>
>>Kannst du mir vielleicht sagen, wie du auf die Anzahl der benötigten
>>Takte gekommen bist? Ich möchte das gern selbst auch nachvollziehen
>>können.
>
> Siehe Datenblatt unter Interrupt Response Time. Der AVR braucht 4
> Takte zum Ereichen der ISR, dann braucht man halt min. 2 Befehle/Take,
> um den Timer neu zu schreiben.

Schon klar.
Aber er hat einen Prescaler von 32.
Normalerweise müsste das massig ausreichen um den Timer zu mainpulieren.
Auf der anderen Seite: erst das Assemblerlisting zeigt die Wahrheit :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim A. schrieb:

> Tut mir echt Leid, normalerweise stell ich mich nicht so blöd an, aber
> ich check grad echt nicht den Unterschied von deinem Zählweise im obigen
> Post zu meiner Zählweise *seufz.*

Ich muss gestehen.
Es hat mich auch verwirrt. Mit einer der Gründe warum ich Timer reload 
nicht mag :-) So ganz ist mir immer noch nicht klar, wie da ein Fehler 
von 0.4% entstehen kann. Sicher, dass der Mega8 mit dem Quarz und nicht 
etwa mit dem internen Oszillator läuft? Obwohl: 0.4% wäre für den wieder 
ein ausgezeichneter Wert.


Hmm. Wenn das mit der Interrupt Latenz zusammenhängt, könnte man ja mal 
einen größeren Vorteiler benutzen und sehen ob das einen Unterschied 
macht.

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Karl Heinz:
puh, da bin ich ja froh ;)

@all:
also der Anfang der ISR sieht im Listing so aus:
ISR(TIMER2_OVF_vect)
{
     1da:  1f 92         push  r1
     1dc:  0f 92         push  r0
     1de:  0f b6         in  r0, 0x3f  ; 63
     1e0:  0f 92         push  r0
     1e2:  11 24         eor  r1, r1
     1e4:  2f 93         push  r18
     1e6:  3f 93         push  r19
     1e8:  4f 93         push  r20
     1ea:  5f 93         push  r21
     1ec:  6f 93         push  r22
     1ee:  7f 93         push  r23
     1f0:  8f 93         push  r24
     1f2:  9f 93         push  r25
     1f4:  af 93         push  r26
     1f6:  bf 93         push  r27
     1f8:  ef 93         push  r30
     1fa:  ff 93         push  r31
  TCNT2 = 7;
     1fc:  87 e0         ldi  r24, 0x07  ; 7
     1fe:  84 bd         out  0x24, r24  ; 36
...
...
}

*ins datenblatt schau.* OH! Der braucht ja ewig! Pro "push" zwei Takte!
Ich zähle 15 "push", also schon 30 Takte, und dann noch ein "in" mit 1 
Takt, ein "out" (1 Takt), "eor" (1 Takt), ldi (1 Takt). Also da allein 
34 Takte, bis da meine 7 reingeladen wurde, richtig? Dann ist die Sache 
natürlich klar -_o ...
Wie kann ich rauskriegen, wie lange das Anspringen der ISR in C dauert? 
Falk sagte etwas von rund 12 Takten...
Und was kann ich gegen die ganzen "push" tun? Sind das meine volatiles?
Tut mir leid, mit den Listings hab ich mich scheinbar bisher zu wenig 
auseinander gesetzt...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau dir deine ISR genau an. Sieht so aus als ob du da drinn viel zu 
viel machst. Dadurch braucht die ISR jede Menge Register und die wollen 
erst mal gesichert werden.

Den Optimizer hast du eingeschaltet?

Und das andere
> Aber ok, ich zeige mal das "wichtigste":

Jetzt weißt du auch, warum diese 'Beschränkung auf das vermeintlich 
Wichtigste' manchmal eine ganz schlechte Idee ist.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Joachim A. (jojo84)

>*ins datenblatt schau.* OH! Der braucht ja ewig! Pro "push" zwei Takte!
>Ich zähle 15 "push", also schon 30 Takte, und dann noch ein "in" mit 1
>Takt, ein "out" (1 Takt), "eor" (1 Takt), ldi (1 Takt). Also da allein
>34 Takte, bis da meine 7 reingeladen wurde, richtig? Dann ist die Sache
>natürlich klar -_o ...

;-) Manchmal ist es einfacher als man denkt.

>Wie kann ich rauskriegen, wie lange das Anspringen der ISR in C dauert?

Im Simulator.

>Falk sagte etwas von rund 12 Takten...

Das war ein Schuß ins Blaue.

>Und was kann ich gegen die ganzen "push" tun?

Wenig.

> Sind das meine volatiles?

Welche? Deiner Zähler? Vielleicht. Hast du mit Optimierung compiliert? 
-Os (minimale Größe).

>Tut mir leid, mit den Listings hab ich mich scheinbar bisher zu wenig
>auseinander gesetzt...

Muss man auch nur in solchen kritischen Fällen.

MFG
Falk

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Schau dir deine ISR genau an. Sieht so aus als ob du da drinn viel zu
> viel machst.

Insbesondere sehen die PUSHs so aus, als ob du in der ISR eine andere 
Funktion aufrufst (denn das sind genau die "call-used"-Register). Das 
ganz vermeiden, oder zumindest dafür sorgen, dass die Funktion 
ge-inline-t wird.

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jo, die Optimierung ist eigenschaltet (0s)

Ich muß ja zugeben, daß in der ISR zu viel passiert. Aber das poste ich 
hier mal lieber nicht, weil das nicht direkt Gegenstand meines Themas 
hier sein sollte. Ihr würdet (zurecht...) den Code völlig auseinander 
nehmen =) . Dann ist das hier rucki-zucki neben dem Thema ;) .
Ich hab mit eurer Hilfe das Problem gefunden und das zu beseitigen soll 
mal schön meine Sorge sein =) ...

Kann ich denn jetzt einen grundlegenden Denkfehler meinerseits im Bezug 
auf die rein rechnerische Zeitgenerierung, ausschließen?
Es müßte dann ja eigentlich funktionieren, wenn ich den Prescaler auf 64 
Stelle. Dann müßte ich eben nurnoch 125 Zählschritte machen. Dann lade 
ich den Zähler mit 131 vor. Bleiben also 124 Zählerschritte bis 255, und 
dann nochmal einer um überzulaufen, den Interrupt auszulösen und wieder 
mit 131 geladen zu werden. Ich sprech nicht von Takten ;) ...

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Joachim A. (jojo84)

>Es müßte dann ja eigentlich funktionieren, wenn ich den Prescaler auf 64
>Stelle.

Ja das geht und löst das Problem.

MfG
Falk

Autor: Pothead (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim A. schrieb:
> Das Prog ist aber schon sehr umfangreich, aber der
> relevante Code nur ein Bruchteil davon.

Keine Ahnung wie hoch die Priorität von diesem Timer auf dem AVR ist, 
aber was machen mögliche andere Interrupts? Knallt dir da vielleicht was 
rein und blockiert den Zugang zur Timer ISR?

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Supi, DANKE! Hauptproblem gelöst =)

@Stefan
ich weiß nicht so recht, was du mit "ge-inline-t" und so meinst. Ich bin 
echt nicht tief drin in Assembler... :(
Aber ja, ich rufe eine weitere Funktion auf. Daß das nicht gut ist hab 
ich schon vermutet. Darum hab ich diesen Aufruf innerhalb der ISR von 
einer Bedingung abhängig gemacht, die nur ganz am Anfang erfüllt ist. 
Damit wollte ich vermeiden, daß diese unschöne Unterfunktion jedes mal 
angesprungen wird (wird sie ja auch nicht). Aber ich vermute mal ganz 
stark, daß der Controller diese ganzen Register ja trotzdem erstmal 
sichert (push), weil er zu Beginn der ISR ja noch nicht weiß, ob diese 
Unterfunktion denn nun auch wirklich angesprungen wird, oder nicht. 
Richtig?

EDIT:
@Pothead:
nee, gibt keine weiteren Interrupts...

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Joachim A. schrieb:
> angesprungen wird (wird sie ja auch nicht). Aber ich vermute mal ganz
> stark, daß der Controller diese ganzen Register ja trotzdem erstmal
> sichert (push), weil er zu Beginn der ISR ja noch nicht weiß, ob diese
> Unterfunktion denn nun auch wirklich angesprungen wird, oder nicht.
> Richtig?

ja, richtig,
inlinen heißt, dass nicht zu einem UP gesprungen wird, sondern dass die 
Befehle des UPs direkt in den Code eingefügt werden

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Joachim A. (jojo84)

>angesprungen wird (wird sie ja auch nicht). Aber ich vermute mal ganz
>stark, daß der Controller diese ganzen Register ja trotzdem erstmal
>sichert (push), weil er zu Beginn der ISR ja noch nicht weiß, ob diese
>Unterfunktion denn nun auch wirklich angesprungen wird,

Genau so ist es. Also pack die Funktion direkt in die ISR.

MFG
Falk

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann doch auch einfach die Funktion als inline deklarieren oder irre 
ich mich da?

Kein Grund alles Copy&Paste einzufügen ;)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Läubi .. (laeubi) (Moderator) Benutzerseite

>Man kann doch auch einfach die Funktion als inline deklarieren oder irre
>ich mich da?

Sicher, aber . . .

>Kein Grund alles Copy&Paste einzufügen ;)

So eine Funktion, welche in der ISR aufgerufen wird, wird sicherlich 
NICHT von woanders aufgerufen, denn das ist SEHR gefährlich (wenn man es 
nicht richtig macht). Also was soll eine Funktion, die nur einmal 
aufgerufen wird? Ist sinnlos. Bringt mehr Verwirrung als Struktur.

MFG
Falk

Autor: Joachim B. (jojo84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ok. Alles klar. Dann weiß ich jetzt erstmal, wo ich ansetzen muß :)

Danke euch nochmal!
CLOSE ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.