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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.