Hallo,
Dank schonmal für die Antworten.
Also, ich habe einen Timer-Interrupt laufen mit 72 Aufrufen pro ms
(Timer0). Hier wird PC2 abgetastet und die steigende Flanke detektiert.
Nach Erkennung der steigenden Flanke starten Vorbereitungen für die
Aktionen, die zeitkritisch nach der fallenden Flanke ablaufen sollen.
Ich habe inzwischen bereits weiter ausprobiert:
a) Interrupts global aus (cli()) vor der while-Schleife, nach Abarbeiten
der I2C Routine wieder global an (sei()), ohne Verbesserung.
b) Verlagerung des Codes in die Timer-ISR. Das sollte den gleichen
Effekt haben, ändert aber auch nichts am Timing.
c) Ich habe vor der I2C-Anweisung einen freien Port geschaltet:
1 | //avr-gcc ... -Os ...
|
2 |
|
3 | #include ...
|
4 |
|
5 | void main(void)
|
6 | {
|
7 | DDRC &= ~(1<<2);//auf Eingang schalten
|
8 | DDRD |= (1<<6);//Port D6 als Ausgang <---------------------
|
9 |
|
10 | for(;;)
|
11 | {
|
12 | ...
|
13 | //wenn Pegel an PC2 oben...
|
14 | PORTD |= (1<<6);//PD6 high <---------------------
|
15 | if((PINC & (1<<2)))
|
16 | {
|
17 | //auf fallende Flanke an PC2 warten
|
18 | while((PINC & (1<<2))){};
|
19 | PORTD &= ~(1<<6);//PD6 low <---------------------
|
20 | i2c_start(...); //-> TWI-Master von Peter Fleury
|
21 | ...
|
22 | }
|
23 | ...
|
24 | }
|
25 | }
|
Der Flankenwechsel an diesem Port ist ebenso verzögert, die
I2C-Anweisung wird danach dann entsprechend schnell aufgerufen (~5µs --
also etwa halbe I2C Bustakt-Periode). Von daher scheint die Verzögerung
mit dem Polling an PC2 in der while-Schleife zusammen zu hängen.
Den Ansatz, "einfach" die fallende Flanke in einem Interrupt auswerten,
habe ich verworfen: Ich bekomme auf PC2 ein 10 Hz Trägersignal mit
Pulsweitenmodulation. Bei unterschiedlichen Pulsweiten sind verschiedene
Aktionen auszuführen. Ich detektiere die steigende Flanke und warte auf
die fallende Flanke. Wenn die länger als 2 ms auf sich warten lässt,
polle ich PC2 (hier geht es um die zeitkritische Aktion). Idee dahinter
ist, die Flanke zeitlich genauer zu detektieren, als per Polling via
Timer-ISR.
Wenn ich PC2 in einer ISR überwache und die Zeit zwischen steigender und
fallender Flanke auswerte, muss ich nach der Erkennung der fallenden
Flanke anfangen auszuwerten, welche Aktion auszuführen ist. In der Zeit
kann mir wieder ein Interrupt in die Parade fahren (OK, könnte ich
deaktivieren...). Daher bereite ich nach Erkennung der steigenden Flanke
meine Aktion vor und schließe sie dann möglichst zeitnah nach Auftreten
der fallenden Flanke ab. Je weniger nach dem Startsignal noch zu tun
ist, desto geringer sollten die zeitlichen Abweichungen sein -- so meine
Arbeitsthese ;)
Gruß,
Peter