Hallo, Leute!
Also, ich habe mich entschieden, selber eine Funktion zu schreiben, mit
dem ich als I²C-Slave arbeiten kann.
Die erste Resultaten sind schon zu sehen! Ich kann Bytes empfangen und,
als Debug, LEDs ein- und ausschalten.
Nun brauche ich unbedingt, daß meine Funktion mit "Register" klar kommt.
Laut Spezifikationen sollte folgendes passieren:
1) Master schickt START
2) Master schickt die Adresse
3) Master schickt die Registernummer
4) Master schickt nochmal ein START
5) Master schickt die Daten für diesen Register
Nun sehe ich, in twi.h die Konstanten TW_START und TW_REP_START.
Ich dachte, vom Slave, wenn ich eine von den bekomme, bin ich an dem
Punkt 4.
Ich habe folgendes geschrieben:
1
ISR(TWI_vect)
2
{
3
switch(TW_STATUS)
4
{
5
...
6
caseTW_START:
7
caseTW_REP_START:
8
turnOnLED(LED2);
9
registerAddress=bufferData;
10
bufferData=NODATA;
11
nReceivedData=0;
12
TWCR_ACK;
13
break;
14
...
15
}
16
}
Leider wird das zweite LED NIE eingeschaltet, also ich komme nicht in
diesem "case".
Was ist dann der Fehler? Ich verstehe überhaupt nicht, warum es nicht
gehen soll...
Danke für eure Hilfe!
Luca Bertoncello
Hi,
ich schätze mal das der µC den Rep_start gar nicht als solchen erkennt,
bzw das man den nicht so benutzt wie du es willst.
Schau dir mal die Seite an
http://www.i2c-bus.org/repeated-start-condition/
Wenn ich das richtig verstehe stimmt deine Annahme vom Ablauf nicht:
1) Master schickt START
2) Master schickt die Adresse // + write
3) Master schickt die Registernummer
/*Punkt 4 ist unnötig da der Master ja sowieso im writemode ist
4) Master schickt nochmal ein START
*/
5) Master schickt die Daten für diesen Register
Schau Dir mal die Datenblätter von I2C-Chips an, ein repeated_start
braucht man nur, wenn der Master random-liest.
Nach dem ersten Start übergibt der Master die Slave-Adresse (mit LSB =
0, d.h. Schreiben), dann kommt die Register-Adresse, dann kommt der
repeated_start, dann nochmals die Slave-Adresse (mit LSB = 1, d.h.
Lesen), dann werden die Daten vom Slave zum Master geschoben.
stephan_ schrieb:> Schau Dir mal die Datenblätter von I2C-Chips an, ein repeated_start> braucht man nur, wenn der Master random-liest.>> Nach dem ersten Start übergibt der Master die Slave-Adresse (mit LSB => 0, d.h. Schreiben), dann kommt die Register-Adresse, dann kommt der> repeated_start, dann nochmals die Slave-Adresse (mit LSB = 1, d.h.> Lesen), dann werden die Daten vom Slave zum Master geschoben.
Ja, genau! Ich hatte vorher eigentlich etwas falsch beschrieben, ist
aber genau was ich machen will.
Von der Masterseite funktioniert alles prima: ich habe schon andere zwei
Geräte die so angesprochen werden.
Nun muß ich es die Slaveseite programmieren. Und ich wundere mich, daß
die REP_START nicht ankommt...
Grüße
Luca Bertoncello
Atmel Datenblatt:
0x08: A START condition has been transmitted
0x10: A repeated START condition has been transmitted
Na, geht Dir ein Seifensieder auf?
Transmit bedeutet als Master.
Als Slave kann man das nicht unterscheiden.
Peter
Peter Dannegger schrieb:> Transmit bedeutet als Master.> Als Slave kann man das nicht unterscheiden.
Deine Erklärung ist sehr unglücklich. Natürlich kann auch der Slave
transmitten.
Die 0x08 und 0x10 bekommt man als Master zurück, wenn man Start und
Repeated Start abgesetzt hat. Der Slave hat in solchen Fällen die 0x60
oder die 0xa0 im TWSR stehen, wenn der Master schreibend auf ihn
zugreifen will. Siehe "Slave Receiver Mode" im ATmega-Datenblatt.
Peter Dannegger schrieb:> Nein, der Slave kann kein START oder repeat START senden!
Das hat auch keiner behauptet. ;)
Du hast gesagt: "Transmit bedeutet als Master"
Das ist schon an sich recht unverständlich und eigentlich auch nicht
korrekt, denn sowohl Slave als auch Master können natürlich Daten
versenden. Allerdings kann nur der Master einen Transfer mittels Start
oder Repeated Start initiieren.
Der OP sollte sich in den ATmega-Datenblättern die Tabellen zu den
Rückgabewerten der jeweiligen Modi
Master Transmit
Master Receive
Slave Transmit und
Slave Receive
ansehen. Abhängig von der Rolle des Kommunikationspartners werden auch
die unterschiedlichen Werte im TWSR abgelegt!
Gastino G. schrieb:> Der OP sollte sich in den ATmega-Datenblättern die Tabellen zu den> Rückgabewerten der jeweiligen Modi>> Master Transmit> Master Receive> Slave Transmit und> Slave Receive>> ansehen. Abhängig von der Rolle des Kommunikationspartners werden auch> die unterschiedlichen Werte im TWSR abgelegt!
Hallo, allerseits!
Also, ich habe mir die ATMega-Datenblatt (diesmal komplett!)
heruntergeladen.
Vorher hatte ich (so habe ich gerade festgestellt!) nur eine kurze
Version, wo diese Informationen nicht geschrieben waren.
Also, ich sehe (Seite 186), die Beschreibung der ATMega8 beim "Slave
Receiver Mode".
0xA0 bekomme ich wenn ein STOP oder REP_START geschick wird.
Gut, nun muß ich unterscheiden, wann ich ein STOP bekommen habe, und
wann ein REP_START.
Ich nehme an, ich kann es machen, beim gucken die Bits STA, STO, TWINT
und TWEA, oder?
Nun verstehe ich aber nicht ganz die Beschriebung, die für dieses Status
geschrieben ist...
Wenn ich sehe, was bei dem Status "Master Receiver Mode" gemacht wird,
wenn ein REP_START gesendet wird, sehe ich STA und TWINT = 1 und STO =
0. Kein Wert für TWEA.
Beim "Slave Receiver Mode" habe ich zwei Möglichkeiten, mit STA = TWINT
= 1 und STO = 0.
Kann jemand mir genau erklären, was ich jetzt bekommen soll?
Besten Dank
Luca Bertoncello
Luca Bertoncello schrieb:> Also, ich sehe (Seite 186), die Beschreibung der ATMega8 beim "Slave> Receiver Mode".> 0xA0 bekomme ich wenn ein STOP oder REP_START geschick wird.> Gut, nun muß ich unterscheiden, wann ich ein STOP bekommen habe, und> wann ein REP_START.
Nein, Du musst da erst mal gar nichts tun. Die Kommunikation ist damit
für Dich als Slave zunächst beendet. Erst, wenn Du wieder als Slave
adressiert wirst (0x60, 0x68 oder 0x70 als Status-Code in TWSR), geht es
weiter bzw. wieder los.
> Ich nehme an, ich kann es machen, beim gucken die Bits STA, STO, TWINT> und TWEA, oder?
Nein, STA, STO und TWEA beschreibst Du. Schauen kannst Du nur in den
Status-Code des TWSR und das TWINT (wenn Du darauf pollst).
Den Status-Code erhältst Du mittels:
1
status=TWSR&0xF8;
> Nun verstehe ich aber nicht ganz die Beschriebung, die für dieses Status> geschrieben ist...
Schau mal in die Tabelle für die Codes. Die ist anfangs etwas
verwirrend, wird aber klar, wenn man sich vergegenwärtigt, dass Du dort
immer nur festlegst, was der ATmega bei dem folgenden
Kommunikationsschritt machen wird.
Also TWINT wird gesetzt, Du schaust in TWSR und entscheidest anhand des
darin abgelegten Wertes (nur Status-Code!) und der Tabelle, was Du als
nächstes machst.
Beispiel:
TWINT wird 1, in TWSR steht 0x60 als Status-Code. Ein Master hat Dich
für eine Schreiboperation adressiert. Ein Blick in die Tabellenspalten
zeigt, dass Du aus dem Datenregister (TWDR) nichts lesen musst/kannst.
Nächste Spalte: Du kannst nur TWINT setzen, dann geht die Kommunikation
weiter, Dein ATmega sendet aber nach dem nächsten Schritt (er wird ein
Byte empfangen) ein NOACK. Setzt Du auch TWEA, wird er danach ein ACK
senden.
Im nächsten Schritt wird wieder TWINT 1, wenn Dir der Master ein Byte
geschickt hat und im TWSR steht - abhängig von Deiner vorherigen Wahl
(TWEA oder nicht) - ein 0x80 oder ein 0x80 als Status-Code. Nun kannst
Du aus dem Datenregister das empfangene Byte lesen. Wie Du TWINT, TWEA
usw. setzen musst, steht dann wieder in der entsprechenden
Tabellenspalte - je nachdem, wie es weitergehen soll...
> Wenn ich sehe, was bei dem Status "Master Receiver Mode" gemacht wird,> wenn ein REP_START gesendet wird, sehe ich STA und TWINT = 1 und STO => 0. Kein Wert für TWEA.
Richtig. Wenn der Master eine Start Condition sendet, dann ist TWEA 1
bzw. nicht zu setzen. TWEA ist im Master-Mode vor dem Empfang des
letzten Bytes auf 0 zu setzen, damit der Master nach dessen Empfang den
Ende des Transfers mit NOACK signalisiert. Ansonsten auf 1, wenn der
Master nach dem nächsten Byte noch weitere empfangen will und das mit
ACK signalisieren soll.
> Beim "Slave Receiver Mode" habe ich zwei Möglichkeiten, mit STA = TWINT> = 1 und STO = 0.
Wenn Du als Slave STA=1 setzt, wird der Controller warten, bis der Bus
frei ist und danach als Master eine Start-Condition senden.
Gastino G. schrieb:
(omissis)
Danke für die Erklärung
>> Beim "Slave Receiver Mode" habe ich zwei Möglichkeiten, mit STA = TWINT>> = 1 und STO = 0.>> Wenn Du als Slave STA=1 setzt, wird der Controller warten, bis der Bus> frei ist und danach als Master eine Start-Condition senden.
Ich wollte auch sie nicht setzten, sondern einfach lesen...
Ich habe mir noch die Tabelle angeschaut.
Bin ich richtig wenn ich sage, daß wenn ich ein 0xA0 (TW_SR_STOP, die,
laut twi.h, zu erwarten bei STOP und REPEATED START ist) prüfen soll,
was TWCR für Bits gesetzt hat.
Ist TWSTO dann ist gerade ein STOP empfangen und ist die Kommunikation
erstmal beendet.
Ist TWSTA dann ist gerade ein REPEATED START empfangen und ich muß was
anderes machen.
Richtig?
Danke
Luca Bertoncello
Hallo
> Bin ich richtig wenn ich sage, daß wenn ich ein 0xA0 (TW_SR_STOP, die,> laut twi.h, zu erwarten bei STOP und REPEATED START ist) prüfen soll,> was TWCR für Bits gesetzt hat.
nein du kannst die Bits nur selber setzen (siehe Tabelle "to TWCR"!!)
> Ist TWSTO dann ist gerade ein STOP empfangen und ist die Kommunikation> erstmal beendet.> Ist TWSTA dann ist gerade ein REPEATED START empfangen und ich muß was> anderes machen.
nein siehe oben nur TWSR gibt dir Informationen über aktuelle Zustände
wenn du 0xA0 hast, dann setzte TWINT & TWEA, womit sich dein Slave im
unadressierten Modus befindet und die Erkennung der Slaveadresse
aktiviert ist.
Du scheinst dir noch nicht ganz im klaren zu sein für was ein REPEATED
START da ist. Man könnte auch STOP senden und anschließend wieder START
womit aber das Problem entsteht, das der Bus zwischenzeitlich wieder
frei wird und ein anderer Teilnehmer den Bus belegen könnte - das wird
durch REPEATED START vermieden.
Als Slave interessiert dich das nicht, weil nach der REPEATED START
wieder die Adresse vom Master gesendet wird und sich dein TWSR wieder
mit 0x60 meldet.
Sascha
Sascha Weber schrieb:> Du scheinst dir noch nicht ganz im klaren zu sein für was ein REPEATED
bestimmt...
> START da ist. Man könnte auch STOP senden und anschließend wieder START> womit aber das Problem entsteht, das der Bus zwischenzeitlich wieder> frei wird und ein anderer Teilnehmer den Bus belegen könnte - das wird> durch REPEATED START vermieden.> Als Slave interessiert dich das nicht, weil nach der REPEATED START> wieder die Adresse vom Master gesendet wird und sich dein TWSR wieder> mit 0x60 meldet.
Nein, mich interessiert SEHR zu unterscheiden, ob ich ein STOP oder ein
REPEATED START kriege...
Folgendes Beispiel:
Der Master will in dem Register 3 die Werte 1, 2 und 3 schreiben. Er
schickt folgendes:
START
Adresse der Slave
3 (die Registernummer)
REP_START
Adresse der Slave
1
2
3
STOP
Wenn er nur ein 3 schicken würde (kein Register) wird folgendes
passieren:
START
Adresse der Slave
3
STOP
Also, schon was anderes...
Dann muß ich als Slave wissen, daß der 3 bei dem ersten Beispiel eine
Registernummer ist, und nicht ein Wert (zweites Beispiel).
Deswegen MUSS ich unbedingt wissen, wann ich ein REP_START kriegen und
wann nicht.
Ich habe inzwischen verstanden, daß ich TWCR nur schreiben kann, und bei
Slave dort nicht zu lesen habe, um dieser REP_START zu fangen.
Laut util/twi.h wird also TW_SR_STOP bei TW_STATUS gesetzt wenn ein STOP
oder ein REP_START empfangen wird.
Und bestimmt DORT muß ich diese zwei Konditionen unterscheiden.
Nun verstehe ich überhaupt nicht wie. Aber es muß machbar sein, da ich
schon mindestens ein Gerät habe (Kompass CMP03) der so arbeitet...
Ich freue mich über eine Erklärung.
Grüße
Luca Bertoncello
> Folgendes Beispiel:> Der Master will in dem Register 3 die Werte 1, 2 und 3 schreiben.
ein "Register" kann nicht 3 Werte haben, dann schreibst du Reg3=1,
Reg4=2 u. Reg5=3
> Er schickt folgendes:>> START> Adresse der Slave> 3 (die Registernummer)> REP_START> Adresse der Slave> 1> 2> 3> STOP
also wenn du nur schreibst dann brauchts kein REP START
Schau dir doch mal EEProm's an wie das dort organisiert ist
START
SLA
Speicherardesse (bei dir Register)
Wert1 -> kommt auf die adressierte Adresse, welche anschließend erhöht
wird
Wert2 -> nächste Adresse
Wert3 -> usw ...
STOP
REP START brauchst du nur um von Schreiben (Adresse/Register) auf Lesen
der Daten umzuschalten!
Sascha
Sascha Weber schrieb:> REP START brauchst du nur um von Schreiben (Adresse/Register) auf Lesen> der Daten umzuschalten!
Ich kann wirklich nicht zustimmen, denn ich mache mit dem Kompass genau
das: wenn ich die Kalibrierung starten will, muß ich in dem Register 15
den Wert 0xFF schreiben, dann nach einer kurzen Pause noch ein 0x00.
Und, um das zu machen, schicke ich:
START
SLA
15
START
255
STOP
(Pause)
START
SLA
15
START
0
STOP
Also, wie du siehst, kann ein REP_START auch beim schreiben passieren.
Danke
Luca Bertoncello
> START> SLA> 15> START
SLA !! oder ? sonst ist die 255 nutzlos
> 255> STOP> (Pause)> START> SLA> 15> START
wieder keine SLA !!
> 0> STOP>> Also, wie du siehst, kann ein REP_START auch beim schreiben passieren.
Das will ich sehen ! poste mal einen Link auf ein Datenblatt !
?? und warum willst du dein Protokoll nun unbedingt an dem dieses
Kompasssensors ausrichten ??
Sascha
Luca Bertoncello schrieb:> Also, schon was anderes...> Dann muß ich als Slave wissen, daß der 3 bei dem ersten Beispiel eine> Registernummer ist, und nicht ein Wert (zweites Beispiel).
Ich bin nicht sicher, ob ich jetzt richtig verstanden haben, was Du
machen willst, aber ich versuche mal eine Erklärung:
Also angenommen, Du willst beginnend ab Register-Adresse 3 im Slave die
Werte 10, 11, und 12 schreiben. Dann sind die Protokolle üblicherweise
so organisiert, dass bei einem Schreibvorgang auf den Slave immer der
erste Wert nach der Slave-Adresse die Register-Adresse im Slave ist.
Also:
START
SLAW
3 //Register-Adresse
10 //Wert für Adresse 3
11 //Wert für Adresse 4
12 //Wert für Adresse 5
STOP
Ein Repeated Start brauchst Du nur, wenn mehrere Master auf denselben
Slave zugreifen können und Du eine Register-Adresse setzen und ab da
Daten auslesen willst:
START
SLAW
3 //Register-Adresse für Lesen
REPEATED START
SLAR //Lesezugriff auf Slave
10 //Wert an Adresse 3
11 //Wert an Adresse 4
12 //Wert an Adresse 5
STOP
Repeated Start unterbindet hier, dass ein anderer Master nach dem Setzen
der Adresse dazwischenfunkt und die Adresse wieder verändert bevor Du
den Slave ausliest.
Luca Bertoncello schrieb:> Bin ich richtig wenn ich sage, daß wenn ich ein 0xA0 (TW_SR_STOP, die,> laut twi.h, zu erwarten bei STOP und REPEATED START ist) prüfen soll,> was TWCR für Bits gesetzt hat.> Ist TWSTO dann ist gerade ein STOP empfangen und ist die Kommunikation> erstmal beendet.> Ist TWSTA dann ist gerade ein REPEATED START empfangen und ich muß was> anderes machen.>> Richtig?
Nein, Du kannst das so nicht erkennen, denn TWSTO und TWSTA sind nicht
dafür da, um das zu unterscheiden, sondern diese Bits sind nur zum
Schreiben da, wenn Du als Master eine Start- oder Stop-Condition senden
willst (oder als Slave Dein TWI wieder zurücksetzen willst).
Siehe oben meine beiden Beispiele. Du kannst und musst als Slave nicht
unterscheiden, ob das ein Stop oder ein Repeated Start ist. Sobald ein
Master schreibend zugreift, ist der erste Wert immer die
Registeradresse, die der Slave sich natürlich merken muss und auch bei
Empfang oder Versenden von Datenbytes automatisch jeweils um 1 erhöhen
muss!
Luca Bertoncello schrieb:> Ich kann wirklich nicht zustimmen, denn ich mache mit dem Kompass genau> das: wenn ich die Kalibrierung starten will, muß ich in dem Register 15> den Wert 0xFF schreiben, dann nach einer kurzen Pause noch ein 0x00.> Und, um das zu machen, schicke ich:>> START> SLA> 15> START> 255> STOP> (Pause)> START> SLA> 15> START> 0> STOP>> Also, wie du siehst, kann ein REP_START auch beim schreiben passieren.
Das geht eigentlich dann so:
START
SLAW //Slave-Adresse+Schreib-Flag
15
255
STOP
...Pause...
START
SLAW //Slave-Adresse+Schreib-Flag
15
0
STOP
Wenn Du das unbedingt mit Repeated Start machen willst, sieht das Ganze
so aus:
START
SLAW //Slave-Adresse+Schreib-Flag
15
255
...Pause... (TWINT-Flag nicht zurücksetzen -> Bus bleibt damit belegt)
REPEATED START
SLAW //Slave-Adresse+Schreib-Flag
15
0
STOP
Wie Du siehst, muss Dein Slave den Unterschied zwischen STOP und
REPEATED START nicht erkennen, denn nach START oder REPEATED START
erfolgt immer wieder dieselbe Datenfolge:
Register-Adresse
Daten
...
> Wie Du siehst, muss Dein Slave den Unterschied zwischen STOP und> REPEATED START nicht erkennen, denn nach START oder REPEATED START> erfolgt immer wieder dieselbe Datenfolge:
OK, Leute!
Ich habe den ganzen Nachmittag experimentiert und das einziges, was ich
geschafft habe, ist einen RIESENGROSSEN Kopfschmerz zu kriegen...
Was ich versucht habe ist folgendes:
1) Daten zu schicken (1 bis X)
2) Daten zu lesen (1 bis X)
3) Daten von einem Register zu lesen (1 bis X)
Das Problem ist, daß ich einfach keine Möglichkeit habe, wenn ich ein
TW_SR_STOP bekomme, zu wissen, ob der Byte, das ich gerade gelesen habe
(wenn es nur EIN Byte ist!) die Adresse der Register ist, oder ein Wert
zu speichern.
Wenn ich später ein TW_ST_SLA_ACK bekomme, dann ist alles klar! Ich habe
die Registernummer bekommen und ich kann den Rest machen.
Aber wenn ich nichts anderes bekomme, ich muß in der Lage sein, dieses
einzelne Byte in einem Array zu schreiben und dem Hauptprogramm Bescheid
zu sagen (was in der Art: gucke mal! Hier sind Daten für dich).
Aber das schaffe ich einfach nicht. Kann jemand mir ein guter Tipp
geben?
Besten Dank!
Luca Bertoncello
Luca Bertoncello schrieb:> Das Problem ist, daß ich einfach keine Möglichkeit habe, wenn ich ein> TW_SR_STOP bekomme, zu wissen, ob der Byte, das ich gerade gelesen habe> (wenn es nur EIN Byte ist!) die Adresse der Register ist, oder ein Wert> zu speichern.
Wenn Du ein TW_SR_STOP (0xA0) bekommst, bist Du im Slave Receiver Mode.
Der Master hat Dir Daten geschickt und gerade die Übertragung beendet.
Wenn Du da nur ein Byte bekommen hast, ist es immer eine Adresse.
Gastino G. schrieb:> Luca Bertoncello schrieb:>> Das Problem ist, daß ich einfach keine Möglichkeit habe, wenn ich ein>> TW_SR_STOP bekomme, zu wissen, ob der Byte, das ich gerade gelesen habe>> (wenn es nur EIN Byte ist!) die Adresse der Register ist, oder ein Wert>> zu speichern.>> Wenn Du ein TW_SR_STOP (0xA0) bekommst, bist Du im Slave Receiver Mode.> Der Master hat Dir Daten geschickt und gerade die Übertragung beendet.> Wenn Du da nur ein Byte bekommen hast, ist es immer eine Adresse.
Das kann nicht sein!
Ich habe Haufen Geräte hier mit dem RnbFra, die nur ein Byte kriegen
müssen.
Und das ist selbstverständlich keine Adresse, sondern einfach ein Wert!
Grüße
Luca Bertoncello
Luca Bertoncello schrieb:> Das Problem ist, daß ich einfach keine Möglichkeit habe, wenn ich ein> TW_SR_STOP bekomme, zu wissen, ob der Byte, das ich gerade gelesen habe> (wenn es nur EIN Byte ist!) die Adresse der Register ist, oder ein Wert> zu speichern.
Vielleicht postest Du endlich mal nen Link auf das Gerät, mit dem Du
kommunizieren möchtest.
Erst dann kann man nachverfolgen, was da schief läuft, bzw. wie es
richtig gehen sollte.
Software kann nicht hellsehen, d.h. es muß im Protokoll immer eine
eindeutige Regel geben, wie ein Byte zu interpretieren ist.
Entwickelt man beide Teilnehmer selber, dann sollte man sich streng an
die original Philips/NXP Spezifikation halten. Alles was dort
spezifiziert ist, kann man nutzen.
Und alles, was dort nicht explizit erlaubt ist, ist verboten, wenn man
sich keine Probleme einhandeln will.
Peter
Luca Bertoncello schrieb:> Das kann nicht sein!> Ich habe Haufen Geräte hier mit dem RnbFra, die nur ein Byte kriegen> müssen.> Und das ist selbstverständlich keine Adresse, sondern einfach ein Wert!
und woher weiß das ??Gerät?? was es mit dem EINEN Byte machen soll? Oder
hat das nur einen Wert den man verändern kann? Ansonsten müsste das Byte
als Wert der nächsten Registeradresse zugeordnet werden - also in etwa
so.
START,SLAW,ADDR,WERT(für ADDR),WERT(für ADDR+1),STOP
START,SLAW,WERT(für ADDR+2),STOP
-----
schreibe die empfangenen Werte in ein Array und merke dir wieviele Bytes
empfangen wurden.
wenn jetzt STOP erkannt wird schau in dein Array
wenn Anzahl>1 dann
Registeradresse=Array[0]
Schleife x = 1 .. Anzahl-1
Register[Registeradresse++]=Array[x]
sonst (1Byte)
Register[Registeradresse++]=Array[0]
Sascha
Luca Bertoncello schrieb:> Das kann nicht sein!> Ich habe Haufen Geräte hier mit dem RnbFra, die nur ein Byte kriegen> müssen.> Und das ist selbstverständlich keine Adresse, sondern einfach ein Wert!
Also: In den Datenblättern muss drinstehen, wie die Bytes zu
interpretieren sind. Wenn mehrere Adressen vorhanden sind, ist in der
Regel immer das erste Byte die Adresse (beim Schreiben auf den Slave).
Ansonsten schließe ich mich Peter Danneger an: Du solltest uns verraten,
um welchen Slave es denn konkret geht, damit man mal im Datenblatt
nachsehen kann.
Peter Dannegger schrieb:> Entwickelt man beide Teilnehmer selber, dann sollte man sich streng an> die original Philips/NXP Spezifikation halten. Alles was dort> spezifiziert ist, kann man nutzen.
Mit einer Ausnahme:
Das NACK als Slave, wenn das nächste Byte an eine ungültige Adresse
geschrieben würde, würde ich nicht senden. Ansonsten ist für den Master
niemals erkennbar, ob das letzte Byte in den Slave geschrieben werden
konnte oder nicht.
Siehe Abschnitt 3.6 in der Spezifikation:
http://www.nxp.com/documents/user_manual/UM10204.pdf
Die Regeln für das Senden des NACK durch den Slave, wenn der Master
schreibt, sind für den Master nicht eindeutig. Ein NACK kann bedeuten,
dass der Slave kein weiteres Byte empfangen kann, es kann aber auch
bedeuten, dass der Slave gerade etwas ungültiges empfangen hat oder den
Transfer unterbrechen will.
Warum man das so spezifiziert hat, ist mir ehrlich gesagt unklar.
Gastino G. schrieb:> Das NACK als Slave, wenn das nächste Byte an eine ungültige Adresse> geschrieben würde, würde ich nicht senden. Ansonsten ist für den Master> niemals erkennbar, ob das letzte Byte in den Slave geschrieben werden> konnte oder nicht.>> Siehe Abschnitt 3.6 in der Spezifikation:> http://www.nxp.com/documents/user_manual/UM10204.pdf
Da finde ich nirgends, daß der Slave nach dem letzten Byte ein NACK
senden muß. Es ist also freigestellt.
Nur der Master muß beim Lesen ein NACK senden, damit der Slave nicht das
nächste Byte anlegt. Wäre das nächste Byte 0x00, könnte der Master
nämlich kein STOP senden.
Peter
Peter Dannegger schrieb:> Da finde ich nirgends, daß der Slave nach dem letzten Byte ein NACK> senden muß. Es ist also freigestellt.
Nicht wirklich. Siehe Spec, Punkt 3.6 (Seite 10):
"There are five conditions that lead to the generation of a NACK:
1. No receiver is present on the bus with the transmitted address so
there is no device to respond with an acknowledge.
2. The receiver is unable to receive or transmit because it’s performing
some real-time function and is not ready to start communication with the
master.
3. During the transfer the receiver gets data or commands that it does
not understand.
4. During the transfer, the receiver cannot receive any more data
bytes.
5. A master-receiver needs to signal the end of the transfer to the
slave transmitter."
Die 5 Punkte sind alle als Grund für ein NACK definiert. Die
Formulierung "that lead to the generation of a NACK" klingt nicht nach
einer Freistellung!
> Nur der Master muß beim Lesen ein NACK senden, damit der Slave nicht das> nächste Byte anlegt. Wäre das nächste Byte 0x00, könnte der Master> nämlich kein STOP senden.
Das ist soweit klar. Das ist Punkt 5 in der Liste und ebenso wenig
freigestellt wie Punkt 4.
OK, Leute!
Ich habe das Problem verstanden...
Wenn es so heiß ist, muß man nicht programmieren... :D
Mein Ziel war (und ist noch!) eine allgemeine Library zu bauen, die alle
Fälle abdeckt, und die ich später für meinen Motorensteuerungscontroller
benutzen kann.
Also, konkrete Fälle gibt es noch nicht, aber eine Sache habe ich jetzt
verstanden.
Ich hatte am Anfang einfach nicht gedacht, daß das Programm ganz genau
wissen soll, wie die Daten ankommen. Ich dachte, ich konnte was
allgemeines machen, und das ist FALSCH!
Wenn ich Register nutze, werde ich nie Daten kriegen, ohne vorher den
Register auszuwählen. Und wenn ich keine Register habe, werden alle
Informationen als Daten verwaltet.
DAS war mein Fehler!
Also, ich werde mich weiter beschäftigen. Wenn ich geschafft habe, diese
Library fertig zu programmieren, so daß man mit ein paar #define das
ganze einrichten kann, werde ich gern in die Codesammlung
veröffentlichen.
Bis dahin, besten Dank für eure Erklärungen!
Luca Bertoncello