Sobald jedoch eine weitere Zeile dabeikommt (also 9) werden Interrupts geschluckt und der counter kommt nicht mehr bei 525 an.
Jeder zusätzliche
else if Abfrage benötigt Zeit, wenn der vorangegangene Vergleich
false ist. Die Interrupts gehen "verloren", weil die Abarbeitung der ISR dann mehr Zeit benötigt, als zwischen den Interrupts zur Verfügung steht.
Die "regelmäßigen Abstände" sind bei Euch zur Zeit wohl 64. Das praktische daran ist, daß es sich dabei um einer Zweierpotenz handelt. Somit kann man ganz leicht feststellen, ob
counter ein vielfaches von 64 (oder 0) ist. Grundlegender Gedanke:
void EXT_isr()
{
if ((counter & 0x3F ) == 0) // "true" für counter==0, counter==64, counter==128, ...
{
r[index] = read_adc();
index++;
}
counter++;
}
Damit wird die Abarbeitungszeit auf jeden Fall schon einmal unabhängig von der Anzahl der ursprünglichen
else if Abfragen. Wenn z.B. alle 32 Interrupts eine Wandlung erfolgen soll, muß das
0x3F nur durch
0x1F ersetzt werden.
counter bräuchte bei der obigen Vorgehensweise auch nicht mehr zurückgesetzt werden (und müßte nur 8 Bit aufnehmen können), da ein Überlauf überhaupt keine Auswirkungen hat.
index muß zurückgesetzt werden, außer wenn der Wertbuffer ebenfalls eine Anzahl von Werten aufnehmen soll, die einer Zweierpotenz entsprechen. Dann könnte man z.B. entsprechend schreiben:
r[index & 0x0F] = read_adc(); // r nimmt 16 Werte auf (0-15)
Generell sehe ich aber ein Problem in Eurem Ansatz. Die Interrupt-Häufigkeit ist (zumindest für den CCS-Compiler) viel zu hoch. Ich habe mir mit der neuesten Demo-Version noch mal das Dissassembly-Listing der ISR angesehen. Für die Sicherung und Rücksicherung von Registern beim Auslösen eines Interrupts benötigt der CCS über 60 Befehlszyklen. Diese Befehlszyklen werden bei
jedem auftretenden Interrupt benötigt. Zusammen mit den Einsprung in die ISR, dem Rücksprung aus der ISR und der Abfrage von den Interrupt-Bits verbringt der PIC 50% (wenn nicht mehr) der zur Verfügung stehenden "Rechenzeit" damit, auf Interrupts zu reagieren (ohne jegliche sinnvolle Aufgabe auszuführen). Dabei gehe ich von 20MHz Taktfrequenz aus (die wirkliche Taktfrequenz wurde nicht genannt).
Die einzig wirklich sinnvolle Möglichkeit, die ich sehe, ist es (wie schon zuvor in einem anderen Thread erwähnt), das externe Signal nicht an INT0 anzuschließen, sondern an T1CKI. Dann das CCP-Modul im "Compare Mode, Trigger Special Event" verwenden, welches die AD-Wandlung startet (und auf den AD-Interrupt reagieren). Damit erfolgt ein Interrupt nur, wenn auch wirklich ein Ergebnis vorliegt. Ihr müßt Euch klarmachen, daß durch Euren Ansatz 63 sinnlose Interrupts generiert werden, welche die "Verfügbarkeit" des Prozessors drastisch einschränken.
Viele Grüße
Bernd