Hallo Zusammen.
Ich arbeite mit einem ATMega324 @ 16MHz und der I2C Lib von Peter
Fleury.
Mein Board läuft mit 3,3V, Pullups mit 4k7 sind auf SDA und SCL
vorhanden.
Die Lib verwende ich folgendermaßen:
1
i2c_init();// initialize I2C library
2
3
// write 0x75 to EEPROM address 5 (Byte Write)
4
i2c_start(MMA7455_SLAVE_ADDRESS+I2C_WRITE);// set device address and write mode
5
i2c_write(reg);// write address = 5
6
i2c_write(data);// write value 0x75 to EEPROM
7
i2c_stop();// set stop conditon = release bus
i2c_start() funktioniert noch, d.h. die Start Condition und die Slave
Adresse werden erfolgreich ausgegeben.
Mein Problem ist nun dass der Bus nach i2c_start() (oder alternativ
i2c_start_wait()) nicht mehr freigegeben wird, d.h. SCL bleibt auf Low
Pegel.
Dadurch wird in i2c_write() nie das TWINT Bit gesetzt, wodurch die Lib
in der while schleife hängen bleibt:
1
unsignedchari2c_write(unsignedchardata)
2
{
3
uint8_ttwst;
4
// send data to the previously addressed device
5
TWDR=data;
6
TWCR=(1<<TWINT)|(1<<TWEN);
7
8
// wait until transmission completed
9
while(!(TWCR&(1<<TWINT)));
Auf dem Bus ist nach i2c_start() keinerlei Aktivität mehr zu sehen.
Um den Slave als Fehlerquelle auszuschließen ist dieser momentan nicht
angeschlossen, er kann also nicht SCL auf Low ziehen.
Ich hoffe ihr könnt mir helfen.
Grüße, Alex
Ich arbeite nicht mit einem ATMEGA, sondern programmiere eher PICs. Mein
erster Tip ohne mich jetzt näher mit der Software zu beschäftigen wäre,
die Pullups auf 2,2k zu verkleinern. Bei 3,3V erscheinen sie mir zu
groß, da schon ein gewisser Strom fließen muss.
gruß~
kannst du mal oszi plots posten ?
SCL auf low ist erstmal ok, wenn eine start condition gesendet wurde ist
das der normale zustand mit eine stop condition gesendet wird.
heldvomfeld schrieb:> dann tausch die Widerstände zurück, bei 1k könnte der Strom für die Pins> des µC zu groß sein. Baudrate gecheckt?>> gruß~
an den widerständen liegt das nicht... alles von 1...10k funktioniert
bei 3.3v..
Hallo,
die Pullups habe ich wieder auf 4k7 geändert.
DS0000.png zeigt die Aktivität von i2c_start().
DS0001.png zeigt die Pegel danach.
Ich hoffe das hilft.
jo das ACK vom slave fehlt, beim 9ten clockbit müsste auf der SDA
leitung ein low pegel zu sehen sein.
wenn der slave kein ack sendet ist das was du siehst das normale
verhalten. in diesem fall wird vom TWI modul eigtl auch ein fehlerflag
gesetzt, dass deine lib aber nicht auszuwerten scheint
Hallo,
danke für den Tip, dann sollte ich doch den Slave anschliessen :)
Nachdem ich die Slave Adresse nun korregiert habe, kommt ein ack und das
Schreiben klappt.
Nun habe ich allerdings dasselbe Problem beim Lesen vom I2C:
1
i2c_init();// initialize I2C library
2
i2c_start(MMA7455_SLAVE_ADDRESS+I2C_WRITE);// set device address and write mode
3
4
i2c_write(reg);// write address = 5
5
i2c_rep_start(MMA7455_SLAVE_ADDRESS+I2C_READ);// set device address and read mode
6
7
*data=i2c_readNak();// read one byte from EEPROM
8
i2c_stop();
nach i2c_rep_start() bleibt SCL wieder auf Low und i2c_readNak() bleibt
wieder in der Schleife hängen.
Hier noch die Scopescreens:
DS0002.png Aktivität von i2c_start
DS0003.png Aktivität von i2c_write
DS0004.png Aktivität von i2c_rep_start
DS0005.png Pegel nach i2c_rep_start
Ich habe nun noch einen anderen I2C Slave (Tempsensor statt
Beschleunigungssenor) mit der Lib unter den selben Bedingungen getestet.
Dieser antwortet sofort und korrekt.
Also hat wohl der Beschleunigungssensor noch irgendein Problem.
Nur ein Schnellschuss: Prüfe die Initialisierung des
Beschleunigungssenors.
Beim MMA7455L: ±2g/±4g/±8g Three Axis Low-g Digital Output Accelerometer
(#1) muss zuerst vom voreingestellten 4-Wire SPI Interface auf das
3-Wire SPI Interface umgestellt werden. Dafür gibt es das Mode Control
Register ($16). In Verbindung mit einer fest verdrahteten CS Leitung
kann man anschliessend eine I2C Verbindung benutzen.
#1
http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MMA745xL
:) genau diesen Beschleunigungssensor habe ich.
Und im Moment initialisiere ich ihn auch auf 4wire SPI, da ich dachte
dass dies keine Auswirkung auf den I2C Betrieb hat.
Ich schreibe in das MCTL Register nun 0x25, also 3wire SPI, 2g Mode,
Measurement Mode.
Allerdings bleibt das Problem bestehen.
In einem anderen Projekt setze ich übrigens den MMA7455L erfolgreich mit
SPI Interface ein. Daher verstehe ich nicht warum ich das (eigentlich
simplere) I2C Interface nicht zum laufen bekomme.
Ich habe den nackten Sensor auf nem selbstgeätzten Board um ihn
Steckbrett kompatibel zu machen. Genau dieses Board habe ich schon für
ein altes Projekt benutzt mit SPI Interface.
Im aktuellen Aufbau habe ich CS direkt (ohne Pullup) auf High gelegt,
wie im Datenblatt angegeben
Alex schrieb:> Hier noch die Scopescreens:> DS0002.png Aktivität von i2c_start> DS0003.png Aktivität von i2c_write> DS0004.png Aktivität von i2c_rep_start> DS0005.png Pegel nach i2c_rep_start
Mir fällt auf, du schreibst von i2c_start, i2c_write, i2c_rep_start aber
nichts von i2c_stop. Ich kenne deine Funktionen nicht, aber wenns ein
i2c_start gibt, sollte es auch ein i2c_stop geben.
MfG Klaus
Hallo Klaus,
i2c_stop() wird auch aufgerufen, siehe die beiden Code Auszüge.
Nur einen Screenshot davon habe ich nicht, da der µC gar nicht soweit
kommt.
Frage an I2C Kenner: seht ihr auf den Screenshots DS002 bis DS004 ACKs
vom Slave?
Alex schrieb:> NACK == high, ACK == low ?
ACK ;-)
ich merk es mir so: wenn keiner etwas macht, ist der Bus high durch den
Pullup, also ist high NACK. Wenn sich einer angesprochen fühlt, wird er
aktiv und erzeugt ein low.
MfG Klaus
die Signale auf den Bildern DS0002, DS0003 und DS0004 erfüllen meiner
Meinung nach alle nicht die Voraussetzung eines ACKs. Bei einem ACK muss
der Slave die Datenleitung auf low ziehen BEVOR der Clock das neunte Mal
auf High geht. In allen drei Fällen liegt die Datenleitung aber auf
High, wenn der Clock das neunte Mal auf High geht, das sollte der Master
als NACK interpretieren.
Warum immer ein NACK kommt weiß ich nicht, da ich den
Beschleunigungssensor nicht kenne.
Aber mal zurück zum Anfang:
Wenn nur der Master auf dem Bus ist, Pullups natürlich auch, muß eine
Sequenz von
i2c_start
i2c_write(irgendwas)
i2c_stop
den Bus nach 9 Takten wieder zur Ruhe (alles high) bringen. Der Status
von write muß NACK liefern. Bevor das nicht erreicht ist, würde ich es
mit einem Slave nicht versuchen.
MfG Klaus
Thorsten schrieb:> Warum immer ein NACK kommt weiß ich nicht, da ich den> Beschleunigungssensor nicht kenne.
Das muß nicht am Sensor liegen, NACK kommt auch von alleine, wenn keiner
den Bus low zieht.
MfG Klaus
Also der Temperatursensor kommuniziert ja bestens mit meinem Master. Ein
schönes ACK dh lowpegel bevor die 9te steigende Taktflanke kommt.
Der Beschleunigungssensor liefert NACK dh highpegel bevor die 9te
steigende Taktflanke kommt. Im Datenblatt wird leider nicht erwähnt
unter welchen Umständen ein NACK erzeugt wird.
Ich habe nun die Frequenz auf 50 kHz halbiert und als Wartezeit bevor
der I2C das erste mal "losfeuert" von 1ms auf 1s erhöht.
Zwischendurch habe ich mal bemerkt dass ich die Slaveadresse immer noch
falsch hatte (0x1D um 1 Bit nach links geschoben). Dieser Fehler erzeugt
aber auch dasselbe Verhalten. Eigentlich sollte sich bei falscher
Adressierung der Baustein doch nicht angesprochen fühlen und einfach nix
machen.
Also selbes Problem mit MMA7455 bei halber Taktfrequenz und richtiger
und falscher Adresse.
Ich habe nun noch alle beiden Slaves vom Bus abgeklemmt (pullups
weiterhin vorhanden) und es zeigt sich dasselbe Problem. Der NACK
scheint also nicht vom Beschleunigungssensor erzeugt zu sein, sondern
wie Klaus schon geschrieben hat durch die Pullups
Klaus schrieb:> Thorsten schrieb:>> Warum immer ein NACK kommt weiß ich nicht, da ich den>> Beschleunigungssensor nicht kenne.>> Das muß nicht am Sensor liegen, NACK kommt auch von alleine, wenn keiner> den Bus low zieht.>> MfG Klaus
Ich meinte damit, dass ich den Sensor nicht kenne und dadurch nichts
genaueres sagen kann, ob man bei diesem Baustein etwas beachten muss
oder nicht. Ich hab nur darauf hinweisen wollen, dass keines der Pakete
mit einem ACK bestätigt wird. Warum das so ist, ob es am Sensor oder am
Master liegt, weiß ich nicht.
> DS0002.png Aktivität von i2c_start
In diesem Bild lese ich die Bitsequenz
1
<Start><0><0><1><1><1><1><0><write><nack>
Es gibt eine Konfusion, wie Hersteller die slave address in der Doku
angeben - mit/ohne RW-Bit, mit ohne Shift nach links...
http://www.totalphase.com/support/kb/10039/
Ich gehe davon aus, dass die 0x1D in der Freescale Doku eine korrekte
7-Bit ([6:0]) Adresse ist. D.h. 1 zeigt nicht die I2C slave address
$1D, wie sie in der Freescale Doku beschrieben ist (S. 16), sondern die
slave address $1E.
Ich hätte das folgende Muster erwartet:
2
<Start><0><0><1><1><1><0><1><write>...
Die Fleury-I2C-Lib schickt die an i2c_start übergebene Adresse (inkl.
RW-Bit) 1:1 and die TWI Schnittstelle. D.h. man muss sich um das Shiften
der slave address um 1 Bit nach links selbst kümmern. Ich würde das
deshalb bei der Definition berücksichtigen - Adresse aus der Doku der
Lesbarkeit halber eintragen und gleich 1x shiften.
Alex schrieb:> Ich habe nun noch alle beiden Slaves vom Bus abgeklemmt (pullups> weiterhin vorhanden) und es zeigt sich dasselbe Problem. Der NACK> scheint also nicht vom Beschleunigungssensor erzeugt zu sein, sondern> wie Klaus schon geschrieben hat durch die Pullups
Zum Verständnis: Genau das ist die Aufgabe der Pullups. Master und Slave
sind nur in der Lage die Leitungen auf Low zu ziehen. Wenn alle "die
Füße still halten", wird die Leitung durch die Pullups auf High gezogen.
Ein NACK ist keine aktive Handlung eines Bausteins, sondern bedeutet
nur, dass keiner aktiv reagiert und die Leitung auf low zieht (ACK).
Stell dir eine Menschenmenge vor. Du bist der Master und rufst einen
Namen in die Runde (unter der Annahme, dass jeder Name nur einmal
vertreten ist). Derjenige, der sich angesprochen fühlt, wird sich
melden, alle anderen werden nicht reagieren. Fühlt sich keiner
angesprochen (die gesuchte Person ist nicht da) oder einer hat dich
vielleicht nicht verstanden, meldet sich halt keiner.
Wenn ich das Datenblatt richtig deute, gilt die Addresse 1D (bzw. 1D <<
1) nur wenn der Pin IADDR0 auf High liegt. Wie hast du den Pin
beschaltet? Liegt der Pin auf Low, müsste die Adresse entsprechend 1C
(bzw. 1C << 1) sein.
Hallo zusammen,
nachdem mir und euch die Ideen ausgegangen sind,
habe ich den IC ausgetauscht.....
ACK kommt nun, Daten auch.
Vielen Dank für euer Bemühen, schönen Abend !