Hier fehlt noch ein 0b, momentan ist das noch dezimal:
Code:TWCR =10010100; //Stop
Grüße, Bernhard
Hier fehlt noch ein 0b, momentan ist das noch dezimal:
Code:TWCR =10010100; //Stop
Grüße, Bernhard
Oh, sowas dummes
Danke vielmals, es funktioniert jetzt.
Ich erhalte alle ACK´s.
Wenn ich dem Sensor seine Masse wegnehme, dann bekomme ich keine ACK´s.
Also er fühlt sich jedenfalls angesprochen und funktioniert.
Jetzt habe ich nur noch eine Frage.
Wann beginnt der Sensor zu senden?
Automatsich, anchdem das ACK angekommen ist oder muss man erst TWINT auf 1 setzen?
Sobald er gesendet hat, steht dann der wert sofort im TWDR register?
Gruß
Olaf
Hallo,
Wunderbar, dass das funktioniert. (Wenn du dem Sensor die Masse wegnimmst, kann er logischerweise nicht antworten, da er für's ACK ja auf Masse ziehen muss, die dann ja fehlt.)Wenn ich dem Sensor seine Masse wegnehme, dann bekomme ich keine ACK´s.
Also er fühlt sich jedenfalls angesprochen und funktioniert.
Der Master kann steuern, ob er lesen oder schreiben will, das geschieht mit der Adresse, genauer: mit dem niedrigsten Bit.
Siehe: http://rn-wissen.de/index.php/I2C#Adressierung
Du brauchst ungefähr diesen Ablauf:
Ich würde dir auch noch empfehlen, einzelne Codeabschnitte als Methoden/Funktionen zu programmieren, das erhöht die Lesbarkeit/Übersicht, lässt sich wiederverwenden und bringt meistens weniger Fehler mit sichCode:I2C-Start Sende Slave-Adresse+Write Sende Nummer des Registers, das ausgelesen werden soll I2C-Stop oder Repeatet-Start Sende Slave-Adresse+Read Lese vom Bus (" TWCR=0b10000100; while(!(TWCR&128)){}; return TWDR; ") I2C-Stop
Grüße,
Bernhard
Geändert von BMS (02.04.2012 um 16:37 Uhr)
Hallo
Vieln Dank für deine Antwort.
Es ist mir gerade gelungen die Chip ID auszulesen: 0b010
Das habe ich gemacht um zu sehen, dass acuh wirklich der Sensor mit mir redet und das ACK nicht sonstwoher kommtWenn du dem Sensor die Masse wegnimmst, kann er logischerweise nicht antworten, da er für's ACK ja auf Masse ziehen muss, die dann ja fehlt
Jetzt gehts daran schöne, nutzerfreundliche und schnelle Funktionen zu schreiben.
Aber ein Problem habe ich da noch.
Und zwar muss ich trotz der Überprüfung des Statusregisters nach dem Start und nach dem Senden warten, damit alles funktioniert (_delay_ms (1)
Ich habe die Startfunktion ein wenig umgeschrieben, aber das bringt auch nichts:
Also nach dem Senden muss ich erst auf TWINT warten und dann auf das ACK ?Code:void i2c_start() { TWCR=0b10100100; //TWEN, TWSTA und TWINT; unschön, aber geht ;) while(!( TWSR ==0x08 || TWSR==0x10 )) ; //warten bis fertig start oder repeated start _delay_us (10); //Ohne delay geht es momentan nicht }
Ich habe gerade gesehen, dass es 2 Register gratis dazu gibt
2 Ungenutzte Register, in die man schreiben kann, was man will, 2Byte Speicher umsosnt!
Gruß
Olaf
Gruß
Olaf
Mit welcher Geschwindigkeit betreibst du denn nun den Bus? (SCL-Frequenz)?Und zwar muss ich trotz der Überprüfung des Statusregisters nach dem Start und nach dem Senden warten, damit alles funktioniert (_delay_ms (1)
Ich habe die Startfunktion ein wenig umgeschrieben, aber das bringt auch nichts
Evtl musst du auch mal das Datenblatt von deinem Sensor durchschauen, ob in dieser Hinsicht etwas von Verzögerungen drinsteht. Auch die maximale Taktfrequenz vom Bus für den Sensor müsste da drinstehen.
Von I2C-EEPROMs weiß ich z.B., dass sie ungefähr 1ms zum Schreiben von einem Byte benötigen.
In dem Moment, wo TWINT entsprechend gesetzt wurde, ist die komplette Datenübertragung abgeschlossen. Ob das ACK dabei empfangen wurde, kannst du dann ja auslesen. Auf das ACK musst du in diesem Sinne nicht "warten".Also nach dem Senden muss ich erst auf TWINT warten und dann auf das ACK ?
Ich würde den Controller auch nicht in eine Endlosschleife schicken zwecks ACK. Falls kein ACK kommt, würde ich die Übertragung abbrechen. Sonst wartet der Prozessor ewig wenn der Sensor mal nicht angeschlossen ist. Besser ist dann eine Art Fehlerbehandlung.
Grüße, Bernhard
Hallo, danke für deine Antwort!
Also, an der Frequenz wird es nciht lieen.
Ich Betreibe das Teil mit 20KHz.
Das Seltsame ist nur, dass ich vor dem repeatet Start 1ms warten muss.
Hier der Entsprechende Code Abschnitt:
In TWDR kommt die Adresse des 2. Registers, dann wird gesendet, aufs ACK gewartet und dann muss die 1ms pause kommen, sonst klappt der repeatet Start nicht.Code:TWDR = 0b00000010; //2. register TWCR = 0b10000100; //senden while(!( TWSR ==0x18 || TWSR==0x28 )) //ACK warten {} _delay_ms (1); i2c_start (); //rep start
Dabei muss ja eigneltich anchdem das ACK empfangen waurde alles erledigt sein.
Um eine Fehlerbehandlung kümmere ich mich Später.
Jetzt möchte ich erstmal nur eine Messung hinbekommen
Gruß
Olaf
Lesezeichen