PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fragen zu TWI



Pascal
22.10.2004, 21:46
ich bin grad dabei eine Verbindung zwischen zwei ATMEGA8 per TWI herzustellen und irgendwie will das ganze nicht so recht gehn...

ich betreibe die µC mit dem internen 1MHz Quartz, meine Frage wäre nun: Kann es sein, dass man für TWI einen externen Quartz braucht?

Michael
22.10.2004, 21:52
Hallo Pascal,


Kann es sein, dass man für TWI einen externen Quartz braucht?

wozu sollte man den brauchen? Ein Clock für den(die) Prozessor(en) reicht. Vielleicht solltest du die Geschwindigkeit nicht zu hoch wählen.
Gruß, Michael

Pascal
22.10.2004, 22:24
ich hab mal gelesen, dass der interne Quarz nicht so genau sein soll, daher meine Vermutung, dass der für TWI evtl nicht ausreicht

die Geschwindigkeit hab ich meiner Meinung nach nicht zu hoch gewählt...für TWBR hab ich den Wert 12 und der Prescaler beträgt 1
bei internen 1MHz komm ich nach der Formel aus dem Datenblatt auf gerundet 8,9kHz

Michael
22.10.2004, 22:30
Hallo Pascal,
Da der TWI nur vom Master getaktet wird, ist die Geschwindigkeit nicht so wichtig. Und beide Teilnehmer haben eh dieselbe Taktquelle.
Gruß, Michael

Pascal
22.10.2004, 22:36
ganz unwichtig ist die Geschwindigkeit nicht, denn laut Datenblatt darf man sie nicht zu hoch wählen, da sonst der Slave nicht mehr "mitmacht"

mal ne dumme Frage: man verbindet doch die beiden SCL und SDA Pins miteinander und dann noch jeweils über 10kOhm Widerstand an 5V? oder muss man nen Wiederstand vor jeden einzelnen Pin schalten?!

Michael
22.10.2004, 22:39
Hallo Pascal,
die Geschwindigkeit ist bei deinem Fall völlig unwichtig, solange du bei beiden dasselbe einstellst. Sie haben doch beide die 1MHz-Taktquelle!


man verbindet doch die beiden SCL und SDA Pins miteinander und dann noch jeweils über 10kOhm Widerstand an 5V

so ists's richtig :)
Gruß, Michael

Pascal
22.10.2004, 22:42
solange du bei beiden dasselbe einstellst

muss ich die Geschwindigkeit nicht nur beim Master einstellen?!?

dann stimmt wenigstens einwas... :-)

Michael
22.10.2004, 22:48
Hallo Pascal,


muss ich die Geschwindigkeit nicht nur beim Master einstellen?!?

hmmm, ja, solange der Slave ein Slave bleibt, hast du natürlich recht.
Gruß, Michael

Pascal
22.10.2004, 23:00
ich hab den Code für den Master aus dem Datenblatt entnommen und der funktioniert auch soweit(nach der jeweiligen Aktion stimmt der Statusregisterwert zumindest mit dem jeweils erwarteten überein)

der Slave ist so programmiert, dass sobald der Interrupt des TWI ausgelöst wird, eine LED angeht

allerdings, obwohl der Master ja anscheinend geht, bleibt die LED aus, also es wird beim Slave kein Interrupt ausgelöst(ich habe die Interrupts auch global aktiviert...), TWCR hat beim Slave den Wert 01000101, woran könnte das liegen? (11000101 ging auch nicht)

ich werde mich aber demnächst auch vom PC entfernen, also mit einer nächsten Antwort meinerseits ist erst wieder morgen zu rechnen

Michael
22.10.2004, 23:09
Hallo Pascal,


ich hab den Code für den Master aus dem Datenblatt entnommen

hmmm, ich benutze für die ersten Versuche immer den Code aus der Hilfe-Abteilung der jeweiligen IDE.
Vielleicht solltest du etwas über deine Programmiersprache posten?
Gruß, Michael

Pascal
23.10.2004, 09:41
ich programmiere in WinAVR und hab da keine richtige Hardware-TWI-Unterstützung gefunden(ich kenn mich mit C aber nicht wirklich aus, evtl hab ichs auch nur übersehen)

deshalb hab ich den Code aus dem Datenblatt verwendet, der ja eigentlich funktionieren müsste...

Pascal
23.10.2004, 10:18
ich hatte bisher was falsch programmiert, ich hatte vergessen, die signal.h einzubinden...

den Master hab ich so programmiert, dass über einen externen Interrupt die Prozedur des TWI gestartet wird

nachdem ich die signal.h jetzt eingebunden hatte, sieht es so aus, dass der µC bei der Zeile "while(!(TWCR & (1<<TWINT)));" "hängenbleibt"

die Zeile ist auch aus dem Datenblatt(S.174), hat evtl jemand mit dem Code Erfahrung oder woran könnte das liegen?

Michael
23.10.2004, 14:17
Hallo Pascal,
tut mir wirklich leid, aber C tu ich mir nicht an.
Ich programmier lieber in Basic oder Pascal (;)).
Diese sind um einiges übersichtlicher. Und der Code ist auch nicht langsamer.
In Pascal habe ich z.B. ein Master/Slave System via Hardware-TWI erfolgreich zum laufen gebracht.
Gruß, Michael

Pascal
23.10.2004, 14:52
trotzdem vielen dank

kennt sich vielleicht einer der C-Programmierer unter euch mit dem TWI aus?
ich schildere nochmal kurz die momentane Lage:
der Aktivierungs-TWI-Code des Masters:


TWAR = 0xFD; //TWI-Addresse des Masters festlegen
TWSR &= 0b11111100; //Prescaler auf 1 setzen, Bit 1 und 0 auf 0
TWBR = 0xC; //Bitrate auf 12 setzen
sei(); //Interrupts global aktivieren


der Code, den der Master ausführt, um Daten zu senden:


TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //START senden
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
//wenn START gesendet, dann "1" an den PC senden
if ((TWSR & 0xF8) != 0x08) USART_transmit_string("1");
//Addresse des Slaves angeben
TWDR = 0xFE;
TWCR = (1<<TWINT) | (1<<TWEN); //Addresse senden
while (!(TWCR & (1<<TWINT))); //warten bis TWINT gesetzt
//wenn erfolgreich, 2 an PC senden
if ((TWSR & 0xF8) != 0x18) USART_transmit_string("2");
//0 ins Datenregister schreiben
TWDR = 0x0;
//Daten senden
TWCR = (1<<TWINT) | (1<<TWEN);
//warten bis TWINT gesetzt
while (!(TWCR & (1<<TWINT)));
//wenn erfolgreich, dann 3 an PC senden
if ((TWSR & 0xF8) != 0x28) USART_transmit_string("3");
//STOP senden
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);


Slave-Init-Code:


TWAR = 0xFE;
TWCR = 0b11000101;
TWBR = 0xC;
TWSR &= 0b11111100;
sei();

dann soll bei einem Interrupt, eine LED eingeschaltet werden

nun zu den Symptomen:
1 wird nie gesendet
(der Rest nur, wenn der Slave-µC nicht mit dem Master verbunden ist)
der Rest wird auch nie gesendet

die LED beim Slave geht nie an

wenn der SlaveµC angeschlossen ist, bleibt der Master in der dritten Schleife "hängen", wenn der Slave nicht angeschlossen ist, bleibt der Master in keiner der drei Schleifen hängen, allerdings werden bei beiden Varianten nur NACKs empfangen, der Slave antwortet also nie

weiß jemand vielleicht, wo der Fehler zu suchen ist?

Edit: siehe Symptome

Pascal
24.10.2004, 12:27
ich hab noch ein wenig herumexperimentiert...der Code vom Master funktioniert jetzt(wenn ich einen PCF8574(Porterweiterungsbaustein)ansteuere)

wenn ich dagegen den mit demselben Code(bis auf Addresse und Daten) einen anderen ATMEGA8 als Slave ansteuere, bleibt der Master immer in der dritten Schleife "hängen", der Fehler müsste also beim Slave zu suchen sein...

Pascal
24.10.2004, 14:29
jetzt funktioniert auch der Slave... :-)

28.12.2004, 15:13
jetzt funktioniert auch der Slave... :-)Woran lag es denn?
Kannst du vielleicht noch mal nen Quellcode für Master und Slave reinstellen?
Ich versuche nämlich auch 2 Mega16 über TWI zu verbinden.
Gute Beispiele oder Tutorials für TWI in C habe ich noch nicht wirklich gefunden.
Wer hätte da ein vielleicht ein paar Links?
MfG Steve

Pascal
29.12.2004, 19:55
das sei(); muss vor dem Code stehen, der den TWI beim Slave auf aktiv schaltet
ich glaub zumindest, dass es das war, ist schon eine Zeit lang her, ich komm heut auch nicht mehr an meinen PC, kann also nicht nachschauen und auch keinen Code posten...aber so in etwa war es das oben gesagte

so richtige Tutorials habe ich auch nicht für C
anfangs ist es sowieso das Beste, wenn man sich mit der Funktionsweise des I²C auseinandersetzt, dann schaut man ins Datenblatt des ATMEGA8/16 usw., da wird das auch nochmal erklärt, weiterhin, wie das auf den AVRs genau funtioniert und drittens gibt es da auch Code-Beispiele(in Assembler und C)

bhm
30.12.2004, 00:37
Trotzdem wäre es nett, wenn du den Code mal reinstellen würdest. Ich versuche auch gerade ein RN-Control mit RN-Mega8 zu verbinden, aber es klappt noch nicht so recht und die Fehlersuche gestalltet sich recht zeitraubend. Ich krieg das wahrscheinlcih irgendwann raus, aber es ist natürlich viel einfacher, wenn mir jemand helfen kann ;-).
ciao ... bernd

Pascal
30.12.2004, 16:51
ich hatte auch vor, den Code noch reinzustellen, in meinem vorherigen Post hat sich das vielleicht nicht so angehört, war aber so gemeint... O:)

beim Mastercode hat sich nichts wichtiges verändert(ich hab nur ein wenig debugging-Code hinzugefügt), der untenstehende Code müsste also funktionieren

hier der Slavecode(mit Kommentaren, ich hab das mal vor einiger Zeit für jemanden geschrieben und glaube, dass es ganz gut ist, wenn die dabeistehen)



//diese 6 Zeilen Code sind für das Initialisieren des TWI-Moduls zuständig, also kommt das Stück
//Code am besten irgendwo in die Mainmethode vor die Endlosschleife

//hier wird die Addresse des µC festgelegt(in den oberen 7 Bit, das LSB(niederwertigstes Bit) steht dafür, ob der µC auf einen general call //reagiert
TWAR = 0xFE;
//TWI Control Register, hier wird der TWI aktiviert, der Interrupt aktiviert und solche Sachen
TWCR = 0b01000101;
//TWI Bitrate Register, für die Frequenz des TWI wichtig
TWBR = 0xC;
//TWI Status Register, die 2 niederwertigsten sind für den Prescaler zur Taktberechnung, aus den
//anderen kann man auslesen, was genau passiert, wenn ein Interrupt ausgelöst wird, es gibt nämlich
//für den TWI nur einen
TWSR &= 0b11111100;
//hier werden Interrupts global aktiviert
sei();
//hier wird das TWI-Modul aktiv geschalten, ab hier man den µC per TWI ansteuern, den Befehl aber
//auf jeden Fall hinter das "sei();", da es sonst nicht geht
TWCR |= 0b10000000;


//Interruptroutine des TWI
SIGNAL (SIG_2WIRE_SERIAL){
//hier wird das TWSR darauf geprüft, ob 0x80 darin steht, dieser Wert bedeutet, dass Daten
//empfangen wurden, 0x60 würde zB bedeuten, dass er addressiert wurde und dies bestätigt hat
if((TWSR & 0b11111000) == 0x80){
//hier Code einfügen, der bearbeitet werden soll, die empfangenen Daten kann man aus
//TWDR auslesen
}
//wenn der Interrupt ausgelöst wird, wird der TWI des µC blockiert, damit man die Daten
//verarbeiten kann
//um ihn wieder zu aktivieren, muss man eben folgenden Befehl ausführen
TWCR |= 0b10000000;
}

bhm
30.12.2004, 18:56
besten dank von mir und allen, die es auch interessiert.
mal sehen. ob ich es heute noch ausprobieren kann.
ciao .... bernd

bhm
07.01.2005, 09:11
jupp, funktioniert!
Kleiner Schönheitsfehler: mit
> if ((TWSR & 0xF8) != 0x08) USART_transmit_string("1");
wird natürlich überprüft, dass ein Fehler aufgetreten ist, ncith dass es ok ist.

Allerdings hab ich bei den Basteleien wahrscheinlich einen Mega8 geschrotet. In dem Zusammenhang ist mir was aufegfallen: Ich hab ein RN-Control (Master) und ein RN-Mega8 (Slave) mit I2c verbunden. Beide haben eine eigene Stromversorgung (gemeinsame Masse). Das RN-Control ist mangels Schalter permanent an.
Wenn das I2C-Kabel nicht da ist, oder der Slave kein Programm hat, läuft das Masterprogramm durch mit Fehlermeldungen kein Slave-Adress-Ack und kein Slave-Data-Ack. Soweit, so erwartet.
Wenn der Mega8 läuft und das Programm ok ist, läuft das Masterprogramm ohne Fehler durch und der Mega8 erhält die Daten (das Datum). Soweit, so gut.
Wenn jetzt aber der Mega8 aus ist (kein Strom) und der Master startet, bleibt das Masterprogramm hängen. Ich vermute bei der Abfrage, ob TWI-START gesendet wurde, muss ich aber noch näher einkreisen.

Das bringt mich zu der Frage wie eigentlich das Verhalten des I2C-Busses definiert ist, wenn ein Gerät stromlos ist. Oder ob das, wie ich vermute, verboten ist.
Und was machen eigentlich die Ports wenn ein Mega stromlos ist? Low?, High geht nicht, Tri-state?, undefiniert? Falls niederohmig low, kann der Master evtl. keinen Clock erzeugen, weil die Leitung low bleibt. Würde dann die I2C-Logik hängenbleiben? Und kann das den Master oder Slave beschädigen? (was erklären würde warum ich einen M8 gekillt habe)

ciao ... Bernd

Pascal
07.01.2005, 09:36
wieso wird da überprüft, ob ein Fehler aufgetreten ist? 0x08 im Statusregister steht doch einfach dafür, dass START übertragen wurde, oder täusch ich mich da?

ich tippe darauf, dass die hochohmig sind, wenn der ATMEGA keinen Strom hat, wissen tu ichs aber nicht

zu der Frage, wie der I²C-Bus beeinflusst wird, wenn ein Gerät keinen Strom hat... ich denke, sofern meine Annahme von eben stimmt, dass das doch eigentlich nichts ausmachen dürfte?

inwiefern ist der M8 eigentlich defekt, macht er gar nichts mehr, oder nur wenig? wieso sollte er kaputt gehen, wenn er keinen Strom hat und an den TWI-Pins die Pegel wechseln?

zu der Frage sollte sich aber noch jemand mit mehr Erfahrung äußern, denn viel Ahnung davon hab ich auch wieder nicht...

bhm
07.01.2005, 11:48
wieso wird da überprüft, ob ein Fehler aufgetreten ist? 0x08 im Statusregister steht doch einfach dafür, dass START übertragen wurde, oder täusch ich mich da?
Das stimmt schon, aber mit "!=" wird halt geprüft ob 0x08 _nicht_ im Statusregister steht, also _kein_ START übertragen wurde.


inwiefern ist der M8 eigentlich defekt, macht er gar nichts mehr, oder nur wenig?
Er reagiert nicht mehr auf Programmieranfragen ("missing or wrong device" in Pony). Ein Ersatzprozessor ging aber. Ich probiere es heute abend nochmal aus, vielleicht hat er es sich ja überlegt ;-)


wieso sollte er kaputt gehen, wenn er keinen Strom hat und an den TWI-Pins die Pegel wechseln?
Tja, das weis ich halt nicht. Ich fand es nur komisch, dass a) der Prozzi nicht mehr ging und b) der Master hängt, wenn der Slave keinen Strom
hat.
Anyway, der Code hat keine Schuld ;-)

ciao ... bernd

Pascal
07.01.2005, 12:20
klingt logisch... O:)
mir ist auch gerade aufgefallen, dass das ein Unterschied zwischen dem geposteten Mastercode und meinem verwendeten ist; hatte ich nicht genau geschaut
man muss halt die Debuginfos nur richtig interpretieren... O:) (aber ich hab das damals falsch kommentiert)
die If-Abfrage war eigentlich dazu gedacht, irgendeine errorhandling-Routine aufzurufen...hab die dann aber zum debuggen verwendet

hast du vielleicht was an den Fusebits geändert? aber gehen sollte er dann eigentlich trotzdem noch...

bhm
07.01.2005, 15:51
hast du vielleicht was an den Fusebits geändert? aber gehen sollte er dann eigentlich trotzdem noch...
naja, ob er noch geht, weis ich nicht, weil das Programm, das ich gerade drin hatte fehlerhaft war und nix tut ...

ciao .. bernd

Pascal
07.01.2005, 16:33
ist natürlich dumm...

aber zu dem Problem, dass der Master hängt, wenn der Slave keinen Strom hat...ich hab grad mal wieder ein wenig experimentiert und wenn ich dem Master die falsche Slaveaddresse(also eine nicht vorhandene) gebe, hängt der Master
das war bei dir dann genauso
ich probier mal, den Code soweit zu überarbeiten, dass der nicht mehr hängen bleibt

Pascal
07.01.2005, 16:34
ich hab jetzt den Code ein wenig erweitert...jetzt bleibt der Master nicht mehr hängen, wenn er eine nicht vorhandene Addresse versucht anzusprechen:

es muss noch eine unsigned char Variable namens errcounter deklariert werden



TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))) {
errcounter++;
if(errcounter==10){errcounter=0; break;}
}
TWDR = addr; //addr = Zieladdresse
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))) {
errcounter++;
if(errcounter==10){errcounter=0; break;}
}

TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))) {
errcounter++;
if(errcounter==10){errcounter=0; break;}

TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);



die If-Abfragen kann man sich bei Bedarf ja selbst reinschreiben

bhm
08.01.2005, 01:12
jupp, so geht es. Die TWI Logik selber hat wohl kein Timeout, oder?
Ich hab übrigens mal im Datenblatt nachgesehen. Für TWI ist vorgeschrieben, dass alle devices powered sind. Es sollte aber trotzdem eigentlich nix passieren, weil die Leitungen über die pull-up Widerstände hochgelegt werden und die Ports die Leitungen entweder auf 0 ziehen, oder tri-state sind, also zu keinem Zeitpunkt selber Strom abgeben. ...
Ist mir ein Rätsel...
ciao .. bernd

bhm
08.01.2005, 01:28
Inzwishen weis ich warum mein alter Code nicht ging.
Ich hab die Slaveaddresse definiert:
uint8_t SlvAdd = 0xFD;
und später das WriteBit dazugeodert:
TWDR = SlvAdd | _BV(TW_WRITE);
Aus mir noch immer unbekannten Gründen kommt da was Falsches raus, es geht mit:
TWDR = SlvAdd + _BV(TW_WRITE);
Ist eigentlich identisch ... oder ?
ciao .. bernd

Pascal
08.01.2005, 08:38
was meinst du mit TWI Logik, den Code oder das Hardware TWI Modul?
ich denke mal, du meinst das Letztere, das braucht kein Timeout, das darauf Auswirkungen hat, die Schleife, die hängen bleibt, läuft doch in Software, hier muss man, wie bereits geschehen, ein Timeout einbauen

wenn die Pins die Leitungen auf Low ziehen, geht doch nichts mehr, weil standartmäßig sind die Leitungen High und werden bei Bedarf auf Low gezogen, wenn jetzt aber eine Leitung dauerhaft Low ist, dürfte doch der ganze Bus nichts mehr tun?!
also müssten die doch eigentlich tristate sein (auf jeden Fall dürfen sie die Leitungen nicht beeinflussen)

bhm
08.01.2005, 15:43
was meinst du mit TWI Logik, den Code oder das Hardware TWI Modul?
ich denke mal, du meinst das Letztere, das braucht kein Timeout, das darauf Auswirkungen hat, die Schleife, die hängen bleibt, läuft doch in Software, hier muss man, wie bereits geschehen, ein Timeout einbauen

korrekt!


wenn die Pins die Leitungen auf Low ziehen, geht doch nichts mehr, weil standartmäßig sind die Leitungen High und werden bei Bedarf auf Low gezogen, wenn jetzt aber eine Leitung dauerhaft Low ist, dürfte doch der ganze Bus nichts mehr tun?!
genau, und genau das (also nix mehr) passiert bei mir, wenn der Slave keinen Strom hat.
Aber kaputtgehen sollte da eigentlich nix. Vielleicht war es auch nur eine unglückliche statische Spannungsspitze beim Umstecken der ISP -Stecker.
ciao .. bernd

partyboarder
07.02.2005, 08:37
moinsens bhm

auf seite 171 absatz 1 letzer satz im atmega16 manual steht die antwort auf deine Frage (naja zumindest für den avr):

"Note that all AVR devices connected to the TWI bus must be powered in order to allow any bus operation."

gruß
partyboarder

bhm
07.02.2005, 09:29
jupp, hab ich auch inzwischen gefunden. Erstaunlich was alles in diesem Datenblatt steht. ;-)
ciao .. bernd