MSSP SPI von PIC = Kuriosität, aber Bit-Banging funktioniert?

Ich versuche, einen PIC16LF1825- Master dazu zu bringen, mit einem ADXL362- Slave über SPI bei 1,8 V zu kommunizieren.

Zuerst habe ich den MSSP (serieller Port des PIC) ausprobiert, der für Hardware-SPI bei 4 MHz FOSC, 1 MHz SPI-Rate (mindestens die von ADXL empfohlene) bei 3,2 V konfiguriert ist. Es hat irgendwie funktioniert und den folgenden SCK und MOSI für den ADXL produziert:

DSO-Erfassung von SCK und MOSI, MSSP-Methode.

Beachten Sie, dass MOSI zwischen den Bytes hoch gehalten wird. Das erste gesendete Byte ist 0x0B (Leseregisterbefehl), gefolgt von 0x00 (Geräte-ID). Das dritte Byte sollte also die zurückgegebenen Daten sein ...

DSO-Erfassung von SCK und MISO, MSSP-Methode.

Was der ADXL jedoch zurückschickte, war falsch. Es sollte 0xAD sein, aber stattdessen bekam ich alle möglichen falschen Werte, 0x90 wird angezeigt. Ich habe alle CPOL- und CPHA-Modi ohne Erfolg ausprobiert. Wird das MOSI zwischen den Bytes hoch gehalten, was zu einer Beschädigung der interpretierten Daten durch ADXL führt? Würde ich nicht glauben ... Das Seltsamste ist, dass sich dieser zurückgegebene Wert scheinbar zufällig ändert, obwohl nichts sichtbar mit SCK oder den anderen Pins passiert ist. Ich habe nach einem Muster mit möglichen zurückgegebenen Werten gesucht (zeigte es tatsächliche Registerinhalte an?), fand aber keine Korrelation. Das Trennen der Oszilloskopsonden (parasitäre Kapazität) hatte keine Wirkung. Der XC8-Code, den ich ursprünglich ausprobiert habe, sah so aus:

/* Routine to fully exchange a byte with the ADXL362 - requires MSSP */
extern uint8_t ExchangeADXL(uint8_t txCommand, uint8_t txAddress, uint8_t txData) {
    SS_ADXL_SetLow();           // SS low
    SSP1CON1bits.WCOL = 0;      // clear any write collision flag

    SSPBUF = txCommand;         // send read/write/fifo byte
    while (!SSP1STATbits.BF);   // wait for exchange

    SSPBUF = txAddress;         // send address byte
    while (!SSP1STATbits.BF);   // wait for exchange

    SSPBUF = txData;            // send byte or dummy byte
    while (!SSP1STATbits.BF);   // wait for exchange (read result)

    SS_ADXL_SetHigh();          // SS high
    return (SSPBUF);            // return result
}

Dies verwendet den Microchip Code Configurator (MCC), um eine Grundkonfiguration für das Gerät zu generieren (Zeit ist natürlich von entscheidender Bedeutung).

Also versuchte ich es mit Bit-Banging. Also habe ich ein wirklich haarig aussehendes Stück Code geschrieben, speziell um MOSI zwischen den Bytes auf Low gehen zu lassen, und siehe da, es hat funktioniert! (Der FOSC wurde hier auf 250 kHz und Vdd auf 1,8 V reduziert.)

DSO-Erfassung von SCK und MISO, Bit-Bang-Methode.

Beachten Sie jedoch das "Rauschen" in der MISO-Leitung. Das ist neu und war vorher nicht da. Alle Bypass-Kappen, Masse, Vdds, Übersprechen, Oszilloskopsonden usw. doppelt überprüft. Keine Ahnung, was es außer dem ADXL verursacht.

Wie auch immer, ich habe den Code wieder auf die Verwendung des MSSP umgestellt, anstatt Bit-Banging, um zu sehen, ob die Hardware mit einer viel reduzierten Geschwindigkeit arbeiten würde. Die Befehle werden sehr klar an ADXL gesendet, aber das einzige, was es zurückgibt, ist Folgendes:

DSO-Erfassung von SCK und MISO, MSSP-Methode.

Hat jemand eine Ahnung, was hier los ist? Der Lärm ist kein großes Problem ... das Fehlen einer Antwort ist. Es hat vorher (fälschlicherweise) mit einer SPI-Rate von 62,5 Hz und 1,8 V geantwortet, jetzt tut es nichts und Rauschen ist sichtbar. Ich würde viel lieber den Hardwaretreiber für SPI verwenden, wenn dies möglich ist.

(nicht gezeigt) verhält sich SS für alle Instanzen so, wie es sollte. Soweit ich das beurteilen kann, liegen alle Timings innerhalb der Spezifikationen des ziemlich anspruchsvollen ADXL-Datenblatts. Danke für deine Hilfe!

Für das Rauschen, das Sie beobachten, sagt das Datenblatt Folgendes: Wie in Abbildung 36 bis Abbildung 40 gezeigt, befindet sich der MISO-Pin in einem hochohmigen Zustand, der von einem Buskeeper gehalten wird, außer wenn der ADXL362 Lesedaten sendet (um Daten zu sparen). Busstrom). Es fährt also nicht wirklich die Linie, es schwebt nur mit dem Lärm.
Das macht Sinn. Abgesehen davon, dass der MSSP anscheinend Bytes ordnungsgemäß sendet, aber der ADXL diese entweder nicht "sieht" oder sich anderweitig weigert, eine Antwort zu senden. Nur bei Verwendung des Hardware-SPI ... Bit-Banging funktioniert immer noch wie erwartet. Sehr eigenartig.

Antworten (2)

Ich habe das Problem gefunden. Es war tatsächlich der Takt, der zwischen den Bytes hoch war. Nun, nicht genau; es war, dass der ADXL das 2. Byte falsch interpretierte, weil die Uhr zu Beginn des zweiten Bytes hoch war. Was ziemlich zweideutig ist, da das ADXL-Datenblatt im Zeitdiagramm deutlich zeigt, dass der Takt vor der Übertragung niedrig und danach niedrig ist . In dieser Konfiguration würde es nicht funktionieren. In der entgegengesetzten Taktkonfiguration, die dem Datenblatt trotzt, funktioniert es.

Die Lösung bestand darin, die Taktflanke in der Software zu invertieren :MPLABX XC8 MCC SPI-Parameter.

Ich habe das schon einmal versucht, aber es hat nichts gebracht ... wahrscheinlich ein Fall, in dem versucht wurde, zu viele Dinge zu schnell zu erledigen.

Die resultierenden MOSI und MISO (250 kHz FOSC, 62,5 kHz SPI-Rate, 1,8 V) sind:

DSO-Erfassung von MOSI und MISO von PIC zu ADXL.

Der PIC kann die korrekte Antwort 0xAD lesen. Immer noch etwas Rauschen auf MISO, bevor der ADXL die Leitung ansteuert, aber wenn dies der Fall ist, ist es sehr klar und klar.

Das Debuggen von SPI wäre ohne ein DSO unmöglich gewesen.

Ihre Frage ist viel zu lang, um sie wirklich vollständig zu lesen, aber nach einem kurzen Überfliegen scheint es, dass Sie die Slave-Select-Zeile vergessen haben. Dies muss nicht nur bestätigt werden, damit das Gerät zuhören und antworten kann, sondern es wird normalerweise auch verwendet, um den Start von Paketen zu synchronisieren. Sie können die Slave-Auswahl nicht die ganze Zeit aktiviert lassen.

Anfangs versuchte ich zu sehen, ob es niedrig bleiben könnte, um einen Pin zu speichern, und stellte fest, dass dies nicht möglich war, also musste ich auf ein uC mit ein paar weiteren Pins upgraden.