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.