PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] I²C Master m328 kann Slave m328 nicht lesen



oberallgeier
02.12.2011, 13:09
Peinlich. Meine Fehlersuche und Sachstudie zum Thema hilft mir seit Tagen (Nächten) nicht weiter. Bisherige Erfahrungen mit I²C auf Atmelcontrollern: schreiben und lesen eines Beschleunigungsaufnehmers, Code von Sternthaler mit leichten Abwandlungen.

Aktuell:
Kurzfassung: Daten von einem Master (mega328/8MHz int. Osz) können auf einen Slave (mega328/20MHz Quarz) übertragen werden. Lesen der Daten vom Master geht nicht - Programm hängt.

AV RStudio4 4.18 Build 700, Master-Slave-Kopplung nach RN/Wissen (siehe hier - klick) (http://www.rn-wissen.de/index.php/TWI_Slave_mit_avr-gcc) mit den dort präsentierten Codes bzw. PFleury-Lib.
Master :
- Der Code für Master wurde geringfügig abgewandelt: Sende-/Leseschleife durch while(1) mit eingebauter Tastenabfage. Wenn Taste gedrückt werden drei andere Bytes definiert wie ohne Tastendruck.
- Die Slaveadresse ist hex70.
- Eigene, bewährte UART-Routine
Slave :
- Der Code wurde bis auf die Slaveadresse übernommen.

Ergebnis:
- Schreiben der beiden Datensätze mit/ohne Taste geht einwandfrei, siehe Ausgabebeispiel - RS232 vom Slave
- Die Schleifendurchläufe des Masters werden durch eine getoggelte LED signalisiert.
- Lesen des Masters der geschriebenen Daten geht nicht, das Programm bleibt nach der Abfrage "Slave bereit zum Lesen" hängen - belegt durch LEDsignal am Master (toggelt nicht), siehe dazu Codeabschnitt.



i2c_init(); // init I2C interface
while (1)
{ // Schleife mit verschiedenen Ausgaben
if (!(PIND & (1 << PIND2))) // Taste bringt GND auf PD2?
{ //
byte1 = 42;
byte2 = 43;
byte3 = 44;
}
else //
{ //
byte1 = 56;
byte2 = 57;
byte3 = 58;
} // Ende if (!(PIND & (1 << PIND2)))
//
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum schreiben?
{
i2c_write(0x00); // Buffer Startadresse setzen
i2c_write(byte1); // Drei Bytes schreiben...
i2c_write(byte2);
i2c_write(byte3);
i2c_stop(); // Zugriff beenden
} //
else
{
/* Hier könnte eine Fehlermeldung ausgegeben werden... */
}
/*
waitms ( 200); // Warten vor Lesen ?? 30Nov2011, 2300
if(!(i2c_start(SLAVE_ADRESSE+I2C_WRITE))) //Slave bereit zum lesen?
{ //
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ToggleBit(PORTD, 5); // LED auf PC2 toggeln
// ###>>> 02 Dez 2011, 0045: Programm kommt bis hieher, dann bleibt es stehen
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
i2c_write(0x00); //Buffer Startadresse zum Auslesen
i2c_rep_start(SLAVE_ADRESSE+I2C_READ); //Lesen beginnen
//
byte1= i2c_readAck(); // Bytes lesen...
byte2= i2c_readAck();
byte3= i2c_readNak(); // letztes Byte lesen, darum kein ACK
i2c_stop(); // Zugriff beenden
}
*/
//else
//{
///* Hier könnte eine Fehlermeldung ausgegeben werden... */
//}


Ausgabebeispiel:
20704

Frage:
Wo steckt der Fehler??
Danke im Voraus für eure Hilfe.

PicNick
02.12.2011, 14:14
Wirklich steckenbleiben kann er ja eigentlich nur bei


i2c_write(0x00); // Da kann man hängen bleiben, wenn der Slave mit "clock-stretch" den master auf das ACK warten lässt
i2c_rep_start(SLAVE_ADRESSE+I2C_READ); // da bleibt man hängen, wenn der Slave den Bus nicht freigibt.

Ich weiss nicht, ob bei der Lib ein "Timeout" für diese zustände eingebaut ist. (offenbar nicht)
Baue zwischen den Befehlen erstmal irgendeine LED-Flunzlerei ein, damit du siehst, ob er bei "write" oder "rep_start" hängen bleibt.

EDIT: bei HW-TWI sollte so ein ewiger CLock-stretch eigentlich nicht möglich sein. d.h. der Verdacht richtete sich auf den Rep_Start.

oberallgeier
02.12.2011, 14:44
Erstmal danke, ich geh in ner Weile drüber (aktuell total lahme Hände/Arme, zuviel Kletterhalle).

PicNick
02.12.2011, 16:10
:mrgreen: Du weisst ja, wenn's hinten weh' tut, soll man vorn' aufhören :mrgreen:

oberallgeier
02.12.2011, 22:55
... ob ... ein "Timeout" ... eingebaut ist. (offenbar nicht) ...Offenbar nicht. Ist nicht zu sehen. Und ich habe meine LED/Leuchtfeuer-Kommunikation weiter ausgebaut:


... Baue ... irgendeine LED-Flunzlerei ein ... Verdacht ... auf den Rep_Start.Damit ist der "i2c_rep_start" als Missetäter überführt. Also drei i2c_readAck/Nak();// Bytes lesen haben das Koma verhindert. Jetzt schaue ich mal mit nem zusätzlichen USART nach was da gelesen wird (der gibt im Moment nur Schrott aus - seltsam.

Danke jedenfalls für den guten Tip, den rep_start zu verdächigen - das war ein Treffer.


"... wenn's hinten weh' tut, soll man ..." Ich klettere eigentlich immer Gesicht zur Wand . . . .

oberallgeier
03.12.2011, 12:18
So. Es stimmt. Drei "i2c_readAck/Nak();// Bytes lesen" statt des "i2c_rep_start" haben das Koma verhindert.

Zum Glück habe ich mir über UART vom Master die nun gelesenen Bytes ausgeben lassen. Baaahhhh - die waren (nur) die übermittelten Adressen(offsets) des zu lesenden Bytes. Also noch schnell ein "i2c_start(SLAVE_ADRESSE+I2C_READ)"-Commando, aber nicht das "i2c_rep_start(SLAVE_ADRESSE+I2C_READ)"! eingefügt - und schon steht wieder alles.

Aktuell gilt u.A. dies:
Modul "master", defines + includes vor "main" enthält u.a.
#define SLAVE_ADRESSE 0x70
Modul "i2cmasterl.h" (l=lokal) enthält u.a.
/** defines the data direction (reading from I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_READ 1
/** defines the data direction (writing to I2C device) in i2c_start(),i2c_rep_start() */
#define I2C_WRITE 0



Fazit: I2C-Slave-Schreiben geht, I2C-Slave-lesen geht nicht ... und bin so klug als wie zuvor.

oberallgeier
03.12.2011, 17:27
Sooo, nun gehts.

Danke Robert für den Hinweis auf den möglichen Fehler. Mittlerweile habe ich den Code für den Test des Master geringfügig ergänzt und das Auslesen, auch mit "i2c_rep_start" funktioniert jetzt klaglos und sicher. Ich dagegen bin nicht sicher, dass der Code "... Testprogramm für den Master..." aus dem RNWiki bei anderen Anwendungen funktioniert (steht ja extra dort "... getestet ..." - allerdings heißt es nicht, dass der auch läuft *ggg*) - wie geschildert gings bei mir nicht. Ich meine trotz meiner bescheidenen Kenntnisse, dass der Codeschnippsel gerade für Testzwecke verbesserungswürdig ist.

Trotzdem danke Robert.

Chypsylon
04.12.2011, 19:32
Ich hatte heute das gleiche Problem (schreiben geht -lesen nicht), und auch in anderen Threads wird berichtet das lesen nicht funktioniert. Ich verwende jetzt die Library von http://www.jtronics.de/avr-projekte/library-i2c/twi-slave-avr , die auch auf Anhieb funktioniert hat und vom Aufbau relativ gleich ist...

oberallgeier
04.12.2011, 22:45
Hi Chypsylon,


Ich hatte heute das gleiche Problem (schreiben geht -lesen nicht), und auch in anderen Threads wird berichtet das lesen nicht funktioniert ...Ja ja, die jtronics, nicht schlecht . . .
Die lib von PFleury ist sicherlich ok - und ob die andere Lib nen timeout hat, hatte ich noch nicht nachgesehen. Ich glaubs aber nicht. PFleurys lib läuft bei mir gut, ich habe jetzt nicht nur einen Beschleunigungsmesser gelesen und beschrieben (Einstellregister modifiziert) sondern auch meine mega328-mega328-Kopplung von Steckbrett/8Mhz-int zu Experimentierplatine/20MHz-Quarz problemlos in Funktion. Sowohl Schreiben als auch Lesen. Ausserdem hatte heute nachmittags mein Master-Testcode noch ne kurze, erfolgreiche Unterhaltung mit (m)einem EEPROM 24C16 gehabt. Einwandfrei. Nur das Beispiel im R N Wissen hat möglicherweise ne Macke - ich hatte ja erwähnt "... getestet ..." heißt noch lange nicht "erfolgreich getestet" - und bei Dir gehts ja auch prompt nicht.

oberallgeier
14.12.2011, 09:47
Um die Erledigung der Frage korrekt zu begründen, hier den aktuellen Stand.

Es werden vom Master (mega328/8MHz-intOsz) drei Bytes an den Slave (mega328bzw.168/20MHz-Quarz) gesendet. Je nachdem ob eine Taste gedrückt oder nicht gedrückt ist, werden zwei unterschiedliche Datensätze gesendet. Slaveadresse Schreiben x70, Slaveadresse Lesen x70+1. Schreibziel ist Position 2 bis 4 des Zielspeichers {von 1 bis 10 möglichen Plätzen}. Nach dem Senden des Datensatzes werden die drei Bytes zurückgelesen. Senden, Zurücklesen und evtl. Fehlermeldung werden im Terminal ausgegeben, siehe Beispiel der Ausgabe des Masters. Es ist eine Terminalverbindung des Masters (9600 Bd da ohne Quarz), des Slaves (128kBd) und des Sniffers (57600 Bd) eingesetzt.

......20804

Um die Unterhaltung der beiden Controller mitzuschneiden wurde ein Sniffer (klick) gebaut (Dank an PDannegger). (http://www.mikrocontroller.net/topic/102228#new) Tiny2313 mit 16MHz-Quarz. Beispiel für einen Mitschnitt:

I2C-Sniff 2313:
...
s70a01a36a37a38ap<\r
...
s70a01a36a37a38ap<\r>

Der Sniffer ist noch verbesserungswürdig, die Ausgaben sind gelegentlich gestört. Der obige Mitschnitt zeigt zweimal :
Sende an Adresse x70 / Speicherplatz 01 {von 10} / Datum x36 senden mit ACK / Datum x37 senden mit ACK / Datum x38 senden mit NAK / Stop