Forum: Mikrocontroller und Digitale Elektronik TWI/I2c Master läst Slave keine Datan senden


von Basti (Gast)


Angehängte Dateien:

Lesenswert?

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

von Basti (Gast)


Angehängte Dateien:

Lesenswert?

hier nochmal der code

von Basti (Gast)


Angehängte Dateien:

Lesenswert?

heute hab ichs irgendwie
sry :(

von Oliver (Gast)


Lesenswert?

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

von Basti (Gast)


Lesenswert?

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?!

von Peter D. (peda)


Lesenswert?

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

von Basti (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Basti (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Basti (Gast)


Lesenswert?

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!

von Bernd M. (bernd_m)


Lesenswert?

>     return TWDR;
>
> TWDR = wert;

uns was ist der Unterschied?

warum sollte ein ACK gesendet werden, wenn du ein Datum ausgibst?

von Basti (Gast)


Lesenswert?

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?

von Bernd M. (bernd_m)


Lesenswert?

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.

von Basti (Gast)


Lesenswert?

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.

von Basti (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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
Noch kein Account? Hier anmelden.