Forum: Compiler & IDEs Reaktionszeit auf Flankenwechsel


von Peter Buttgereit (Gast)


Lesenswert?

Hallo zusammen,

ich möchte mehrere ATmega128-Module per Funk synchronisieren. Und zwar 
soll möglichst gleichzeitig auf eine abfallende Flanke an einem Port 
eine Messung gestartet werden.
1
//avr-gcc ... -Os ...
2
3
#include ...
4
5
void main(void)
6
{
7
   DDRC  &= ~(1<<2);//auf Eingang schalten
8
   for(;;)
9
   {
10
     ...
11
     //wenn Pegel an PC2 oben...
12
     if((PINC & (1<<2)))
13
     {
14
        //auf fallende Flanke an PC2 warten
15
        while((PINC & (1<<2))){};
16
        i2c_start(...); //-> TWI-Master von Peter Fleury
17
        ...
18
     }
19
     ... 
20
   }
21
}

Im Prinzip funktioniert es auch, allerdings vergeht zwischen der 
abfallenden Flanke und der Ausführung von i2c_start() je nach Modul 
deutlich unterschiedlich viel Zeit. Bei einem Systemtakt von 14.7456 MHz 
liegen zwischen fallender Flanke an PC2 und i2c_start(), d.h. der ersten 
fallenden Flanke auf SCL, 20 bis 60 µs.

Ich hätte da nur "ein paar Takte" Verzögerung erwartet und entsprechend 
wenig Varianz zwischen verschiedenen Modulen. Ein Problem habe ich 
primär mit der Varianz.

Hardwaremäßig sind die Module identisch aufgebaut.

Verrät mir jemand meinen Denkfehler?

Mit Dank + Gruß,

Peter

von Steffen R. (stevven)


Lesenswert?

wieso versuchst du es nicht per interruptfähigen Pin?

von Karl H. (kbuchegg)


Lesenswert?

20 - 60µs ist ziemlich viel.

Sind da irgendwelche ISR zu gange?

von Peter Buttgereit (Gast)


Lesenswert?

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

von Peter Buttgereit (Gast)


Lesenswert?

Uah -- Fehler gefunden.
Liegt nicht an der while-Schleife, sondern daran, dass die 
Schleifenbedingung schon falsch ist, wenn der Code aufgerufen wird.
Danke für die Unterstützung.
Grüße,
Peter

von Peter Buttgereit (Gast)


Lesenswert?

Hallo nochmal,

um das abzuschließen:

mit meinem 4 MHz Billig-Logic-Analyzer komme ich auf ca. 1 µs Differenz 
zwischen den zu erkennenden fallenden Flanken und auf eine Verzögerung 
des Startsignals (1. fallende Flanke SDA) von 2 bzw. 4 µs.

Das ist wohl das, was man erwarten darf...

Frohes Schaffen euch allen.

Grüße,

Peter

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