Frage zur "genauen Sekunde"

Gast #364853
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!
Angehängte Dateien:
#364854
Lesenswert?
• ▲
▼
Also ich habe es immer so gemacht:
1
#include <avr/io.h> 
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4

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

8
ISR(TIMER1_OVF_vect){
9
  timercount++;
10
  TCNT1 = TIMER_VALUE;
11
  /* Hier könntest du dann was ausgeben */
12
}
13

14
int main(void){
15

16
  TCCR1A = 0x00;        /* kein PWM usw. */
17
  TCCR1B |= (4<<CS10);  /* Prescaler = 256 */
18
  TCNT1 = TIMER_VALUE;  /* => erzeugt alle 500ms nen Int. */
19
  TIMSK |= (1 << TOIE1);
20
  sei();
21
  while(1);
22
}
Moderator Persönliche Seite #364857
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.
Gast #364859
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
Gast #364860
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
Gast #364861
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.
Gast #364863
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
#364868
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.

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.