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
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.
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. ...?
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.
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
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
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.
Vermutung korrekt. Macht alles die Hardware im Hintergrund. Für irgendwas müssen die vielen Transistoren ja gut sein... Gruß, heinz
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.