mikrocontroller.net

Forum: Compiler & IDEs Reaktionszeit auf Flankenwechsel


Autor: Peter Buttgereit (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
//avr-gcc ... -Os ...

#include ...

void main(void)
{
   DDRC  &= ~(1<<2);//auf Eingang schalten
   for(;;)
   {
     ...
     //wenn Pegel an PC2 oben...
     if((PINC & (1<<2)))
     {
        //auf fallende Flanke an PC2 warten
        while((PINC & (1<<2))){};
        i2c_start(...); //-> TWI-Master von Peter Fleury
        ...
     }
     ... 
   }
}

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

Autor: Steffen R. (stevven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wieso versuchst du es nicht per interruptfähigen Pin?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
20 - 60µs ist ziemlich viel.

Sind da irgendwelche ISR zu gange?

Autor: Peter Buttgereit (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
//avr-gcc ... -Os ...

#include ...

void main(void)
{
   DDRC  &= ~(1<<2);//auf Eingang schalten
   DDRD |= (1<<6);//Port D6 als Ausgang  <---------------------
   
   for(;;)
   {
     ...
     //wenn Pegel an PC2 oben...
     PORTD |= (1<<6);//PD6 high          <---------------------
     if((PINC & (1<<2)))
     {
        //auf fallende Flanke an PC2 warten
        while((PINC & (1<<2))){};
        PORTD &= ~(1<<6);//PD6 low       <---------------------
        i2c_start(...); //-> TWI-Master von Peter Fleury
        ...
     }
     ... 
   }
}

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

Autor: Peter Buttgereit (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter Buttgereit (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.