Forum: Mikrocontroller und Digitale Elektronik I²C Slave. Probleme mit REP_START


von Luca B. (lucabert)


Lesenswert?

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
    case TW_START:
7
    case TW_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

von marc2100 (Gast)


Lesenswert?

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

von stephan_ (Gast)


Lesenswert?

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.

von Luca B. (lucabert)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Gastino G. (gastino)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

Gastino G. schrieb:
> Natürlich kann auch der Slave
> transmitten.

Nein, der Slave kann kein START oder repeat START senden!


Peter

von Gastino G. (gastino)


Lesenswert?

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!

von Luca B. (lucabert)


Lesenswert?

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

von Gastino G. (gastino)


Lesenswert?

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.

von Luca B. (lucabert)


Lesenswert?

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

von Sascha W. (sascha-w)


Lesenswert?

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

von Luca B. (lucabert)


Lesenswert?

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

von Sascha W. (sascha-w)


Lesenswert?

> 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

von Luca B. (lucabert)


Lesenswert?

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

von Sascha W. (sascha-w)


Lesenswert?

> 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

von Gastino G. (gastino)


Lesenswert?

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!

von Gastino G. (gastino)


Lesenswert?

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
...

von Luca B. (lucabert)


Lesenswert?

> 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

von Gastino G. (gastino)


Lesenswert?

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.

von Luca B. (lucabert)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Sascha W. (sascha-w)


Lesenswert?

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

von Gastino G. (gastino)


Lesenswert?

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.

von Gastino G. (gastino)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Gastino G. (gastino)


Lesenswert?

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.

von Luca B. (lucabert)


Lesenswert?

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

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.