www.mikrocontroller.net

Forum: Compiler & IDEs Problem: AT90S2313 und der TimerCapture Pin (ICP - Interrupt)


Autor: Timo Birnschein (Firma: MicroForge) (timob)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich versuche einen digitalen Drehzahlmesser zu programmieren.
Leider komme ich mit dem 16-Bit TimerCounter1 des AT90S2313 nicht klar.

Ich wollte gerne, dass der Timer bei 0 startet. Ich möchte Signale 
zwischen 50Hz und 400Hz messen können, daher habe ich bei 10Mhz einen 
Prescaler von 1024 gewählt. Wenn an ICP eine positive Flanke auftritt 
möchte ich einen Interrupt auslösen. Der Interrupt wird ausgelöst, 
allerdings steht dann nichts im Zähler drin! Ein OverFlow tritt 
entsprechend auch nie auf, was mich extrem verwirrt.

Ich habe meinen Code im Anhang. Meiner Meinung nach habe ich alle 
Register richtig gesetzt. Die Interruptroutine steht unten in main.c.

Wenn an PD6 (ICP) eine positive Flanke auftritt soll er in den IRQ 
hüpfen und über eine kleine Funktion ein 14-Bit Wort an die Ausgänge 
legen. Alle Funktionen funktionieren, bis auf dieser Counter. Der wird 
scheinbar nicht hochgezählt.

Habe ich irgendwas übersehen? Ich wäre euch wirklich dankbar, wenn 
jemand einen Fehler findet.... :(

Gruß
Timo

Autor: Timo Birnschein (Firma: MicroForge) (timob)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry... offenbar stand ich ganz ganz kurz vor der Selbsterkenntnis.

Im Code initialisiere ich den Counter wie folgt:
  TIMSK = (1<<TICIE1) | (1<<TOIE1);
  //TIFR = (1 << ICF1);
  TCNT1 = 0;
  //TCCR1A = 0x00;
  TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CTC1) | (1 << CS12);
  sei();

um dann mit folgendem Interrupt zu arbeiten:
ISR(TIMER1_CAPT1_vect){

  //unsigned int counterValue = 0;
  //counterValue = ICR1;
  short tableEntry = calc_RpmToArray(ICR1);
  ICR1 = 0;
  TCNT1 = 0;

  PORTB = ~(drehzahl[tableEntry] & 0xFF);
  PORTD = ~((drehzahl[tableEntry] >> 8) & 0xFF);

  //PORTB = ~((counterValue) & 0xFF);
  //PORTD = ~(((counterValue) >> 8) & 0xFF);

  //PORTB = 0x00;
  //PORTD = ~PORTD;
}

Das klappt nicht, weil ich den Counterstand durch setzen des CTC1 Flags 
automatisch löschen lasse!
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CTC1) | (1 << CS12);

Ich dachte, dass das klug wäre, da ich ja den Counter neustarten möchte, 
wenn ich mit dem Auslesen des ICR1 Registers fertig bin. Es scheint aber 
so zu sein, dass das ICR1 Register geschrieben wird, nachdem der 
Counter zurückgesetzt wurde. Das ist natürlich Schwachsinn.

Aber
TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << CS12);

so läuft es jetzt. Ich setze in der Interruptroutine den Counter selbst 
zurück.

Gruß
Timo

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.