Hallo,
ich möchte gerne einen Fifo per SPI von einem Slave auf einen Master
übertragen. Der Fifo auf dem Slave soll slavefifo hier heissen. Die
Werte in dem slavefifo sind 16bit breit.
Per SPI kann ich nur 8bit Daten versenden. Hat jemand von Euch einen
Link zu einer fertigen Routine, wie man größere Datenmengen darüber
versenden kann?
Warum nicht einfach 2x 8 Bit versenden und dann beim Empfänger wieder
zusammensetzen? Bzw. im Zweifelsfalle eben nicht den Hardware-SS-Pin zu
nehmen sondern eben einen beliebigen anderen Pin und dann eben eben zu
Beginn der Übertragung diesen Pin auf LOW ziehen, erst die ersten 8 Bit
und dann die zweiten 8 Bit übertragen und dann diesen Pin eben auf HIGH
ziehen.
Wo liegt das Problem?
Was ich gut hinbekommen habe, das ist die Zerlegung der 16bit-Werte in
zwei 8bit-Werte mit dem Shifen >>8 und dem Unden & 0xFF - und das
Zusammenbauen auf der Master-Seite.
Jetzt geht es darum, eine Möglichkeit zu finden, viele Werte
hintereinander gut zu übertragen.
Mein Problem ist die Sache mit dem SPI-Port. Ich kann mir die Länge der
zu übertragenden Daten ermitteln - nehmen wir mal an, ich möchte 30
Stück aus meinem Fifo lesen.
Also muss der Master 60 mal 8bit-Werte holen (30 mal 16bit aus dem
Fifo).
Ein einfacher schöner Befehl wäre, wenn ich auf dem Raspberry Pi unter
Python das machen könnte:
spi.readbytes(Anzahl*2).
Dann bekomme ich eine Liste in Python mit 60 Elementen. Leider
funktioniert das auf der Slave-Seite nicht, die Daten dann so
bereitzustellen, dass ich den spi.readbytes-Befehl ausführen kann. Es
kommt dann nur ein Wert an.
Auf der Slave-Seite muss ich mit dem Befehl
.reply(value); den Wert an den SPI-Port schreiben, damit er bei der
nächsten Leseoperation ausgewertet werden kann.
Ich komme halt momentan auf keine neue Idee, wie ich das hinkriegen
kann.
Stefan Schmidt schrieb:> Warum nicht einfach 2x 8 Bit versenden und dann beim Empfänger wieder> zusammensetzen?
das klappt ja schon.
Stefan Schmidt schrieb:> Bzw. im Zweifelsfalle eben nicht den Hardware-SS-Pin zu> nehmen sondern eben einen beliebigen ...
Meinst Du, ich muss mir einen Software-SPI-Port entwickeln und nicht den
Hardware-SPI benutzen?
Hugo Zahnfee schrieb:> Stefan Schmidt schrieb:>> Bzw. im Zweifelsfalle eben nicht den Hardware-SS-Pin zu>> nehmen sondern eben einen beliebigen ...>> Meinst Du, ich muss mir einen Software-SPI-Port entwickeln und nicht den> Hardware-SPI benutzen?
Entweder du bleibst bei 8-Bit oder du benutzt ein eigenes
16-BIT-Software-SPI.
--> Zerleg es is 2 Teile und nimm Hardware-SPI
Was nicht geht ist das hier:
Microcontroller(C):
for (i=0; i<30; i++) { device.reply(i); }
Master (Python):
result = spi.readbytes(30)
[/c]
Ich verstehe einfach nicht, warum das mit dem spi.readbytes(30) nicht in
einem Rutsch funktionieren tut :-(
In Python kenne ich mich nicht wirklich aus, aber prinzipiell habe ich
es wie folgt implementiert gehabt:
Ich habe einen beliebigen freien Pin (beispielsweise Pin PC1) mit dem
SS-Pin vom Slave verbunden. Die restlichen Hardware-SPI-Pins habe ich
beibehalten und alles entsprechend verkabelt.
Dann habe ich unmittelbar vor dem Aktivieren der Übertragung mittels SPI
einfach den Pin PC1 auf Low gezogen und die ersten 8 Bit ganz normal
übertragen.
Nach dem die Übertragung fertig ist wird ja der eigentliche
Hardware-SS-Pin wieder auf High gezogen. Dies juckt den Slave ja nicht,
da der Pin PC1 immer noch auf low ist.
Daraufhin habe ich erneut eine SPI-Übertragung mit den zweiten 8 Bit
gestartet und NACH DEM diese beendet war den Pin PC1 auf High gezogen.
So sieht es für den Slave aus, als ob die 16 Bit am Stück übertragen
wurden. Hauptsache der SS-Pin VOM SLAVE ist Low während der gesamten
Übertragung(en).
Hugo Zahnfee schrieb:> Die Kombination funktioniert:> Microcontroller (C):>> for (i=0; i<30; i++) { device.reply(i); }>> Master (Python):>> for kkkk in range (0, 30):> result.append(spi.readbytes(1)[0])>> Was nicht geht ist das hier:>> Microcontroller(C):>> for (i=0; i<30; i++) { device.reply(i); }>> Master (Python):>> result = spi.readbytes(30)
Also es scheint daran zu liegen, dass dein uC die Daten nicht
rechtzeitig in den Buffer legen kann. Mit der funktionierenden Variante
wird vermutlich für jedes Byte die SS Leitung auf Low gezogen und nach
dem einen Byte wieder losgelassen. Das passiert 30 mal. Dabei hat der uC
genug Zeit seinen Buffer zu füllen.
Bei der nicht funktionieren Variante wird die SS Leitung nur einmal Low
gezogen, dann werden schnell 30 Bytes versendet und danach wird die SS
Leitung losgelassen.
sushi schrieb:> Bei der nicht funktionieren Variante wird die SS Leitung nur einmal Low> gezogen, dann werden schnell 30 Bytes versendet und danach wird die SS> Leitung losgelassen.
Das wird das Problem sein. Ich habe mir den Quelltext nicht genau
angesehen, aber ausgehend davon, dass der µC nur einen Puffer von 8 Bit
hat muss natürlich JEDES MAL die SS-Leitung losgelassen werden.
Ich habe ursprünglich nur auf die Anforderung geantwortet gehabt, mehr
als 8 Bit auf einmal zu versenden. Habe angenommen, dass ein IC/Slave
angesprochen werden sollte, welches eben einen (beispielsweise) 16 Bit
langen Befehl braucht bzw. dessen Puffer groß genug ist.
Es kann aber auch sein, dass dein Chip dir per Interrupt Bescheid gibt,
dass dein Puffer sich leert, und du dann dort schnell weitere Bits
hineinschieben kannst...
Stefan Schmidt schrieb:> Das wird das Problem sein. Ich habe mir den Quelltext nicht genau> angesehen, aber ausgehend davon, dass der µC nur einen Puffer von 8 Bit> hat muss natürlich JEDES MAL die SS-Leitung losgelassen werden.
So ist es. Ein SPI Slave hat keine andere (sichere) Möglichkeit
signalisiert zu bekommen dass ein Datum eintrifft. Es sei denn
er zählt die Clocks einzeln mit.
sushi schrieb:> Bei der nicht funktionieren Variante wird die SS Leitung nur einmal Low> gezogen, dann werden schnell 30 Bytes versendet und danach wird die SS> Leitung losgelassen.
Ach so - Du meinst, der Buffer kann erst dann befüllt werden, wenn CS
seinen Pegel ändert und "fertig" ist?