Einfache Zweidraht-SPI-Kommunikation zwischen zwei PIC24s

Ich versuche, eine einfache SPI-Kommunikation von 16-Bit-Daten von einem PIC24FJ64GA002 zu einem anderen desselben Mikrocontrollers zu erreichen. Indem ich dem Datenblatt bis ins kleinste Detail folgte, schrieb ich den Sender- und Empfängercode wie folgt:

Sender:

unsigned int i = 0;

void main()
{
    RPOR2bits.RP4R = 7;  // Data out through Peripheral Pin 4
    RPOR2bits.RP5R = 8;  // Clock out  through Peripheral Pin 5
    SPI1CON1bits.MODE16 = 1; //16 bit mode 
    SPI1CON1bits.MSTEN = 1;  // Master enable
    SPI1CON1bits.SSEN = 0; //No slave selection
    SPI1STATbits.SPIROV = 0; //Receiver Overflow cleared as told in datasheet
    SPI1STATbits.SPIEN = 1; //SPI is enabled
    while (1)
    {
        while (SPI1STATbits.SPITBF); //Waiting for any transmission to complete
        SPI1BUF = i; // Data is written
        i++
    }
}

Empfänger:

unsigned int i;

void main()
{
    RPINR20bits.SDI1R = 0; //Data in through Peripheral pin 0
    RPINR20bits.SCK1R = 2; //Clock in through Peripheral pin 2
    AD1PCFG = 0xFFFF;
    TRISA = 0x0000;
    SPI1CON1bits.MODE16 = 1;
    SPI1CON1bits.MSTEN = 0; // Slave mode
    SPI1CON1bits.SSEN = 0;
    SPI1CON1bits.SMP = 0; //Must be cleared in slave mode as told in datasheet
    SPI1CON1bits.DISSDO = 1; //Receiver only receives data
    SPI1STATbits.SPIROV = 0;
    SPI1STATbits.SPIEN = 1;

    while (1)
    {
        while (!SPI1STATbits.SPIRBF); //waiting for receive to complete
        LATA = SPI1BUF; // pushing Received data onto A
    }
}

Der Sender scheint die Daten zu übertragen (Takt- und Datenleitungen zeigen erwartete Zyklen), aber aus irgendeinem Grund empfängt der Empfänger die Daten nicht und schiebt sie auf A-Anschlüsse.

Die Konfigurationseinstellungen für beide Mikrocontroller sind:

Primary Oscillator Select: Primary Oscillator Disabled 
I2c1 Pin Location Select: Use default SCL 1/SDA 1 pins 
IOLOCK Protection: Disabled 
OSCO Pin Configuration: OSCO functions as port I/O 
Clock Switching and Monitor: Clock switching is enabled, Fail-safe Clock Monitor is enabled 
Oscillator Select: Fast RC Oscillator (FRC) 
Sec Oscillator Select: Default Secondary Oscillator (SOSC) 
Wake-up timer Select: Legacy Wake-up Timer 
Internal External Switch Over Mode: Disabled
External Watchdog Timer Postscaler: 1:32,768
WDT Prescalar: Prescaler ratio of 1:128 
Watchdog Timer Window: Disabled 
Watchdog Timer Enable: Disabled 
Comm Channel Select: Emulator EMUC1/EMUD1 pins are shared with PGC1/PGD1 
Background Debug: Disabled 
General Code Segment Write Protect: Disabled 
General Code Segment Code Protect: Disabled 
JTAG Port Enable: Disabled

Die einzigen zwei Verbindungen sind die Takt- und Datenleitungen von den jeweiligen Peripheriestiften. Was ist hier das Problem und wie erhält man die Daten?

Es scheint unmöglich, dass dies tatsächlich funktioniert, hat das jemals jemand erreicht?

Überprüfen Sie, ob die SPI-Chipauswahl auf logisch 1 hochgezogen und während der Kommunikation korrekt auf 0 gesetzt wird.
@Oliver Wenn Sie Slave Select meinen, habe ich es deaktiviert, indem ich SPI1CON1bits.SSEN=0 angegeben habe; (was Standard ist), aber es löst das Problem immer noch nicht.
Ich meinte Sklavenauswahl, ja. Jedes Gerät hat einen eigenen Namen dafür. Ich sehe, dass der Master so eingestellt ist, dass er kein SS/CS-Signal ausgibt, ist der Slave auch so eingestellt, dass er es nicht erwartet? Und mit welcher Geschwindigkeit läuft der SPI? Haben Sie die Daten- und Taktleitungen untersucht, um zu sehen, wie sie aussehen?
Ja die Zeile SPI1CON1bits.SSEN=0; Das spezifische Deaktivieren der Chipauswahl ist sowohl in den Sender- als auch in den Empfängercode geschrieben. Es hilft immer noch nicht. Die Preskalar-Einstellung wird auf den Standardwerten belassen, sodass der sekundäre Preskalar 8:1 und der primäre 64:1 beträgt und unter Verwendung des internen FRC-Oszillators bei 10 MHz läuft. Alles wird auf seinen Standardwerten belassen, weil ich den einfachsten SPI-Code möchte, funktioniert es leider nicht. Die Senderausgabe ist (durch die ausgegebenen Wellenformen) konsistent. Der Empfänger kann diese Daten nicht empfangen oder in den Ausgangsport übertragen.
Welche Zeile ist das im Empfängercode? Um nicht auf den Punkt zu kommen, aber ich kann nicht sehen, wo SS im Empfangscode deaktiviert ist.
Nein, ich habe es jetzt hinzugefügt, um zu sehen, ob es etwas ändert, aber es tut es nicht.
Schade, wäre eine einfache Lösung gewesen. Können Sie die Ausgangswellenformen auf einem Osziloskop sehen (Zugriff darauf haben)?
In jedem Fall sind alle Bitwerte standardmäßig 0, sofern nicht oder anders angegeben, richtig? Nun, ich übertrage 0 und die Datenleitung bleibt niedrig und für alle anderen Werte die erwarteten Wellenformen. Die Schaltung hat in der Simulation noch nicht funktioniert, also habe ich sie noch nicht auf die Hardware gebracht. Ich benutze Proteus und es war immer ziemlich genau.
@Oliver Ich bin neu bei Stackexchange und weiß nicht, ob dies akzeptabel ist, aber wenn Sie möchten, kann ich Ihnen das gesamte Mikro C-Programm zusammen mit der Simulationsdatei senden. Es könnte Dinge geben, die wichtig sind, die ich hier nicht gesagt habe.
Ich denke, Ihr Problem ist der SS-Pin. Ohne sie bekommt der Slave die Daten in sein Schieberegister, aber er überträgt sie nicht zum FIFO.
@Alex Ich habe SSEN sowohl im Empfänger als auch im Sender auf 1 geändert. Diese Zeile zum Sender hinzugefügt: RPOR1bits.RP3R =9; und zum Empfänger: RPINR21bits.SS1R=1; Ich habe RP3 des Senders mit RP1 des Empfängers verbunden und die Leitung ist überhaupt nicht aktiv (Proteus zeigt eine aktive Leitung entweder als hoch oder niedrig an) und die Kommunikation findet auch nicht statt.
Kann mir jemand einen Beispiel-SPI-Code mailen, der die Kommunikation zwischen 2 PIC24-Mikrocontrollern ermöglicht? Es scheint keine Referenz zu geben, auf die ich mich beziehen könnte. hp07@india.com
Beim Durchsehen des Codes bemerke ich, dass ein "!" in der While-Anweisung des Empfängers, die in der While-Anweisung des Senders nicht gefunden wird.
@Guill Nun, es hängt von der Art des Bits ab. Im Fall des Senders wird das Bit gelöscht, nachdem die Übertragung abgeschlossen ist, während in einem Empfänger das Bit gesetzt wird, nachdem der Empfang abgeschlossen ist.
@Harsha: Ich empfehle, den Debug-Code wie folgt zwischen die Anweisungen while und LATA einzufügen: - Nachricht anzeigen ("Daten lesen, zum Fortfahren die Tabulatortaste drücken") - warten (für die Tabulatortaste).
Wenn die Meldung angezeigt wird, funktioniert die While-Anweisung einwandfrei!
@Guill wie genau kann ich den Debug-Code in MikroC hinzufügen? Und ich verstehe nicht, was du mit Tab meinst.
Wenn Sie keine Slave-Auswahlleitung verwenden, müssen Sie entweder eine zeit- oder datenbasierte Methode zur Erkennung des Beginns einer neuen Übertragung einbauen, um eine Synchronisierung zu erreichen. Andernfalls hängt Ihr System von der Startreihenfolge ab und hat nach einer Fehlsynchronisierung keine Möglichkeit, dies zu korrigieren.

Antworten (1)

Sie weisen Peripheriegeräten falsche Pins zu. Es reicht nicht aus, das Bit einfach zu setzen, Sie müssen mindestens einmal eine Entsperrsequenz befolgen, und es wird empfohlen, das Register zu sperren, nachdem Sie mit der Zuweisung fertig sind. Die nützlichen Makros sind in 'pps.h' enthalten, der Code sieht so aus (für UART2):

PPSUnLock;
PPSOutput( PPS_RP21, PPS_U2TX );
PPSInput( PPS_U2RX, PPS_RP26 );

Die ganze C-Datei kann hier eingesehen werden -> https://github.com/felis/cdb/blob/master/fw/minimal/bsp.c#L185

Wenn das das Problem wäre, würde es überhaupt keine Übertragung geben, aber es gibt Änderungen, die in der Ausgabe auftreten, und auch die erste Übertragung erfolgt erfolgreich.