Während meines momentan laufenden Projektes ist dieses TWI Modul entstanden, welches ich euch nicht vorenthalten möchte. Natürlich wieder in ASM. Vielleicht kann es irgendjemand gebrauchen und ich konnte damit weiter helfen. Ich habe mal noch ein Beispiel mit angehangen, damit man weiß wie das Modul benutzt werden kann. Grüße Steffen
Ich habe jetzt gerade ein Problem erkannt: Wenn der TWI Interrupt durch irgend einen anderen Interrupt aufgehalten wird, dann verzögert sich komischerweise auch die Stop-Bedingung. Dieses Verhalten ist allerdings in keinem Datasheet nachzulesen. Das TWI_busy Flag wird schon dann gelöscht, wenn die TWI-Hardware als nächste Aktion ein STOP ausführen soll. Dadurch weiß man natürlich nicht, ob die TWI-Hardware die STOP-Bedingung auch schon auf den BUS gebracht hat. Wenn man dann im ungünstigsten Fall sofort auf ein gelöschtes TWI_busy Flag reagiert und eine neue Datenübertragung per START einleitet, ist die Zeit zwischen STOP und START auf dem I2C Bus sehr kurz. Und wahrscheinlich so kurz, dass der Slave dies nicht mehr verarbeiten kann und ein NACK auf die gültige Adresse sendet! Hab das Problem mal im Anhang grün eingekreiselt. In welcher Specs/Appnote von Atmel findet man die TWI Hardware Timings? Oder wie könnte man dieses Problem lösen? Steffen
Hallo, Ich suche immer noch nach Spezifikationen/Timings der AVR Controller. Hat jemand einen Tip? Wo hat ATMEL sowas versteckt?
@Steffen >Wenn der TWI Interrupt durch irgend einen anderen Interrupt aufgehalten >wird, dann verzögert sich komischerweise auch die Stop-Bedingung. Das muss auch so sein, denn der µC kann nur einen Interrupt zur gleichen Zeit abarbeiten. Natürlich kann man "verschachtelte" Interrupts zulassen durch "SEI" in der Interrupt-Routine. Ich füge gern eine angemessene Pause nach einem STOP ein, damit die SLAVES auf STOP regaieren könnnen, es kann vorkommen, dass nach einem Stop der SLAVE noch Daten verarbeiten muss. Gib ihnen die Zeit ;-) Gruß Bernhard
Hab's gefunden. TWI Characteristics steht in jedem AVR Datasheet unter Electrical Characteristics. Übrigens, die Zeit zwischen STOP -> START nennt sich laut Datasheet tBuf und sollte mindestens _1.3µs_ lang sein.
Hmm, ich muss jetzt zusehen dass mein TWI_busy erst durch einem realen "STOP" auf dem Bus zurückgesetzt wird. Da Hardwareseitig ja kein Interrupt durch beendeter Aktion "STOP" auf dem Bus ausgeführt wird muss man das irgendwie anders detektieren. Mal sehen wie ich das machen kann. Ich denke dabei an einen wait to PIN CHANGE INTERRUPT auf SDA wenn die Aktion "twi_stop" in das TWCR eingetragen wird. Na mal sehen, ob das klappt
Hallo, So geht es. Mittels Pin_Change Interrupt auf den SDA Pin. Das TWI_busy Flag wird jetzt erst bei einer STOP-Bedingung auf dem Bus gelöscht. Somit kann man nun gleich nachdem das TWI_busy Flag wieder '0' ist einen neuen TWI-Start auslösen. LG Steffen
Hallo Steffen, konnte deine Routine gebrauchen, vielen Dank! Dein Problem mit der STOP-Bedingung bzw. die Lösung dessen verstehe ich nicht ganz. Aus meiner Sicht ist das mit dem PinChang-Int etwas übertrieben. Ginge das nicht auch so (Auszug aus der TWSI-ISR)?
1 | twi_process_stop: |
2 | ;TWI-Commando laden |
3 | ldi r16, twi_stop_cmd |
4 | ;TWI-Commando ausgeben |
5 | sts TWCR, r16 |
6 | ;Flags setzen/löschen |
7 | lds r16, (SR_TWI_STATE) |
8 | cbr r16, (1<<TWI_busy) |
9 | sbr r16, (1<<TWI_ready) |
10 | sts (SR_TWI_STATE), r16 |
11 | rjmp TWI_int_end1 |
12 | TWI_int_end: |
13 | sts TWCR, r16 |
14 | TWI_int_end1: |
15 | pop XH |
16 | pop XL |
17 | pop r17 |
18 | pop r16 |
19 | pop Copy_SREG |
20 | out SREG, COPY_SREG |
21 | pop Copy_SREG |
22 | reti |
Oder übersehe ich da was? mfg foikei
Hallo Florian, Das mit dem PIN CHANGE Interrupt war für mich die einzige Lösung um zu sehen, wann die TWI Hardware den STOP auf den Bus gebracht hat. Denn nur vom einschreiben des STOP-Befehls in das TWI-Control-Registers [TWCR] weiß man ja nun nicht, ob die Hardware auch sofort reagiert. Das heißt: Um das TWI_BUSY_FLAG für den Start der nächsten TWI Übertragung zu nutzen muss man diesen Umweg gehen. Denn nur mit der Version mit PIN CHANGE Interrupt und Auswertung der STOP Bedingung direkt am PIN wird das TWI_BUSY_FLAG auch erst dann zurück gesetzt und nicht schon zuvor. Siehe hier: Beitrag "Re: [ASM] Hardware TWI-MASTER Interrupt basierend für Mega AVR" Gruß Steffen
Hallo Steffen und Florian, ich finde diese Frage auch sehr interessant, da mein ATmega8A leider keinen PinChangeInterrupt kann. @Steffen: Welche Sorte Interrupts hat denn bei Dir das Stop Signal auf dem Bus verzögert? Oder ein Schlafmodus? Ich verstehe jedenfalls nicht, wie ein Interrupt, die TWI Hardware-Einheit vom Senden des Signal abhalten sollte. Die arbeitet doch selbständig, oder nicht? Gruß, Michael
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.