Hallo zusammen,
ich versuche aktuell das SPI Modul meines dsPIC30F5011 als Master zu
konfigurieren.
Dabei versuche ich eine Routine zu basteln, die gleichzeitig empfängt
und sendet.
Als "Empfangsdaten" erwarte ich jeweils immer 1 Byte aus 0en und 1en ;)
Die Routine sieht aktuell folgendermaßen aus:
1
unsigned char sendreadSPI2(unsigned char data)
2
{
3
unsigned char dummy;
4
dummy = SPI2BUF ; //Auslesen vor dem Senden
5
6
SPI2BUF = data;
7
8
while(!IFS1bits.SPI2IF); //Warten bis gesendet=>Auslesen Interrupt Flag
9
10
while(SPI2STATbits.SPITBF); //Warten bis TransmitBuffer voll
11
dummy = SPI2BUF ; //reset, damit gesendetes Byte weg ist
12
13
while(!SPI2STATbits.SPIRBF); //Warten bis Empfangsbuffer voll
14
15
return SPI2BUF;
16
17
}
Irgendwie bleibt meine Schleife aber kontinuierlich in dem
while(!SPI2STATbits.SPIRBF); hängen. Nun versuche ich auszuschließen,
dass diese Schleife einen Fehler hat oder ob meine Initialisierung für
meinen Slave falsch ist.
Sieht jemand einen entscheidenden Denkfehler?
Der Programmablauf wäre grob:
1.) Senden eines Request, dass ich mehrere Register auslesen will.
Also quasi: sendreadSPI2(Befehl);
2.) for- Schleife, welche lang genug für jedes Register ist das ich
erwarte und dann nach dem Motto:
Ergebnis1= sendreadSPI2(0x00);
Das 0x00 sende ich, damit ausgelesen wird, aber keine neue Information
gesendet. Dürfte ja auch so richtig sein oder?
Liebe Grüße
Ralf
Ralf Kowalski schrieb:> ich versuche aktuell das SPI Modul meines dsPIC30F5011 als Master zu> konfigurieren.> Dabei versuche ich eine Routine zu basteln, die gleichzeitig empfängt> und sendet.
Da genau das der absolute Normalfall für SPI ist, sollte das unabhängig
vom verwendeten µC vollkommen problemlos umzusetzen sein...
Das Problem ist vermutlich nur, dass du sowas von überhaupt keine
Vorstellung hast, wie SPI funktioniert, dass es die Hunde jammert...
Ralf Kowalski schrieb:> Dabei versuche ich eine Routine zu basteln, die gleichzeitig empfängt> und sendet.
Was wäre da so besonders dran. SPI ist immer ein Byteaustausch - auf dem
einen Ende kommt was aus dem Schieberegister raus und auf dem anderen
Ende kommt was rein.
Ralf Kowalski schrieb:> Die Routine sieht aktuell folgendermaßen aus
Ja.
Ich verstehe dein Anliegen dennoch nicht. Normalerweise vergeudet man
Rechenzeit nicht, weswegen Trampelschleifen verpönt sind. Man wartet
deshalb lieber auf das Eintreffen von Bedingungen wie z.B. ein
Interrupt, der anzeigt, daß jetzt ein neuese Byte/Wort irgendwo
eingetroffen ist oder daß ein Sendepuffer jetzt ein neues Byte/Wort
vertragen könnte. Und dann reagiert man per Interrupt-Routine darauf.
Dazu werden In- und Out-Ströme dezent zwischengepuffert, so daß man eine
zeitliche Entkopplung hat zwischen dem Strom und seinem eigentlichen
Algorithmus.
Wo bittesehr sehe ich sowas in deinem Entwurf?
W.S.
c-hater schrieb:> Das Problem ist vermutlich nur, dass du sowas von überhaupt keine> Vorstellung hast, wie SPI funktioniert, dass es die Hunde jammert...
Ich taste mich da langsam heran und habe in anderen Foren gelesen, dass
es nicht unbedingt unüblich ist die Routinen entweder aufzuteilen, daher
war ich etwas verunsicher, wieso man das ganze aufteilt.
Scheint die Routine denn sonst richtig zu sein? Abgesehen von der
Anmerkung vonholger?
W.S. schrieb:> Ich verstehe dein Anliegen dennoch nicht. Normalerweise vergeudet man> Rechenzeit nicht, weswegen Trampelschleifen verpönt sind. Man wartet> deshalb lieber auf das Eintreffen von Bedingungen wie z.B. ein> Interrupt, der anzeigt, daß jetzt ein neuese Byte/Wort irgendwo> eingetroffen ist oder daß ein Sendepuffer jetzt ein neues Byte/Wort> vertragen könnte. Und dann reagiert man per Interrupt-Routine darauf.> Dazu werden In- und Out-Ströme dezent zwischengepuffert, so daß man eine> zeitliche Entkopplung hat zwischen dem Strom und seinem eigentlichen> Algorithmus.>> Wo bittesehr sehe ich sowas in deinem Entwurf?
Ich verstehe deine Anmerkung. Die Rechenzeit ist bei mir prinzipiell
aber eher unkritisch. Dazu habe ich nur einen Slave, der mir nur dann
Daten zurückgibt, wenn ich konkret vorher per Request anfordere. Daher
würde der Interrupt doch eigentlich auch nur direkt nach dem Senden
ausgelöst werden und es ergeben sich keine weiteren vorteile abgesehen
davon, dass er ggf. nicht in der while festhängt. Dieses in der while
festhängen könnte man allerdings auch noch ohne großen Aufwand
beseitigen.
Ralf Kowalski schrieb:> Ich taste mich da langsam heran und habe in anderen Foren gelesen
Lesen in Foren ist u.U. nützlich, wenn man ein konkretes Problem hat. Es
kann aber niemals systematisches Lernen ersetzen.
> dass> es nicht unbedingt unüblich ist die Routinen entweder aufzuteilen, daher> war ich etwas verunsicher, wieso man das ganze aufteilt.
Es gibt sicher Bussysteme, bei denen es sehr sinnvoll ist, Lesen und
Schreiben in getrennten Routinen zu behandeln. Nur ist SPI eben kein
solches Bussystem, sondern das genaue Gegenteil davon. Mit hinreichendem
Grundlagenwissen über die Funktionsweise ist das jedem sofort klar, der
auch nur ansatzweise logisch denken kann. Dein Problem ist halt, dass
dir genau dieses Grundlagenwissen fehlt. Da hilft nur eins: Lernen.
W.S. schrieb:> Rechenzeit nicht, weswegen Trampelschleifen verpönt sind. Man wartet> deshalb lieber auf das Eintreffen von Bedingungen wie z.B. ein> Interrupt, der anzeigt, daß jetzt ein neuese Byte/Wort irgendwo> eingetroffen ist oder daß ein Sendepuffer jetzt ein neues Byte/Wort> vertragen könnte. Und dann reagiert man per Interrupt-Routine darauf.
Aber nicht beim SPI.
Ein Slave kann keine Kommunikation starten, nur Master.
Deswegen ist es nix mit Interrupt und Master, es sei denn, Master
sendet Daten in Paketen, was aber hier nicht der Fall ist.
Danke für die Anmerkungen und Hilfestellungen die ich bisher erhalten
habe
Ich denke ich habe mein eigentliches Problem gefunden.
Mein Slave "verlangt" CPOL=1 und CPHA=1 also folglich:
Eine Clock, die den Idle auf High hat. Darüber hinaus müssen die Daten
am SDI des Slaves stabil sein, wenn eine steigende Flanke der CLK kommt.
Interpretiere ich die angehängte Grafik richtig:
CKP muss 1 sein => Idle = 1
CKE muss 0 ein => Daten auf steigender Flanke stabi
Daraus folgt der zweite SCKX Graph ist der entsprechend relevante.
Für SMP finde ich im Reference:
1
SMP: SPI Data Input Sample Phase bit
2
Master mode:
3
1 = Input data sampled at end of data output time
4
0 = Input data sampled at middle of data output time
Nach welcher relevanten Info muss ich dazu im Datenblatt des Slaves
suchen?
Mir scheint es aus dem Zusammenhang so, als hängt das stark davon ab,
wie ich CKE setze. Wenn ich eine steigende Flanke abwarte kann ich mit
der ANtwort folglich erst am Ende rechnen und nicht direkt in der Mitte.
Vielen Dank für jede weitere Hilfe :)
Hallo,
bei PIC24 (welche fast identisch mit dspic33 sind) ist das so:
SPI1CON1bits.CKE = xx; //clock edge select
SPI1CON1bits.CKP = XX; //clock polarity select
Steht im SPI-Kapitel des Handbuchs.
Sei dir im Klaren, dass dieses nur eine Zusammenfassung ist. Eine
detailliertere Beschreibung findest du auf der Produktseite deines PIC.
Dort sind auch Codebeispiele drin, welche das Leben doch sehr
erleichtern.
Desweiteren gibts das hier:
http://www.microchip.com/doclisting/TechDoc.aspx?type=CodeExamples
Heiner schrieb im Beitrag #4642295:
> c-hater schrieb:>> ist das jedem sofort klar, der>> auch nur ansatzweise logisch denken kann.>> Du hast es drauf, Troll!>> lg Heiner
Diesmal hat er Recht, der Troll bist du.