Mahlzeit zusammen !!
Ich hab mir ein kleines Stück Code geschrieben um am Mega8 per ICP1
Frequenzen zu messen. Prinzipiell funktioniert das alles recht gut. Zum
Testen hab ich bisher eine über Timer2 im CTC Mode erzeuge Frequenz von
genau 10000 Hz am OC2 pin gemessen. Getaktet ist der Mega8 mit einem
12Mhz Quarz.
Im Anhang ist der Code dazu. Wichtig ist mir, dass nur für die Dauer
einer Messung die Input Capture und Overflow Interrupts laufen, da ich
später noch andere zeitkritische Dinge per Interrupts erledigen möchte.
Der Code der main() Loop sieht etwa so aus:
1 | FreqCountInitialize();
|
2 |
|
3 | uint8_t nSecondsPassed = 0;
|
4 | uint8_t nFreqCount = 0;
|
5 | for(;;)
|
6 | {
|
7 | // delay 100ms
|
8 | for(uint8_t i = 0; i < 10; i++)
|
9 | {
|
10 | _delay_ms(10);
|
11 | }
|
12 |
|
13 | if(nFreqCount == 0)
|
14 | {
|
15 | nFreqCount = 1;
|
16 | nSecondsPassed = 0;
|
17 | FreqCountStart();
|
18 | }
|
19 | else
|
20 | {
|
21 | nSecondsPassed++;
|
22 | if(FreqCountIsFinished())
|
23 | {
|
24 | double dResult = FreqCountGetResult();
|
25 | char szBuf[25] = {0};
|
26 | dtostrf(dResult, 14, 8, szBuf);
|
27 | DisplayWriteLine(szBuf);
|
28 | nFreqCount = 0;
|
29 | }
|
30 | else
|
31 | {
|
32 | if(nSecondsPassed > 3)
|
33 | {
|
34 | FreqCountStop();
|
35 | nFreqCount = 0;
|
36 | DisplayWriteLine("too low");
|
37 | }
|
38 | else
|
39 | {
|
40 | DisplayWriteLine("pending");
|
41 | }
|
42 | }
|
43 | }
|
44 | }
|
So erhalte ich etwa 5 Messungen die Sekunde.
Die 10000Hz werden bis auf die 8. Nachkommastelle genau berechnet.
Die ICP Tick Differenz zwischen zwei Peaks ist dann 1200, d.h. es
sollten während der Messung eigentlich keine Overflows auftreten.
Da aber beide Timer den Takt letztendlich vom gleichen Quarz beziehen
hatte ich das auch so erwartet.
Jetzt hab ich zwei "seltsame" Probleme die ich gern verstehen würde.
1.) Ich lasse FreqCountInitialize() weg und verschiebe den Code zum
Initialisieren des Timers über TCCR1B vors Aktivieren der Interrupts in
FreqCountStart(). Dadurch wird TCCR1B ab der zweiten Messung beschrieben
obwohl der Timer schon entsprechend läuft. Das sieht dann etwa so aus:
1 | void FreqCountStart()
|
2 | {
|
3 | g_unState = STATE_FIRST;
|
4 | TCCR1B &= ~_BV(ICNC1);
|
5 | TCCR1B |= _BV(ICES1);
|
6 | TCCR1B &= ~(1 << 5);
|
7 | TCCR1B &= ~_BV(WGM13);
|
8 | TCCR1B &= ~_BV(WGM12);
|
9 | TCCR1B &= ~_BV(CS12);
|
10 | TCCR1B &= ~_BV(CS11);
|
11 | TCCR1B |= _BV(CS10);
|
12 | TIMSK |= _BV(TICIE1);
|
13 | TIMSK |= _BV(TOIE1);
|
14 | }
|
So funktiert es dann auch, alle Messungen sind ok.
Ich änder den Code nochmal so ab, das TCCR1B komplett beschrieben wird
und nicht jedes Bit einzeln:
1 | void FreqCountInitialize()
|
2 | {
|
3 | g_unState = STATE_FIRST;
|
4 | TCCR1B = _BV(ICES1) | _BV(CS10);
|
5 | TIMSK |= _BV(TICIE1);
|
6 | TIMSK |= _BV(TOIE1);
|
7 | }
|
So ist jede Messung nach der ersten Schrott mit einem relativ konstanten
Wert.
Das kann ich mir jetzt mal nicht erklären......wo liegt der Unterschied
zum Bitweise beschreiben des TCCR1B ?
Das Problem verschwindet, wenn ich zwischen dem Initialisieren des
Timers und dem Aktivieren der Interrupts ein "_delay_ms(1)" einfüge.
Ein "_delay_us(1)" langt nicht. Irgendwelche Ideen warum sich das so
verhält ?
2.) Sporadisch, etwa jede 10. Messung, erhalte ich Unsinnige Werte weil
der Overflow-Count nicht 0 ist. Oft steht er auf 1, weniger oft auf 19.
Keine anderen werte. Die 19 Overflows konnte ich mir nur durch das
Weiterlaufen des Overflow Interrupts nach der Messung erklären, denn die
entsprechen ungefähr den 100ms bis zum Start der nächsten Messung. Das
hab ich scheinbar in den Griff bekommen indem ich den Code des Overflow
Interrupt Handlers so umgebaut habe:
1 | ISR(TIMER1_OVF_vect)
|
2 | {
|
3 | if(g_unState != STATE_IDLE)
|
4 | {
|
5 | g_unOverflows++;
|
6 | }
|
7 | }
|
Da ich allerdings beim Abschluss der Messung den Interrupt deaktiviere
und sogar das Overflow Flag lösche, wie kann das sein ?
Mach ich beim Deaktivieren des Overflow Interrupts im ICP Interrupt was
falsch ?
Ich vermute, ein Fehler hier auch die Ursache für den sproadischen
Overflow-Count 1 ist.
Es geht mir hier nur darum zu verstehen warums der Code nicht 100%ig
tut.
In meinem Anwendungsfall kann ich gut damit leben, aber ich bin halt
neugierig.
Vielleicht nützen ein paar Augenpaare mehr ja was....
Danke & Gruß,
Watz