Hi! Ich habe ein paar Probleme mit der USI des AtTiny26 und ich hoffe mir kann jemand helfen. Der AtTiny26 soll nachher als SPI<->I2C Wandler agieren (mit diversen möglichkeiten den i2c bus zu konfigurieren) und ist nachher nur ein kleiner Teil der gesammten Hardware. Ich nutze hauptsächlich folgende Routinen: Initialisierung: ;Initialisiert USI als SPI slave, MISO wird vorher schon ;richtig konfiguriert... ldi temp, (1<<USIWM0)+(1<<USICS1) ;+(1<<USIOIE) out USICR, temp SPI-Transfer Funktion (aus dem Datenblatt übernommen): SpiXFer: out USIDR, SpiDat SpiXFerNoWrite: ldi temp, (1<<USIOIF) out USISR, temp SpiXFerLoop: sbis USISR, USIOIF rjmp SpiXFerLoop in SpiDat, USIDR ret Nun zu meinem Problem: Über den SPI-Bus wird - um einen i2c write-transfer zu initiieren auf den Bus ein paar bytes geschrieben, die in dem Ram zwischengepuffert werden. Wenn die zu schreibenden i2c-daten alle übertragen werden, wird ein i2c transfer durchgeführt. Wenn der i2c transfer beendet ist, rufe ich die oben stehende Funktion SpiXFer auf und lasse damit eine "0x00" ausgeben: ;...i2c transfer hier zuende... ldi SpiDat, 0x00 rcall SpiXFer Da der SPI-"Master" mitbekommen muss, wann der transfer beendet ist polle ich momentan den SPI-Bus vom Master aus, ob der zurückgelesene Wert=0x00 ist (der Master sendet dabei 0xff). Wenn der Wert 0x00 ist, ist das ein Zeichen dafür, dass der i2c-transfer beendet ist. Leider läuft an dieser stelle in 50% der Fälle die Bitsynchronisation von Master und Slave durcheinander, das heisst der Master empfängt werte wie: 0x0F 0xF0 Vermutlich kommt das dadurch, dass das USIDR-Register nicht synchronisiert ist. Nur WIE warte ich auf den Zeitpunkt, dass ein Byte zuvor komplett übertragen wurde? Ich habe es mit folgender Funktion probiert. Damit klappt es aber auch nicht: SpiWait: sbis USISR, USIOIF rjmp SpiWait ldi SpiDat, 0x00 rcall SpiXFer Hat jemand eine Idee, wie ich mein Problem lösen kann? Da das der erste AVR mit USI ist, den ich benutze bin ich da momentan ziemlich ratlos. Mit dem Overflow interrupt zu arbeiten ist leider nicht möglich, da das Auslösen des Interrupts das Timing auf dem i2c Bus beeinflußt, was auf keinen Fall geschehen darf, da er zu Tests von i2c slaves eingesetzt wird (z.B. um seine maximale Clockrate zu ermitteln). viele Grüße, Kai
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.