Hallo Leute,
folgendes Problem, ich programmiere einen Atmel 32UC3A1512.
Jede ms soll ein Wert vom ADC eingelesen werden. Hierzu rufe ich jede ms
eine ISR mittels Timer-Interrupt auf. Der Timer läuft in Waveform-Mode.
Ausschnitt aus Main:
1 | int main(void)
|
2 | {
|
3 |
|
4 | ...
|
5 |
|
6 | static const tc_interrupt_t TC_INTERRUPT = // OPTIONEN Interrupts
|
7 | {
|
8 | ...
|
9 | .cpcs = 1, // Compare RC <--
|
10 |
|
11 | ... // sonst alle 0
|
12 | };
|
13 |
|
14 | static const tc_waveform_opt_t TC_WAVEFORM =
|
15 | {
|
16 | ...
|
17 | // Werte hiervor sind alle: TC_EVT_EFFECT_NOOP,
|
18 | .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,
|
19 | ...
|
20 | .tcclks = TC_CLOCK_SOURCE_TC2 // fPBA/2 --> (fPBA = 48MHz)
|
21 | };
|
22 |
|
23 | ...
|
24 |
|
25 | tc_write_rc(&AVR32_TC, TC_CHANNEL, 24000); // 1KHz
|
26 |
|
27 | ...
|
28 |
|
29 | while(1)
|
30 | {...}
|
31 |
|
32 | return 0;
|
33 | }
|
Das funktioniert auch alles, d.h. die ISR wird ausgeführt.
Die Option RC_Trigger bedeutet meines Erachtens, dass der Timerwert
wieder auf Null gesetzt wird und der Timer neu startet wenn der Timer
den Wert, der im Register C geladen wurde, erreicht. Ist das richtig?
Durch die Interrupt-Einstellungen wird bei Compare_RC in die ISR
gesprungen.
Nun muss ich aber immer am Ende(!) der ISR den Software-Trigger
ausführen, damit das Ganze funktioniert. Das finde ich komisch, da ja
eigentlich dieser Trigger automatisch bei RC-Compare ausgeführt werden
sollte..?!?!
Hier die ISR:
1 | static void led_ISR(void)
|
2 | {
|
3 | ... // Wert aus dem ADC auslesen
|
4 |
|
5 | tc_read_sr(&AVR32_TC, TC_CHANNEL); // Interrupt Flag löschen
|
6 | tc_software_trigger(&AVR32_TC, TC_CHANNEL);
|
7 | }
|
Wie gesagt, das Ganze funktioniert, aber so wird ja nun nicht jede ms
die ISR ausgeführt, sondern jede
ms + (Bearbeitungszeit der ISR)
Um diese Zeit wirklich auf 1ms schrumpfen zu lassen, müsste der Timer,
nachdem er den Wert RC erreicht hat sofort wieder auf Null gesetzt
werden und neustarten. Hier wird der Timer aber erst nach Abarbeitung
der ISR genullt und neugestartet.
Kurios ist, wenn ich das Löschen des Interrups Flags und den Software
Trigger am Anfang der ISR schreibe, dann wird die ISR zwar ein paar Mal
aufgerufen (das erkenne ich weil ich eine LED toggeln lasse) aber dann
ist die ISR tot bzw. sie wird nicht mehr aufgerufen (LED toggelt nicht
mehr). Dieses Verhalten verstehe ich nun gar nicht mehr.
Ich hoffe, Ihr könnt mir ein wenig Aufschluß geben;)