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


von Timo B. (Firma: MicroForge) (timob)


Angehängte Dateien:

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

von Timo B. (Firma: MicroForge) (timob)


Lesenswert?

Sorry... offenbar stand ich ganz ganz kurz vor der Selbsterkenntnis.

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

um dann mit folgendem Interrupt zu arbeiten:
1
ISR(TIMER1_CAPT1_vect){
2
3
  //unsigned int counterValue = 0;
4
  //counterValue = ICR1;
5
  short tableEntry = calc_RpmToArray(ICR1);
6
  ICR1 = 0;
7
  TCNT1 = 0;
8
9
  PORTB = ~(drehzahl[tableEntry] & 0xFF);
10
  PORTD = ~((drehzahl[tableEntry] >> 8) & 0xFF);
11
12
  //PORTB = ~((counterValue) & 0xFF);
13
  //PORTD = ~(((counterValue) >> 8) & 0xFF);
14
15
  //PORTB = 0x00;
16
  //PORTD = ~PORTD;
17
}

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

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

Gruß
Timo

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.