www.mikrocontroller.net

Forum: Compiler & IDEs Frage zur "genauen Sekunde"


Autor: baeri3 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich habe leider ein "kleines" Problem mit der "genauen Sekunde".
Habe diese aus dem WIKI rauskopiert, bekomme es aber leider im
AVR-Simulator nicht gescheit zum laufen.
Der PORTB sollte eigentlich die Sekunde im Bin-Wert ausgeben,
aber wie es scheint, wird der Timer-IRQ nur einmal ausgeführt,
denn wenn ich dort den PORTB auf 0xFF setze, ist dieser auch HIGH.
Habe ich irgendwo einen Fatalen Fehler gemacht?

Danke für eure Hilfe!

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe es immer so gemacht:
#include <avr/io.h> 
#include <avr/interrupt.h>
#include <util/delay.h>

#define TIMER_VALUE 34286 /* Bei 16MHz und prescaler von 256 => 500ms
Int. */

ISR(TIMER1_OVF_vect){
  timercount++;
  TCNT1 = TIMER_VALUE;
  /* Hier könntest du dann was ausgeben */
}

int main(void){

  TCCR1A = 0x00;        /* kein PWM usw. */
  TCCR1B |= (4<<CS10);  /* Prescaler = 256 */
  TCNT1 = TIMER_VALUE;  /* => erzeugt alle 500ms nen Int. */
  TIMSK |= (1 << TOIE1);
  sei();
  while(1);
}


Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Overflow-Methode sollte man vermeiden, wenn immer möglich.
Sie ist prinzipbedingt mit Unsicherheiten und Jitter durch die
Interruptlatenz behaftet.  Bis auf ganz wenige Ausnahmen hat der
Timer 1 doch überall einen CTC-Modus, den man benutzen kann.
(Bei neueren AVRs hat Timer 0 diesen Modus auch.)

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mhh, wusste ich nicht. Aber was sollte der Comparemodus daran ändern?
Der Zähler ist der selbe, Takt ist auch gleich. Und wenn ich das mal so
über nen Tag messe, kann ich eigentlich keine Ungenauigkeit feststellen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Aber was sollte der Comparemodus daran ändern?

Dass das Rücksetzen des Zählers in der Hardware erledigt
wird und damit unabhängig von der Interruptlatenz erfolgt.
Einen Interrupt kannst du dir ja dennoch generieren lassen
(damit du auch erfährst, dass jetzt wieder Zeit vergangen
ist), aber die Latenz in der Interruptannahme spielt dann
keine Rolle mehr; dein Programm erfährt zwar u. U. erst etwas
später, dass es jetzt später geworden ist, der Zähler hat es
aber schon vorher erfahren und kann weiterzählen.

Autor: Timmo H. (masterfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt leutet ein, danke für die Info.

Autor: leo9 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
im Prinzip hat Jörg mit den Latenzzeiten schon recht, aber man sollte
auch die Auswirkungen auf die Applikation betrachten.

In diesem Beispiel würde der Fehler
365  24  60  60  62,5 ns = +1,97 Sek pro Jahr ausmachen (unter der
Annahme dass der int immer bei 2-zyklischen Befehlen zuschlägt,
statistisch wird er auch etliche 1-zyklische erwischen und der Fehler
wird kleiner).

Steht kein CTC Mode zur Verfügung und der Prescaler ist groß genug
könnte auch ein TCNT = TCNT + VALUE helfen, dann muß man nur aufpassen
dass man das "Prescaler-Fenster" erwischt, ab pres > 1:16 sollte das
aber kein Problem sein.

Wenn es auf absolute Genauigkeit ankommt könnte man auch einen
"Vorinterrupt" generieren der GIE per SW enabled und eine Folge von
nops startet, dann unterbricht der echte Interrupt jedenfalls einen
1-zyklischen Befehl und der Fehler der Latenzzeit reduziert sich auf -0
bis +1 Taktzyklus.

Eine weitere Möglichkeit wäre den up schlafen zu lassen, dann ist die
Latenzzeit ebenfalls konstant.

grüße leo9

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@leo9,

die Interruptlatenz ist vielleicht nicht so erheblich, aber man hat ja
noch andere Interuptquellen oder Programmabschnitte unter
Interruptsperre und dann gibt es schon erhebliche Verzögerungen.

Der AVR hat ja keine Prioritäten, wenn also ein anderer Interrupt z.B.
1ms dauert, wird Deine RTC-Routine so lange verzögert.


Peter

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nicht nur im Prinzip hat Jörg recht

gewöhnlich sieht die ISR Routine so aus

(volatile unsigned char timercount;)
ISR(TIMER1_OVF_vect){
timercount++;
//tue evt. noch was
TCNT1 = TIMER_VALUE;
}

da kommen noch 4 Takte eintritt in den Interrupt hinzu
+ push der benötigten Register ca. x*3 Takte
+ code bis TCNTx = Timervalue =x Takte

wenn man die Suchfunktion dieses Forums benutzt kann man die
Auswirkungen hervoragend nachvollziehen. Dabei steht schon im
Datenblatt der Hinweis.

Autor: Manuel B. (baeri3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Zahlreichen Hinweise...
Ich dachte eiegntlich dass die Lösung die ich verwendet habe
In Ordnung sei, da diese aus einem Articel von hier stammt:

http://www.mikrocontroller.net/articles/AVR_-_Die_...

Evt. sollte diesen jemand überarbeiten, und die hier Diskutieren
Anhaltspunkte miteinbeziehen.

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Manuel,

die Kommentare beziehen sich nur auf den Code von Timmo.

Dein Code benutzt ja das Compareregister.

Warum er bei Dir nicht funktioniert, könnte daran liegen, daß Du den
falschen AVR-Typ angegeben hast, dann zeigen die Interrupts in den
Wald.


Peter

Autor: Manuel B. (baeri3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Peter,

danke für die Info.

Also ich verwende einen Mega8 und habe diesen auch im Simulator
ausgewählt. Der Code sollte wie er ist ja auf einem Mega8 laufen,
oder liege ich da falsch?

Autor: Manuel B. (baeri3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmals,

also die Interrupt Vektoren für den Mega8 stimmen mit denen in dem
Code Sample überein.
Die initialisierung der Register und Compare-Werte stammen ja aus dem
Artikel (s.O.), sollten somit auch stimmen.
Ist dies evt. ein Problem mit dem Simulator aus dem AVR-Studio?

Autor: peter dannegger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zum Simulator kann ich nichts sagen, ich teste immer im real-life, z.B.
aufm STK500.


Peter

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

Bewertung
0 lesenswert
nicht lesenswert
Also in meinem AVR-Studio Simulator funzt das Ganze
einwandfrei.

Autor: Manuel B. (baeri3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eigenartig... Evt. mach ich da ja irgendwo einen fatalen Fehler!?
Ich bin bisher einfach ins AVR-Studio und dann habe ich direkt über
File -> Open File das Hex-File geladen. Danach kann man Ihm ja dann
noch
den AVR Typ angeben, da habe ich natürlich den Mega8 ausgewählt.
Und dann gehts ja schon los.
Im I/O View Window sehe ich auch, dass der DDRB usw. richtig gesetzt
wird und auch der Timer schön hoch zählt.

Ich habe gerade noch auf die Version 4.12 mit SP2 geupdatet.

Autor: Manuel B. (baeri3)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey, es scheint nun doch zu funktioneren.
Sorry für die Umstände! Werde es demnächst noch in Real-Life testen..

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.