Forum: Mikrocontroller und Digitale Elektronik I2C Übertragung unterbrechen (z.B. ATmega16 etc.)


von Matthias Thüringer (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich bin gerade dabei ein minimales "Multitasking" aufzubauen. Ein Task 
davon soll eine Kommunikation über die TWI Schnittstelle abhandeln. Die 
Kommunikation an sich funktioniert soweit. Zum Testen sollte mein 
Programm prinzipiell so aussehen:
Der Slave befindet sich in einer Endlosschleife, in der er zyklisch 
nachsieht, ob es was zu tun gibt oder nicht. Bei einem Interrupt sichere 
ich mir das TWI Status Register(TWSR). Setze ein Flag, dass es jetzt 
etwas zu arbeiten gibt und verlasse die ISR wieder. In der Hauptschleife 
"sieht" der Task "jetzt gibts was zu tun" und arbeitet alle weiteren 
nötigen Schritte ab. Wenn er fertig ist, wartet er wiederum bis der 
nächste Interrupt auftritt.
Soweit die Idee. Mein Problem ist aber, das nach dem Verlassen der ISR 
sofort wieder in die ISR gesprungen wird, und wieder und wieder.... 
Irgendwann kommt doch die Abarbeitung des Tasks in der Hauptschleife 
dran und die Kommunikation geht weiter.
Ihr könnt euch vorstellen wie lange! Genau, bis zum nächsten Interrupt!
In den Datenblättern ist beschreiben, dass es nach dem Interrupt die 
jeweilige definierte Softwareaktion auszuführen ist. Mir ist schon klar, 
dass der Interrupt nach dem Verlassen der ISR immer noch ansteht und das 
der Grund ist warum er wieder in die ISR springt. Der logische Schritt 
war die Interruptflags in dem TWI Control Register(TWCR) zu bearbeiten. 
Also TWIE usw. zurückzusetzen. Fehlanzeige! Sobald in diesem Register 
irgendetwas verändert wird, fühlt sich das TWI-Modul veranlasst, mit der 
Abarbeitung fortzufahren(z.B. den Inhalt des Adressregisters auf den Bus 
zu legen). Wenn das TWI Modul mir somit keine Möglichkeit lässt, selbst 
zu entscheiden, wann ich die weitere Abarbeitung vornehme, dann hat der 
Interrupt für mich nicht wirklich einen nutzen.
Ich habe den Beginn der Übertragung mit dem Oszi aufgezeichnet und 
angehängt.
Der gelbe Graph stellt die Sprünge in die ISR dar. Also jeder 
Flankenwechsel bedeutet einen Sprung in die ISR.
Rosa ist die Datenleitung und Grün der Takt.

Hat jemand eine Idee, wie ich es schaffe nach dem Verlassen der ISR 
nicht wieder in die ISR zu springen? Also selbst enscheiden kann, wann 
es weiter geht?

von Klaus 2. (klaus2m5)


Lesenswert?

Wenn Du in der Hauptschleife ein Flag abfragst, ob ein TWI-Interrupt 
stattgefunden hat, dann kannst Du auch gleich das TWINT im TWCR pollen. 
Der Interrupt ist vollkommen sinnlos.

von Matthias Thüringer (Gast)


Lesenswert?

Du hast schon recht. Der Programmaufbau ist zum testen gedacht gewesen. 
Später soll nicht in einer Endlosschleife eine Variable gepollt werden, 
sondern andere Tasks laufen die bestimmte (u.a. zeitliche)Bedingungen 
einhalten müssen. Wenn ich aber in der TWI-Kommunikation "festsitze" 
kommen andere Tasks die eine höhere Priorität haben nicht dran. Evtl. 
kann dann die Echtzeitbedingung nicht eingehalten werden. Ich habe ein 
bestimmtes Zeitfenster, in der die TWI-Kommunikation laufen darf und 
kann. Wenn der TWI-Interrupt während der Bearbeitungszeit eines anderen 
Tasks auftaucht, muss er laut Vorgabe warten bis er dran kommt. Also in 
der ISR alles nötige sichern und sie wieder verlassen. Die Bearbeitung 
des Interrupts hätte dann in dem für ihn vorgesehene Zeitfenster 
passieren sollen.
Mal sehen wie groß die ISR wird, wenn alles in ihr verarbeitet wird und 
wie lange ich in ihr aufgehalten werde...

von Klaus 2. (klaus2m5)


Lesenswert?

Wenn die Hauptschleife zu bestimmten Zeiten nicht unterbrochen werden 
darf, dann solltest Du in dieser Zeit alle Interrupts disablen (CLI). In 
der ISR muss nichts gesichert werden, denn ohne Abarbeitung des 
anstehenden Status geht auch von selbst nichts weiter. Nach SEI werden 
sofort die anstehenden Interrupts abgearbeitet.

Du könntest Programmteile mit höherer Priorität auch selbst als 
Interrupt starten, dann werden sie auch nicht unterbrochen. Dies kann 
durch Timer oder I/O Interrupt (Du setzt selbst die Bedingung an einem 
I/O-Pin, der dann den Interrupt auslöst) geschehen.

Wenn nur ein Teil der Interrupts verhindert werden soll, wirds beim AVR 
schwierig, denn Prioritäten bei Interrupts kann der AVR nicht.

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.