Hallo zusammen, mit dem TWI-Bus möchte ich Daten aus einem Beschleunigungssensor Auslesen. jedoch stoße ich auf folgendes Problem: der Master lästen den Sensor nach Übertragung der Slaveaddresse und Übertragung des Registers den Slave nicht mehr antworten sondern Sendet sofort die Stoppbedingung. Wenn ich jedoch diese aus meinem Code Rauslösche überträgt der Slave noch das erste Byte bis es dazukommt das der Master eig. das ACK senden müsste(kann er ja auch nicht). Ich hänge von beiden Szenarien noch Bilder meines Oszilloskope dran. meine Vermutung ist das der Master nicht erkennt das er Daten empfangen soll und deshalb direkt die Stoppbedingung Sendet. Die soll Übertragung ist laut Datenblatt des Sensors; Start,Adresse/WRITE,Register,Stopp,Start;Adresse/READ, 6 Byte Datenübertragung, Stopp Auf den Bildern sind die Stoppbedingung zu Sehen und dann die Adressübertragung, im bild ohne der stoppbedingung ist noch das erste bayt der datenübertragung zu sehen“ 0x01“. der Code Bezieht sich auf die Artikel http://elk.informatik.fh-augsburg.de/da/da-21/Tutorial/tutorial.html 2.13 TWI und http://www.mikrocontroller.net/articles/AVR_TWI ich würde mich sehr freuen wenn ihr mir helfen könnt den Fehler zu finden grüße Sebastian
Basti schrieb: > meine Vermutung ist das der Master nicht erkennt das er Daten empfangen > soll Das musst du ja auch selber Programmieren, das "weiß" der Master nicht von sich aus. Nach einem Stop ist auf dem Bus die Kommunikation beendet, da macht der Slave nichts mehr. Neben Start und Stop gibt es daher auch noch repeat_start usw., mit denen sich eine Kommunkation mit mehr als einem Byte aufbauen lässt. Alle Infos gibts dazu, wie immer, per google im Netz. Hilfreich ist auch die i2c-lib vonm Peter Fleury. Oliver
mein problem ist ja nicht das der slave nicht weiß das er was senden soll, das macht er ja auch(wen ich die stopp weglasse) ich zitiere aus aus meiner erstequelle: wert= TWDR; Der Master sendet ein ACK zum Slave. Das TWINT-Bit wird wieder von der Hardware gesetzt, es findet die Überprüfung statt, ob der Slave Daten geschickt hat, TWINT wird in der Software gelöscht und der Master kann das nächste Datenpaket aus dem TWDR-Register lesen. Dies wird solange wiederholt, bis der Master das letzte Datenpaket empfangen hat. Dessen Eingang muss er dann durch ein NACK (Not Acknowledged) bestätigen. Danach sendet der Master die Stopbedingung und der Datenaustausch wird beendet. TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); ich verstehe das so das das alles in der TWI.h Bibliothek definiret ist das mit der Kombi start stopp das der master weiß das es sich um eine Master Receiver handelt?!
Basti schrieb: > Start,Adresse/WRITE,Register,Stopp,Start;Adresse/READ, 6 Byte > Datenübertragung, Stopp Dann solltest Du es genau so programmieren. Ich sehe in Deinem Programm aber nirgends eine Zählschleife bis 6, die die Bytes einliest. CPUs haben die komische Eigenschaft, genau das zu tun, was man hinschreibt. Sie lesen nicht Deine Gedanken. Peter
wenn das Problem das wäre das der Controler nicht bis 6 zählen muss, müste er ja nach meinem code wenigsten das erste byte Empfangen? grüße basti
Basti schrieb: > wenn das Problem das wäre das der Controler nicht bis 6 zählen muss, > müste er ja nach meinem code wenigsten das erste byte Empfangen? Nö. Warum sollte er. In dem Moment, in dem der Master den Stop generiert, ist die Sache mit der Datenübertragung für den Slave Schnee von gestern. Und genau das macht dein Code Start generieren Slave Adressieren Stop generieren Wie soll denn da der Slave jemals seine Daten loswerden?
1 | ....
|
2 | while (!(TWCR & (1<<TWINT))); |
3 | TWDR = (0x02<<1) | TW_WRITE; |
4 | // ACK und Stop senden
|
5 | TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); |
6 | |
7 | //somit sollte der Slave wissen auf welches Register ich zugreifen Will.
|
8 | _delay_us(150); |
Nö. Den Slave interessiert das alles nicht mehr. Dadurch dass du 1<<TWSTO gemacht hast, hast du die Kommunikation als beendet erklärt. Hol dir die Fleury Lib.
okay das ist einleuchtend. ich habe es jetzt mit der schleife versucht for (i=0;0<5;i++) int i; for (i=0;0<5;i++) {//wert auslesen wert = TWDR; //ACK senden TWCR = (1<<TWINT) | (1<<TWEN); } TWCR = (1<<TWINT) | (1<<TWEN)|(1<<TWSTO); } der code Folgt direkt nach der 2 Übertragung der Slaveaddresse ich weiß das der Slave mich verstanden hat, weil ich ja das erste byte als Antwort kriege wenn ich die stopp weglasse. mit dem neuen code erhalte ich jetzt eine antwort aber der master schreibt das ack bit nicht ich habe es mit verschiedenen Versionen aus dem Internet versucht: TWCR = (1<<TWINT) | (1<<TWEN)|(1<<TWSTO); TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWEA)|(1<<TWIE); TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC) ; jedoch wurde bei keiner dieser Codeschnippel ein ack gesendet.
Basti schrieb: > okay das ist einleuchtend. > ich habe es jetzt mit der schleife versucht > for (i=0;0<5;i++) > > > int i; > for (i=0;0<5;i++) > {//wert auslesen > wert = TWDR; > //ACK senden > TWCR = (1<<TWINT) | (1<<TWEN); > } und wer wartet darauf, dass das eine Byte dann auch draussen ist, ehe es weitergeht? Ich kann mich nur wiederholen. Hol dir die Fleury Lib. Und sei es nur um zu studieren, wie er das gemacht hat. > ich habe es mit verschiedenen Versionen aus dem Internet versucht: Einfach irgndwelche Codeschnipsel (im konkreten Bits setzen) aus 'dem Internet' zu verwenden ohne sie zu verstehen bzw., zu wissen warum und wieso gerade diese Bits, ist sinnlos. So lernst du nix. Wenn du dir was aus 'dem Internet' holst, dann hol dir eine fertige Lib, stell sicher dass sie funktioniert und dann STUDIER den Code! So lernst du. Die Zeiten, wo du nur die Bitnamen brauchtest und die dir irgendwie zusammengesucht hast, sind offenbar vorbei. Jetzt geht es immer mehr um Konzepte, die sich in ganzen Codesequenzen niederschlagen; in Abläufen. Die kann man nicht mehr verstehen, indem man einfach irgendwelche Bits setzt und die solange durchiteriert, bis es klappt.
hier der code der in der Fleury Lib. verwendet wird. /*********************************************************************** ** Read one byte from the I2C device, request more data from device Return: byte read from I2C device ************************************************************************ */ unsigned char i2c_readAck(void) { TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); while(!(TWCR & (1<<TWINT))); return TWDR; }/* i2c_readAck */ und mein code: TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); while(!(TWCR & (1<<TWINT))); TWDR = wert; das Ergebis was mein Oszilloskop ausgibt ist das gleiche :das ACK wird nicht gesendet!
> return TWDR; > > TWDR = wert; uns was ist der Unterschied? warum sollte ein ACK gesendet werden, wenn du ein Datum ausgibst?
der unterschied ist das das eine veröffentlichte Bibliothek ist und das 2 von mir geschrieben wurde. damit soll der bus ausgelesen werden. das ack soll von gesetzt werden wenn der master alles empfangen hatt und das sollte er selbstständig machen wenn das byte versendet wurde! und das wird doch hier gesagt: TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); while(!(TWCR & (1<<TWINT))); oder irre ich mich?
ich wollte darauf hinaus, dass: >> return TWDR; hier TWDR gelesen wird und hier >> TWDR = wert; TWDR gesetzt wird. Damit ist Dein Code schon mal signifikant anders als der veröffentlichte.
natürlich ist er vom äußeren anders. aber inhaltlich ist er mit dem was das auslesen identisch. und ein ack wird mit der Fleury Lib auch nicht gesendet.
ich habe jetzt den Code so umgeschrieben das das der slave die 6byts senden kann. der Master sendet zwar immer noch keine ACKs aber ich kriege jetzt alles zugesendet. eine frage habe ich jetzt jedoch {_delay_us(50); TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); while(!(TWCR & (1<<TWINT))); } das ist die Routine die 6mal wiederholt wird. muss ich in der Routine jeweils eine Variable mit twdr Beschreiben oder kann ich auch den gesamten TWDR in einem Schwung am ende Raus holen ? vielen dank schon mal
Basti schrieb: > muss ich in der Routine > jeweils eine Variable mit twdr Beschreiben oder kann ich auch den > gesamten > TWDR in einem Schwung am ende Raus holen ? Warum hast Du so große Angst vor Datenblättern? Oder steht darin irgendwo, daß TWDR 48 Bit groß ist? Du solltest Dir wirklich erstmal die Beschreibung des I2C durchlesen. Peter
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.