Hallo, ich habe ein kleines I2C-Netzwerk aus 2 AtMega16 aufgebaut. Beide haben externe Taktquellen(Quarz 4MHZ), die FuseBits sind dementsprechend gesetzt. Als Pull-Up Widerstände habe ich 2k genommen. Jedoch lässt sich mit einem Oszilloskop nicht einmal der Schiebetakt SCL an PC0 lesen, wo er eigentlich sein sollte. Der Sende-Controller(Master) läuft auf einem STK500, für den Controller, der empfangen soll(Slave), habe ich eine kleine Schaltung aus Spannungsversorgung und Quarz aufgebaut. Das Oszilloskop ist aber allgemein etwas komisch, sodass es sein kann, dass es etwas falsches anzeigt. Ich poste jetzt mal die beiden Queltexte für beide Controller, vielleicht sind die ja falsch: Sender: .INCLUDE "m16def.inc" .CSEG rjmp start .ORG $2A start: ldi r16,LOW(RAMEND) ;Stapel anlegen out SPL,r16 ; ldi r16,HIGH(RAMEND) ; out SPH,r16 ; ldi r16,50 ;Vorteiler 50 out TWBR,r16 ;Faktor 1 ldi r16,$1 ;in die Taktregister out TWSR,r16 ;für Takt ca. 10Khz loop: sbis PIND,PD0 ;Wenn Taster gedrückt rjmp send ;sende rjmp loop ; send: ldi r16,(1 << TWINT) | (1 << TWSTA) | (1 << TWEN) out TWCR,r16 ;Startbedingung ausgeben send1: in r16,TWCR ; sbrs r16,TWINT ;überprüfen, ob gesendet rjmp send1 ; ldi r16,0b00000010 ;Adresse+Write laden out TWDR,r16 ;in Datenregister ldi r16,(1 << TWINT) | (1 << TWEN) out TWCR,r16 ;Adresse senden send2: in r16,TWCR ; sbrs r16,TWINT ;Prüfen, ob gesendet rjmp send2 ; ldi r16,$00 ;00 laden = out TWDR,r16 ;alle LEDS an ldi r16,(1 << TWINT) | (1 << TWEN) out TWCR,r16 ;Daten senden send3: in r16,TWCR ; sbrs r16,TWINT ;Prüfen, ob alles rjmp send3 ;gesendet ldi r16,(1 << TWINT) | (1 << TWSTO) | (1 << TWEN) out TWCR,r16 ;Stopbedingung ausgeben rjmp loop Empfänger: .INCLUDE "m16def.inc" .CSEG rjmp start .ORG TWIaddr ;Bei Interrupt jmp rec ;an TWI gehe zu rec .ORG $2A start: ldi r16,LOW(RAMEND) ;Stapel out SPL,r16 ; ldi r16,HIGH(RAMEND) ; out SPH,r16 ; ser r16 ; out DDRB,r16 ;DDRB ist Ausgang out PORTB,r16 ;alle LEDS aus ldi r16,0b00000010 ;Adresse ohne out TWAR,r16 ;General Call laden ldi r16,(1 << TWEA) | (1 << TWEN) out TWCR,r16 ;ACK anschalten sei ;Interrupts setzen loop: rjmp loop ;Warteschleife rec: cli ;Interrupts abschalten ldi r16,(1 << TWINT) | (1 << TWEN) out TWCR,r16 ;Daten holen rec1: in r16,TWCR ; sbrs r16,TWINT ;und kontrollieren rjmp rec1 ; in r16,TWDR ;nach r16 out PORTB,r16 ;dann PortB sei ;Interrupts an reti ;Rücksprung
Hallo Florian, weshalb hast Du kein DDR beim Sender beschrieben - ist das ein Trick, den ich nicht durchschaue ? Gruss Otto
das soll nur ein Versuch sein, der Sender sendet permanent 00, damit beim Empfänger alle LED's angehen. und für I2C braucht man doch kein DDR, oder irre ich mich?
@ Florian Glaser > das soll nur ein Versuch sein, der Sender sendet permanent 00, damit > beim Empfänger alle LED's angehen. und für I2C braucht man doch kein > DDR, oder irre ich mich? Er irrt sich. Die I2C Leitungen sind open Drain, d.h. du kannst nicht 0 und 1 ausgeben, sondern nur 0 und Z (Tristate). Dazu brauchst du das DDR Register, um die Pins zwischen Ausgang (0) und Eingang (Z) umzuschalten. MfG Falk
aha. und das bedeutet ich muss auf PC0 und PC1 das DDR-Bit 0 setzen? Dass die Pins Tristate sind, habe ich übrigens heute mittag mit meinem Oszilloskop gemerkt ;). Ich muss also bei Initialisieren einfach die DDR-Register noch setzen?
@ Florian Glaser > aha. und das bedeutet ich muss auf PC0 und PC1 das DDR-Bit 0 setzen? > Dass die Pins Tristate sind, habe ich übrigens heute mittag mit meinem > Oszilloskop gemerkt ;). > Ich muss also bei Initialisieren einfach die DDR-Register noch setzen? Schreib in DDRx und PORTx erstmal 0. D.h. alles Tristate, die exteren Pull-ups ziehen dann auf HIGH. (warum 2k? 10K tuns meist völlig) Wenn jetzt ein AVR Daten ausgeben will (Daten oder ACK-Bit), schreib er die in DDRx, NICHT in PORTx. 0 ausgeben : DDRx = 1 (Ausgang, Portx ist 0, 0 wird ausgegeben) 1 ausgeben : DDRx = 0 (Eingang, Tristate, 1 wird ausgegeben, gezogen durch Pull-ups.) MFG Falk
Um sicher zu gehen, dass wir nicht aneinander vorbeireden: Ich spreche von einem AtMeag16, mit integrierter TWI-Steuerung. PC0 ist takt und PC1 datenleitung. und dafür muss man die DDR-Register setzen?
Ohhh, das ist natürlich was anderes. Ich dachte du machst das per Software. Wie das mit dem TWI-Modul im Detail läuft weis ich nicht. Entschuldigung. MfG Falk
;) kein Problem. das will ich ja gar nicht. so tief will ich da gar nicht eintauchen, einfach den bus benutzen. also ich probier das jetzt nochmal aus, irgendwas kann da nicht stimmen. danke für deine antworten, hoffentlich schreibt noch jemand anderes was :)
Hallo Florian, leider kann ich Dir auch nicht sagen, ob beim TWI die DDR gesetzt werden müssen. >> Das Oszilloskop ist aber allgemein etwas komisch, >> so dass es sein kann, dass es etwas falsches anzeigt. Evtl. versuchst Du es zuerst mal mit LED und setze ausserdem noch die DDR. Gruss Otto
Okey, das Problem hat sich nun bis auf weiteres erledigt. Folgendes: Die DDR-Rehister müssen NICHT gesetzt werden, sie werden kompeltt gesperrt, sobald man in TWBR bzw TWCR etwas schreibt. Mein Oszi misst nun mit 2k Pull-Up einen Takt, und wenn man auf einen Taster drückt auch Daten :T Diese werden zwar nur als gezackte Doppellinie angezeigt, das liegt aber wohl an dessen Auflösung. Da ich meinen 2ten Atmega heute mittag durch einen Kurzschluss geschrottet habe :( besorge ich mir da einen neuen, und probiers dann nochmal. Danke an alle, die mir so schnell geantwortet haben, wenn man jemand hat, der mit einem redet, ist das Lösen eines Problemes immer viel einfacher :T
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.