Hallo zusammen,
Kurze Frage was SPI Empfangen angeht. Das Programm funktioniert bis auf
das Empfangen einwandfrei. Der Mikrocontroller bleibt hängen sobald der
Befehl Master Receive ausgeführt wird. Kann mir jemand erklähren wiso
und was ev. das Problem sein könnte, das ich keine Daten empfangen kann.
Der Code für Emfangen und Senden sind fast identisch und aus meiner
Sicht aus auch korrekt.
Meine Glaskugel sagt mir, dass du wahrscheinlich mit irgendeinem IC
kommunizieren möchtest und dabei die Daten dieses Bausteins aus einem
seiner Register lesen möchtest.
Remo S. schrieb:> SPI_MasterTransmit(0x11);> SPI_MasterTransmit(0xFA);
.. sind dann wohl die entsprechenden Register des ICs. Ob die gesendeten
Bytes so sinnvoll sind. (richtige Register und read-Bit richtig
gesetzt..) kann dir keiner sagen ohne deinen Slave zu kennen.
Peter schrieb:> Du musst auch zum Empfangen etwas senden. Sende einfach 0x00. Wenn du> ein Bit übergibst, erhältst Du auch einen.
Dein Mikrocontroller erzeugt als Master das Clock Signal auf dem SPI
Bus. Das wird aber nur "erzeugt" so lange der Master etwas sendet. Um
dem IC die Möglichkeit zu geben mit seinem Register Inhalt zu antworten
musst du jetzt N -dummy Bytes senden, wobei N die Anzahl der erwarteten
Bytes des Slave ICs sind.
Wie Peter geschrieben hat einfach ein 0xFF oder 0x00 hinterher und dann
den Inhalt aus dem Empfangregister holen.
Wenn du uns aber noch sagst mit welchem Slave Device zu kommunizieren
möchtest, kann man dir bestimmt auch weiter helfen.
> Dein Mikrocontroller erzeugt als Master das Clock Signal auf dem SPI> Bus. Das wird aber nur "erzeugt" so lange der Master etwas sendet. Um> dem IC die Möglichkeit zu geben mit seinem Register Inhalt zu antworten> musst du jetzt N -dummy Bytes senden, wobei N die Anzahl der erwarteten> Bytes des Slave ICs sind.> Wie Peter geschrieben hat einfach ein 0xFF oder 0x00 hinterher und dann> den Inhalt aus dem Empfangregister holen.>> Wenn du uns aber noch sagst mit welchem Slave Device zu kommunizieren> möchtest, kann man dir bestimmt auch weiter helfen.
Oke das hab ich jetzt soweit begriffen, danke nochmals für die
Erklährung. Das Ic ist ein EEPROM mit integrierter MAC Adresse
IC:(25AA02E48) Ich versuche gerade aus den Registern die MAC Adresse zu
lesen. Dafür wird im Datenblatt 0x11 für lesen und dan 0xFA für das
Entsprechende Register gesendet. Ab da kann die 6byte MAC Adresse
ausgelesen werden. Jetzt suche ich verzweifelt nach dem Fehler im Code.
S. Landolt schrieb:>> DDR_SPI |= (1<<DD_MOSI)| (1<<DD_MISO)|(1<<DD_SCK) | (1<<DD_SS);>> Im MasterInit MISO als Ausgang?
Aber er hat doch SPI kapiert. Kannst du nicht lesen?
Remo S. schrieb:> Das Ic ist ein EEPROM mit integrierter MAC Adresse> IC:(25AA02E48)
Alles klar jetzt wird das Bild doch schon langsam klarer.
Die Info, die du von EEPROM lesen möchtest ist 6 Byte lang und steht an
den Adressen 0xFA bis 0xFF. Also musst du schon mal mehr als nur ein
Byte lesen.
"The 6-byte EUI-48™ node address value of the
25AA02E48 is stored in array locations 0xFA through 0xFF[..]" - Seite 13
im Db.
Deine Idee, erst eine Read Instruction zu senden und dann die Adresse
hinterher, war auch richtig. Nur musst du als Read Instruction das Byte
0b0000 0011 senden. In Hex also 0x03 und nicht 0x11.
Danach kommt dann das Adress-Byte also 0xFA. Dann musst du nur noch
abwechselnd ein Dummy Byte senden und das Byte empfangen.
Falls du ein Oszi oder einen logic analyzer hast, häng das mit auf
deinen SPI Bus um alle anderen Fehler auszuschließen.
Bin leider mit den AVR Controllern nicht so bewandert und kann deswegen
auf die Schnelle einen Fehler in deiner Empfangs und Sende Routine
erkennen.
Remo S. schrieb:> Das Programm funktioniert bis auf> das Empfangen einwandfrei.
.. aber wenn du das sagst wird es schon stimmen..
S. Landolt schrieb:>> DDR_SPI |= (1<<DD_MOSI)| (1<<DD_MISO)|(1<<DD_SCK) | (1<<DD_SS);>> Im MasterInit MISO als Ausgang?
gut, MISO als Ausgang zu setzten ist natürlich Banane. Bring also erst
mal dein SPI so weit zum laufen, dass du einzelne Bytes senden und
empfangen kannst und dann lies dir nochmal meinen Beitrag zum richtigen
Protokoll durch. Eine Baustelle nach der anderen.
> Deine Idee, erst eine Read Instruction zu senden und dann die Adresse> hinterher, war auch richtig. Nur musst du als Read Instruction das Byte> 0b0000 0011 senden. In Hex also 0x03 und nicht 0x11.> Danach kommt dann das Adress-Byte also 0xFA. Dann musst du nur noch> abwechselnd ein Dummy Byte senden und das Byte empfangen.> Falls du ein Oszi oder einen logic analyzer hast, häng das mit auf> deinen SPI Bus um alle anderen Fehler auszuschließen.> Bin leider mit den AVR Controllern nicht so bewandert und kann deswegen> auf die Schnelle einen Fehler in deiner Empfangs und Sende Routine> erkennen.
Ja hab ein logic analyzter der mir dabei hilft. Soweit sieht es ja so
aus wie im Datenblatt jedoch kommt von dem Bautein keine Antwort. Ich
hatte zuerst noch micht alle 6byte ausgelesen da ich mit dem ersten
zuerst das ganze testete.
doz schrieb:> S. Landolt schrieb:>>> DDR_SPI |= (1<<DD_MOSI)| (1<<DD_MISO)|(1<<DD_SCK) | (1<<DD_SS);>>>> Im MasterInit MISO als Ausgang?>> gut, MISO als Ausgang zu setzten ist natürlich Banane. Bring also erst> mal dein SPI so weit zum laufen, dass du einzelne Bytes senden und> empfangen kannst und dann lies dir nochmal meinen Beitrag zum richtigen> Protokoll durch. Eine Baustelle nach der anderen.
Das wurde schon korrigiert Danke dafür.
Remo S. schrieb:> Das Programm funktioniert bis auf> das Empfangen einwandfrei.
Wenn du dein EEPROM nicht lesen kannst weil das Empfangen auf SPI nicht
funktioniert, woher weißt du dann, dass das Schreiben auf das EEPROM,
also das Senden auf SPI, funktioniert? Nur weils Pegelwechsel auf der
Leitung gibt muss das noch lange nicht heißen, dass das Senden
funktioniert.
Der Rest wurde ja schon gesagt: Für jedes Byte, dass du auf dem SPI
lesen willst, musst du auch ein Byte senden. Das haben solche
Schieberegister so ansich.
Im Datenblatt auf den Seiten 7 und 8 ist doch klar das Timing gezeigt.
Und das solltest du einhalten.
Zuerst geht Chipselect runter, mit den folgenden 8 Takten von SCLK wird
die "Instruction" zum IC übertragen (MOSI), darauf folgen weitere 8
Takte von SCLK mit denen die Adresse zum IC übertragen wird (auch MOSI)
und danach kommen die Daten (Bytes).
Du willst 6 Byte Daten lesen, und muss vorher Instruction + Adresse
senden, macht zusammen 8 Bytes oder 64 Takte von SCLK.
Du ziehst also Chip select runter, gibst danach 64 Takte auf SCLK aus
und nimmst Chip select wieder hoch.
Während der ersten 8 Takte von SCLK gibst du Instruction, wärend der
nächsten 8 Takte die Adresse aus. Während der weiteren 6*8 Takte von
SCLK kannst du beliebiges ausgeben. Wichtig ist, dass du dann MISO
einliest. Da kommen nämlich die Daten.
M. K. schrieb:> Für jedes Byte, dass du auf dem SPI> lesen willst, musst du auch ein Byte senden. Das haben solche> Schieberegister so ansich.
Das stimmt so allgemein nicht. Es gibt auch ICs, denen genügt es wenn
man Chipselect runterzeiht und die entsprechende anzahl an Takten über
SCLK ausgibt und dann Chipselect wieder hoch nimmt. Die brauchen also
kein MOSI. Beispiel sind ADCs wie der LTC2325.
> Du ziehst also Chip select runter, gibst danach 64 Takte auf SCLK aus> und nimmst Chip select wieder hoch.> Während der ersten 8 Takte von SCLK gibst du Instruction, wärend der> nächsten 8 Takte die Adresse aus. Während der weiteren 6*8 Takte von> SCLK kannst du beliebiges ausgeben. Wichtig ist, dass du dann MISO> einliest. Da kommen nämlich die Daten.
Also für mich sieht das auf dem Bild genau danach aus nicht?
Bild siehe weiter oben (Analyzer)
> Wenn du dein EEPROM nicht lesen kannst weil das Empfangen auf SPI nicht> funktioniert, woher weißt du dann, dass das Schreiben auf das EEPROM,> also das Senden auf SPI, funktioniert? Nur weils Pegelwechsel auf der> Leitung gibt muss das noch lange nicht heißen, dass das Senden> funktioniert.
Das weiss ich daher, dass ich noch ein anderer Baustein anspreche der
sauber funktioniert, allerdings muss ich bei dem nur schreiben nicht
lesen. Aber schreiben funktioniert also sonst würde der andere Baustein
auch nicht gehen.
Remo S. schrieb:> Also für mich sieht das auf dem Bild genau danach aus nicht?> Bild siehe weiter oben (Analyzer)
Entschuldigung, das hatte ich übersehen. Ja, sieht gut aus. Aber ...
vielleicht funktioniert das ja auch, aber du bekommst als Antwort eben
die Bytes mit dem Wert x"00".
Du musst also vorher auch etwas schreiben um etwas von Null
verschiedenes lesen zu können.
Und da hat der IC einen Schreibschutz. Das Write Enable Latch.
http://ww1.microchip.com/downloads/en/DeviceDoc/20002123F.pdf
Auf Seite 9.
doz schrieb:> Remo S. schrieb:>> SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0)| (1 << CPHA);>> stell mal deine CPHA und CPOL auf 0, also SPI Mode 0.
CPHA auf 0 das war die Lösung. DANKE Jedoch ist das einwenig sehr
umstädlich den der eine Baustein braucht CPHA 1 und jezt das EEPROM 0.
Remo S. schrieb:> CPHA auf 0 das war die Lösung. DANKE Jedoch ist das einwenig sehr> umstädlich den der eine Baustein braucht CPHA 1 und jezt das EEPROM 0.
Sorry, war vorhin nicht eingeloggt und habe als Gast(doz) geschrieben.
Dass der EEPROM SPI Mode 0 verlangt, habe ich dem Timing Diagramm aus
dem Datenblatt entnommen.
Bei den meisten ICs steht aber auch konkret drin welche Modes
unterstützt werden. Schau also einfach mal bei deinem anderen IC im
Datenblatt ob er vielleicht auch mit Mode 0 läuft.
Gustl B. schrieb:> Du musst also vorher auch etwas schreiben um etwas von Null> verschiedenes lesen zu können.>> Und da hat der IC einen Schreibschutz. Das Write Enable Latch.> http://ww1.microchip.com/downloads/en/DeviceDoc/20002123F.pdf> Auf Seite 9.
was du geschrieben hast stimmt zwar, ist ein dem Fall aber irrelevant,
da er ja die MAC auf dem write Protected Bereich lesen möchte. Da hilft
auch kein Latch enable und selbst wenn ist 0x03 immernoch eine read und
keine write Instruction.
> Dass der EEPROM SPI Mode 0 verlangt, habe ich dem Timing Diagramm aus> dem Datenblatt entnommen.> Bei den meisten ICs steht aber auch konkret drin welche Modes> unterstützt werden. Schau also einfach mal bei deinem anderen IC im> Datenblatt ob er vielleicht auch mit Mode 0 läuft.
Also ja das EEPRom benötigt CPHA 1 und der andere Baustein CPHA 0. Das
konnte ich auch so herauslesen Danke. Der andere Baustein versteht CPHA
1 gar nicht also ausgeschlossen. Ich versuchte jetzt gerade CPHA wärend
den jeweiligen Routinen zu ändern dies funktioniert leider nicht auch
wen ich SPI deaktiviere und wieder jedes mal erneut aktiviere. Was macht
man in solch einem Fall?
S. Landolt schrieb:> Dacht' ich doch - was ist also das Resultat einer Oder-Operation?
Stimmt wäre ja dan das gleiche.
Müsste ich in demfalle dies so schreiben.
SPCR &= ~(1<<CPHA);
SPCR &= ~(0<<CPHA);
Remo S. schrieb:> S. Landolt schrieb:>> Dacht' ich doch - was ist also das Resultat einer Oder-Operation?>> Stimmt wäre ja dan das gleiche.> Müsste ich in demfalle dies so schreiben.> SPCR &= ~(1<<CPHA);> SPCR &= ~(0<<CPHA);
Lass doch mal das Nullen rumschieben. Es ist wirkungslos und
dokumentiert nur einen mittleren bis großen Hirnschaden beim Autor.
Remo S. schrieb:> umstädlich den der eine Baustein braucht CPHA 1 und jezt das EEPROM 0.
Auf PIC32 habe ich sowas gemacht:
extern void spi_reconfigure(unsigned char user, unsigned char SMP,
unsigned char CKP, unsigned char CKE, unsigned int BRG);
und
extern uint8 spi_lock(unsigned char user);
extern uint8 spi_unlock(unsigned char user);
wenn der user den SPI haben möchte, dann erstmal locken. Dann
umkonfigurieren. Dann CS ziehen, Daten schicken empfangen, dann CS
loslassen und unlock.
Der lock leifert ja zurück ob man glück gehabt hat (SPI war frei).
Könnte sein das da jemand schon etwas überträgt und dafür länger
braucht, sprich acyncrone übertragungen. Das heisst dass der User auch
hier asychron arbeiten muss. Sonst passt das nicht zusammen. Tcha leider
sind die Resourcen knapp und man muss die teilen :) Reconfigure braucht
man immer, weil man ja nicht weiss wer da vorhin etwas gemacht hat.
Es geht ja auch ohne lock, dann kann man aber nicht über längere Zeit
den SPI blockieren. Zum beispiel aus einer Background task daten zu
übertragen über n*10ms cyklen.
Gustl B. schrieb:> Das stimmt so allgemein nicht. Es gibt auch ICs, denen genügt es wenn> man Chipselect runterzeiht und die entsprechende anzahl an Takten über> SCLK ausgibt und dann Chipselect wieder hoch nimmt. Die brauchen also> kein MOSI. Beispiel sind ADCs wie der LTC2325.
War auch nicht allgemein gemeint sondern für AVRs. Und die geben den
SPI-Clock nur aus wenn sie was "Senden" sollen.
Zitat aus dem Datenblatt eines AVRs:
>> Writing a byte to the SPI data register starts the SPI clock generator,>> and the hardware shifts the eight bits into the Slave. After shifting>> one byte, the SPI clock generator stops.
Und hier wird ja ein AVR verwendet ;)
M. K. schrieb:> War auch nicht allgemein gemeint sondern für AVRs. Und die geben den> SPI-Clock nur aus wenn sie was "Senden" sollen.
Welcher Controller macht denn das nicht so das beim Beschreiben des
Daten-Registers ein Transfer ausgelöst wird?
Remo S. schrieb:> Jedoch ist das einwenig sehr> umstädlich den der eine Baustein braucht CPHA 1 und jezt das EEPROM 0.
Was ist daran umständlich? Du setzt einfach das SPCR vor dem jeweiligen
/CS = 0 neu. Das sind nur 2 CPU Instruktionen, da muß man nicht geizig
sein.
TippsUndTricks schrieb:> Auf PIC32 habe ich sowas gemacht:> extern void spi_reconfigure(unsigned char user, unsigned char SMP,> unsigned char CKP, unsigned char CKE, unsigned int BRG);> und> extern uint8 spi_lock(unsigned char user);> extern uint8 spi_unlock(unsigned char user);
Ja, man kann natürlich für einfache Aufgaben auch einen Boliden nehmen,
wo man alles super kompliziert machen muß.
Peter D. schrieb:> Ja, man kann natürlich für einfache Aufgaben auch einen Boliden nehmen,> wo man alles super kompliziert machen muß.
Aber es gab dafür eine Wichsvorlage, also wird's genommen...
C&P-"Programmierer" halt, die können nix selbst, nichtmal Sachen im
Umfang von zwei Maschinen-Instruktionen...
Gustl B. schrieb:> Das stimmt so allgemein nicht. Es gibt auch ICs, denen genügt es wenn> man Chipselect runterzeiht und die entsprechende anzahl an Takten über> SCLK ausgibt und dann Chipselect wieder hoch nimmt. Die brauchen also> kein MOSI. Beispiel sind ADCs wie der LTC2325.
Ja, ja, sicher, wieder mal so eine Aussage...
Ob man eine Null sendet oder 0xFF, ist in deinem Beispiel (LTC2325)
vollkommen egal.
Aber bei Hardware-SPI muss man als Master etwas senden um etwas
zu empfangen. Clock wird nur beim MASTER erzeugt, es geht also schon
mal nicht - CLOCK erzeugen, nix senden...
Ob der Empfänger mit gesendeten Daten oder der Master mit
empfangenen Daten etwas anfangen kann (und soll), ist eine ganz
andere Sache.