Forum: Mikrocontroller und Digitale Elektronik Kann I2C (TWI) am Atmega8 von Timerinterrupt gestört werden?


von Steffen S. (immanuel777)


Lesenswert?

Hallo zusammen,

ich möchte in einem Projekt den Hardware-I2C (TWI) des Atmega8 parallel 
zu einem Timer nutzen, der alle 10ms einen Interrupt auslöst. Meine 
I2C-Implementierung läuft bereits korrekt.

Wenn dann noch der Timer dazu kommt kann es aber natürlich passieren, 
dass ein Interrupt ausgelöst wird, wenn der Atmega8 gerade am 
Kommunizieren über den I2C-Bus ist.

Kann es da Probleme geben? Z.B. wenn ich gerade Daten empfange und dabei 
der Interrupt zuschlägt: Verliere ich dann die übertragenen Daten? Oder 
passiert der Empfangsprozess komplett in Hardware, so dass die 
Interruptroutine ausgeführt werden kann während das I2C-Modul die Daten 
parallel empfängt? Beim Senden ist es ja weniger ein Problem, weil da 
der Atmega8 SCL auf Low halten kann.

Vielen Dank schonmal für die Hilfe und viele Grüße,
Steffen

von Peter R. (Gast)


Lesenswert?

Bei I2C und timer int sind die Verhältnisse unproblematisch.

Der  timer-Vektor steht in der Tabelle an früherer Stelle, hat also 
höhere Priorität als I2C. Der timer-int wird also meist nur um einige 
µsec verzögert, was kaum eine Rolle spielen würde. und bricht in die 
I2C-Routine gewaltsam ein.

I2C beansprucht während der Ausführung eigentlich nur wenig CPU-Zeit. 
das Meiste läuft in der I2C-Hardware ab. In der Zeit in der die 
I2C-Hardware arbeitet, kann ein anderer int beliebig einsteigen.

Natürlich muss man auf Registerüberlappung achten (ein Register in 
beiden Routinen) bzw. in C auf lokale und globale Variablen achten.

An kritischen Stellen muss man halt mit CLI und SEI arbeiten und darauf 
achten, wann der timer-int rein darf und wann nicht.Kritische Stellen 
gibts vor Allem beim Laden/Lesen von 16-bit-Registern.

Man muss halt im Datenbuch die Seiten über das int-System und über 
int-Priorität gründlich durcharbeiten.

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Peter R. schrieb:
> Der  timer-Vektor steht in der Tabelle an früherer Stelle, hat also
> höhere Priorität als I2C.

Das mag zutreffen, wenn beide Interrupts gleichzeitig eintreffen.

> Der timer-int wird also meist nur um einige µsec verzögert, was
> kaum eine Rolle spielen würde. und bricht in die I2C-Routine
> gewaltsam ein.

Sicher? Das Datenblatt liest sich für mich ein wenig anders:

"When an interrupt occurs, the Global Interrupt Enable I-bit is cleared 
and all interrupts are disabled. The user software can write logic one 
to the I-bit to enable nested interrupts. All enabled interrupts can 
then interrupt the current interrupt routine. The I-bit is automatically 
set when a Return from Interrupt instruction – RETI – is executed."

> Man muss halt im Datenbuch die Seiten über das int-System und über
> int-Priorität gründlich durcharbeiten.

...?

von Steffen S. (immanuel777)


Lesenswert?

Danke schonmal für die bisherigen Antworten.

Ich glaube, ich muss noch etwas hinzufügen: Ich möchte den I2C nicht per 
Interrupt betreiben, sondern ich polle das TWCR-Register und überprüfe 
regelmäßig, ob das TWINT-Bit gesetzt ist.

Die Frage ist also: Wenn ich gerade Daten empfange, kann der Controller 
dann aus der Empfangsroutine "gerissen" werden oder ist das unkritisch? 
Es geht mir also nicht um eine Unterbrechung in meinem Code - das wäre 
unkritisch - sondern um eine Unterbrechung, während der Controller 
"selbstständig" die Daten empfängt.

von cppler (Gast)


Lesenswert?

Jein,
da Du pollst gehe ich mal davon aus das Du den Handshake vom I2C auch 
selber erledigst ?
Ansonsten mußt Du nachsehen wie schnell Du mit dem I2C unterwegs bist.
In der Timer-IRQ was wird da gemacht, ein Zähler für eine Timestamp 
hochgezählt ?
Im Fall der Fälle im TimerIRQ nur ein Flag setzen und das dann in der 
Hauptschleife abarbeiten.
Und wie immer wäre es am sinnvollsten sich den gesamten Code ansehen zu 
können bevor die Glaskugel vor lauter polieren zu Staub zerfällt :-P

von katastrophenheinz (Gast)


Lesenswert?

Steffen S. schrieb:
> Die Frage ist also: Wenn ich gerade Daten empfange, kann der Controller
> dann aus der Empfangsroutine "gerissen" werden oder ist das unkritisch?
> Es geht mir also nicht um eine Unterbrechung in meinem Code - das wäre
> unkritisch - sondern um eine Unterbrechung, während der Controller
> "selbstständig" die Daten empfängt.

Nein. Der TWI-Interrupt wird nur dann ausgelöst, oder anders gesagt, 
deine TWI-Polling-Schleife muss nur dann was tun, wenn eine 
TWI-Operation abgeschlossen ist. Es wird also kein Empfang unterbrochen.
Es kann jedoch passieren, daß während der Timer-Interrupt abgearbeitet 
wird, deine "TWINT-Bit gesetzt?"-Abfrage verzögert wird. Dies führt aber 
nur dazu, daß z.B. die Übertragungspause zwischen zwei TWI Bytes etwas 
länger dauert oder der Zeitraum zwischen "Byte gesendet" und "Stop wird 
gesendet" etwas längert wird, nämlich genauso lange wie du in der 
Timer-ISR rumrödelst. Wie lange das maximal sein darf: -> 
I2C-Spezifikation.

Gruss, Heinz

von Steffen S. (immanuel777)


Lesenswert?

Hallo cppler,

in der Timer-IRQ passiert nicht viel. Wie du richtig vermutest, wird ein 
Timestamp hochgezählt. Ich habe keinen Code gepostet, weil es eher eine 
allgemeine Frage sein sollte. Aber hier weiter unten nun doch etwas 
Code.

katastrophenheinz,
eine verspätete TWINT-Abfrage ist kein Problem, das ist klar. So lange 
brauche ich (wie oben geschrieben) in der Interruptroutine nicht.
Im Wesentlichen geht es darum, was passiert, wenn ich folgendes mache:
1
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
2
while ( ! (TWCR & (1<<TWINT)) )
3
{}
4
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);

Ich will also ein Byte empfangen und setze deshalb TWCR. Dann warte ich 
bis TWINT gesetzt ist, und setze TWCR erneut, um ein weiteren Byte zu 
empfangen.

(Keine Angst, mein Code sieht nicht so aus, aber das illustriert meine 
Frage. Außerdem werte ich natürlich auch das empfangene Byte aus, bevor 
ich es überschreiben lasse. :-))

Die Frage ist jetzt: Was passiert, wenn ich zum ersten Mal TWCR gesetzt 
habe, in der while-Schleife warte und gerade ein Byte empfange, wenn 
mein Timerinterrupt ausgelöst wird?

Passiert der Empfang des Bytes einfach in Hardware, so dass das 
vollkommen unabhängig von meinem restlichen Code quasi parallel läuft? 
Oder kann mein eigentlicher Code während des Empfangs des Bytes nicht 
ausgeführt werden, weil gerade empfangen wird? Dann könnte der 
Timerinterrupt hier dazwischenfunken.

Vermutlich ist meine Frage einfach doof und während des Schreibens denke 
ich immer mehr, dass der Empfang komplett in Hardware ablaufen muss, 
weil sonst das Verhalten meines Programm vollkommen unvorhersagbar wäre 
(wann  wird zum Empfangen gesprungen und wann wird mein Code wieder 
ausgeführt?). Wenn es wirklich in Hardware abläuft, dann wäre auch der 
Interrupt kein Problem.

Ich hoffe, meine Frage ist jetzt etwas verständlicher geworden.

Vielleicht kann noch jemand etwas dazu sagen, ob meine Vermutung korrekt 
ist.

von katastrophenheinz (Gast)


Lesenswert?

Vermutung korrekt. Macht alles die Hardware im Hintergrund. Für 
irgendwas müssen die vielen Transistoren ja gut sein...
Gruß, heinz

von Steffen S. (immanuel777)


Lesenswert?

Vielen Dank, katastrophenheinz!
Damit ist meine Frage eigentlich geklärt.

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.