Ich habe an meinem Pico den DA-MCP4922 an SPI angeschlossen.
Der DA hat nur einen Write Kanal. Der SPI_MOSO Pin ist unbeschaltet,
aber als SPI-Pin initalisiert.
Wenn ich nun dahin Daten sende, bleibt in der API-Funktion in Zeile 12
das Programm hängen. Da wird ja gefragt ob Readable.
Rudi schrieb:> Meine DA-SPI-Ic ist aber nicht readable.
Uninteressant!
Rudi schrieb:> SPI_MOSO
Du meinst MISO!
Irgendwo muss MISO als Eingang am RP definiert werden.
Dann kann man ihn mit einem Pullup oder Pulldown versehen um eindeutige
Pegel zu erhalten.
Die µC SPI Einheit merkt nicht, dass da kein Baustein angeschlossen ist.
Bei SPI gibt es kein "OnlyWrite". SPI tauscht auf unterstem Level immer
gleichzeitig Bytes zwischen Master und Slave in beide Richtungen aus,
auf MOSI (= Master out, Slave In) vom Master zum Slave, auf MISO (=
Master In, Slave Out) vom Slave zum Master. Der Master ist derjenige,
der den Clock für die Taktung der Übertragung erzeugt.
Ob deine Software dann eines der übertragenen Bytes ignoriert, bleibt
ihr überlassen.
Rudi schrieb:> SPI_MOSO Pin
Master Out Slave Out, also eine Buskollision.
> Wie geht sowas trotzdem?
Sieh dir an, was die von dir verwendete spi_is_readable(spi) macht. Und
dann wirf sie raus oder schreib sie um.
Mein Tipp:
1. sieh dir an, was SPI ist und wie er funktioniert (das sind nur
gekoppelte Schieberegister)
2. sieh dir an, welche Struktur der SPI deines uC hat und verstehe, wie
du sie ansteuern musst, dass das Schieberegister lostaktet
3. schreib diese Software selber, lass das nicht die KI machen
Lothar M. schrieb:> Master Out Slave Out, also eine Buskollision.
oder dicke Finger, wenn man bedenkt, wo sich "I" und "O" auf der
Tastatur befinden ;)
Lothar M. schrieb:> Sieh dir an, was die von dir verwendete spi_is_readable(spi) macht. Und> dann wirf sie raus oder schreib sie um.
Nein, auf keinen Fall. Die gesamte Routine spi_write16_blocking() stammt
direkt aus dem SDK und sie funktioniert so, wie sie ist. Benutze ich an
etlichen Stellen in etlichen Programmen.
Sie ist allerdings etwas schräg konstruiert. Um schneller schreiben zu
können, wird während des Schreibvorgangs erst mal alles ignoriert, was
mit der Empfangsseite der SPI-Hardware zu tun hat.
Dadurch "hängen" dann natürlich ungelesene Daten im RX-FIFO, u.U. ist
auch der RX-FIFO übergelaufen. Alles ab Zeile 10 in dieser Routine dient
einzig dazu, nach dem Schreiben auch die RX-Seite der Hardware
"aufzuräumen" und wieder in einen sauberen und leeren Zustand zu
versetzen. Diese SPI-Schnittstelle ist eben doch MEHR als einfach nur
ein Schieberegister!
Das Problem des TO liegt wahrscheinlich an einer inkorrekten
Initialisierung der SPI-Hardware. Die hat er aber leider nicht gezeigt.
Rainer W. schrieb:> Bei SPI gibt es kein "OnlyWrite".
Und wenn der Slave MCP4922 keinen Sendepin hat?
Lothar M. schrieb:> Und dann wirf sie raus oder schreib sie um.
Das ist eine API-Funktion! Die kann ich nicht.
Ob S. schrieb:> Die hat er aber leider nicht gezeigt.
1
MCP4922::MCP4922(){
2
3
if(!spi_is_writable(SPI_PORT)){
4
// SPI initialisation. This example will use SPI at 1Mhz.
Mach mal das ganze init Zeug aus deinem Konstruktor in eine eigene
init() Methode und rufe diese zu einem definierten Zeitpunkt in
setup/main auf.
Die Aufrufe momentan im Konstruktor passieren sehr früh. Vielleicht zu
früh.
Außerdem kannst du mit einer init() auch gezielter steuern wann der
Zugriff auf die Register genau passiert. Momentan ist das abhängig vom
Zeitpunkt der Erzeugung der Objekte.
Nicht dass da nochmal später in main was überschrieben wird oder die
Clocks noch garnicht initialisiert waren.
Rudi schrieb:> Und wenn der Slave MCP4922 keinen Sendepin hat?
Das interessiert nicht.
Bevor du sendest, hast du im SSPSR nur TNF: 1 | TFE: 1.
Wenn du dann sendest, jedoch keine Daten abholst, bzw. noch nicht einmal
einen GPIO MOSI zugewiesen hast,
dann kommt im SSPSR erst RNE: 1 und nach kurzer Zeit RFF: 1.
Aber, und das ist wichtig, das sind lediglich flags.
Es wird nichts blockiert.
PS.
Sollte diese Zeile:
Ob S. schrieb:> Dadurch "hängen" dann natürlich ungelesene Daten im RX-FIFO, u.U. ist> auch der RX-FIFO übergelaufen. Alles ab Zeile 10 in dieser Routine dient> einzig dazu, nach dem Schreiben auch die RX-Seite der Hardware> "aufzuräumen" und wieder in einen sauberen und leeren Zustand zu> versetzen.
Beim OP können da ja gar keine Daten in den FIFO reinlaufen, weil sein
Slave keine liefert.
Also den MISO-Pin fest auf Low legen. Wenn das nicht genügt, die
API-Doku studieren (was genau macht spi_is_readable). Es kann ja nicht
sein, dass man nur Slaves anschließen kann, die bidirektional arbeiten.
Nebenbei: "Readable" heißt "lesbar". Das ist zumindest zweideutig.
Gemeint ist "Es befinden sich derzeit Daten im FIFO, die man auslesen
kann (Rx data available)". Gemeint ist nicht das Gegenteil von
"readonly", also der grundsätzlichen Möglichkeit, irgendetwas etwas zu
lesen. Steht ja in der Doku:
https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_spi_1ga20dcaa3037e92bbcbab50b8635f102ff
Soweit Danke.
Jetzt hänge ich am nächsten Problem.
1
spi_set_format(SPI_PORT,16,0,0,SPI_MSB_FIRST);
Weil ich ja 16Bits senden will soll ich diese Zeile einfügen. Der
Compiler mekert aber die beiden Nullen an. Ohne dieser Zeile messe ich 8
Clockimpulse. Seltsammer Weise sind diese nur dreieckig. Bei Data kommt
nur Dauerhigh. CS ist ok.
Rudi schrieb:> Rainer W. schrieb:>> Bei SPI gibt es kein "OnlyWrite".> Und wenn der Slave MCP4922 keinen Sendepin hat?
Dann liest der Master trotzdem ein, was bei ihm an MISO anliegt.
Rudi schrieb:> Weil ich ja 16Bits senden will soll ich diese Zeile einfügen.
spi_set_format ( SPI_PORT, 16, 0, 0, SPI_MSB_FIRST);
> Der Compiler mekert aber die beiden Nullen an.
Es hilft, wenn du sagst, wie die Fehlermeldung lautet. :-(
Ich rate mal: "Falscher Typ". Dort werden ja auch keine Integer ("0")
erwartet, sondern zwei Namen von enum-Konstanten. Siehe
Funktionsdefinition. So, wie SPI_MSB_FIRST ja auch eine enum-Konstante
ist. Die Namen der der Konstanten findest du unter dem Link, den ich
schon genannt habe.
Nimm also SPI_CPHA_0 und SPI_CPOL_0. Dann ist das Programm auch besser
lesbar.
Rolf schrieb:> Beim OP können da ja gar keine Daten in den FIFO reinlaufen, weil sein> Slave keine liefert.
Unsinn. Da wird immer irgendetwas gelesen. Auch dann, wenn es überhaupt
keine echte Datenquelle gibt. Selbst wenn der RX-Pin einfach nur in der
Luft hängt. Dann werden halt Zufallsdaten gelesen.
Norbert schrieb:> Rudi schrieb:>> Weil ich ja 16Bits senden will soll ich diese Zeile einfügen.>> Frechheit, dass ShitGPT das nicht besser erklärt.
LOL
Naja, mit Nachhaken kann man vermutlich auch eine bessere Erklärung
bekommen. Aber ob die irgendwas mit der objektiven Realität zu tun hat
oder reine KI-Halluzination ist, wer weiß das schon...
Ob S. schrieb:> Selbst wenn der RX-Pin einfach nur in der> Luft hängt. Dann werden halt Zufallsdaten gelesen.
Das sind dann Zufallswerte, keine Daten. Bei einer Datenübertragung
werden Daten vom sie sendenden Partner generiert.
Rolf schrieb:> Das sind dann Zufallswerte, keine Daten.
Was ist der Unterschied zwischen Werten und Daten?
> Bei einer Datenübertragung> werden Daten vom sie sendenden Partner generiert.
Ja. Nur ist in dieser konkreten Anwendung eben eine Datenübertragung in
dieser Richtung nicht gewünscht, ja nicht einmal möglich, weil eben der
Partner NICHT in der Lage ist, irgendwas sinnvolles zu generieren,
schon weil ihm ein passender Pin dafür fehlt.
Aber gelesen wird unweigerlich trotzdem irgendetwas. Und genau das ist
hier der springende Punkt. Und eben deswegen existieren die Zeilen ab
Nr. 10 im Code der SDK-Routine.
Das kann doch nicht so schwer zu begreifen sein?!
Rolf schrieb:> Nimm also SPI_CPHA_0 und SPI_CPOL_0. Dann ist das Programm auch besser> lesbar.
Das hatte ich schon probiert, aber leider in falscher Reihenfolge.
Sorry, manchmal bin ich doch zu oberflächlich.
An Alle:
Seit 12:00 Uhr blockiert der MISO nicht mehr.
.... denn MISO ist ein Daten-Eingangspin der dem SPI-Input-
Register einfach nur Daten liefert die am Pin anliegen. Und
das können genau zwei Werte sein: 1 oder 0. MISO beeinflusst
nicht den Ablauf der SPI-Statemachine.
Wastl schrieb:> .... denn MISO ist ein Daten-Eingangspin der dem SPI-Input-> Register einfach nur Daten liefert die am Pin anliegen. Und> das können genau zwei Werte sein: 1 oder 0. MISO beeinflusst> nicht den Ablauf der SPI-Statemachine.
Genauso ist das. Der Slave hat keinerlei Einfluss auf die Statemachine
des Masters. Der Hardware und dem "Treiber" ist vollkommen Wurscht, was
genau da gelesen wird. Es wird aber immer irgendwas gelesen. Das muss
der "Treiber" berücksichtigen und tut das auch.
Hallo, ein großteil der Disskussion geht von missverstandenen Umständen
aus. Ich hab in Beitrag
Beitrag "PicoPi & OnlyWrite SPI blockiert" gefragt warum die
API-Funtion hängen bleibt.
Im Beitrag Beitrag "Re: PicoPi & OnlyWrite SPI blockiert" sieht
man meinen Fehler: Die SPI-Init sollte da nur ausgeführt werden , falls
die SPI noch nicht da ist. Das aber geht nicht so! Ohne die IF-READABLE
Abfrage ist der Fehler weg.
Rudi schrieb:> Ohne die IF-READABLE Abfrage ist der Fehler weg.
Also in etwa das, was
ich schrieb:>>> Sieh dir an, was die von dir verwendete spi_is_readable(spi) macht. Und>>> dann wirf sie raus
// SPI initialisation. This example will use SPI at 1Mhz.
3
spi_init(SPI_PORT,1000*1000);
4
gpio_set_function(PIN_MISO,GPIO_FUNC_SPI);
Es tut mir leid. Ich habe schon wieder einen Flüchtigkeitsfehler
gemacht.
Rudi schrieb:> Ohne die IF-READABLE Abfrage
Ich habe nicht die API- spi_is_readable(spi) Fkt entfernt sondern die IF
Abfrage in der INIT-Sequenz. Denn so wurde diese Init nicht ausgeführt,
was zur zur Blockade führte.
Mein Logigfehler war: wenn der SPI-Port schon vorher, möglicher Weise,
Initalisiert war, dann kann man gleich senden. Dass diese Abfrage auch
ohne spi_init True meldet konnte ich nicht vermuten.
Wie viel Wind muss man eigentlich machen, wenn es insgesamt um die
Konfiguration zweier GPIO Pins und um genau drei (DREI) SPI-Register
Zugriffe zur Initialisierung geht?
Denn damit hat man ein lauffähiges SPI eingerichtet.