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