Problem: AT90S2313 und der TimerCapture Pin (ICP - Interrupt)

OP (Firma: MicroForge) #1030455
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
Angehängte Dateien:
OP (Firma: MicroForge) #1030469
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren