Forum: Mikrocontroller und Digitale Elektronik PIC18F26Q43 SPI slave empfängt keine Daten


von Tobias S. (herrgesangsverein)


Lesenswert?

Hallo,

ich möchte einen PIC18F26Q43 als PSI slave im Vollduplex betreiben. 
Dieser hat das neuere SPI Modul mit TX und RX FIFO. Leider empfängt der 
Slave keine Daten. Wahrscheinlich konfiguriere ich das Modul falsch.

Ich nutze "Start of SS", um den Transfer vorzubereiten und "end of SS", 
um den Transfer abzuschließen. Dieser Teil funktioniert, d. h. die 
Interrupt Routine wird zumindest angesprungen. Ich sehe am Oszi, dass 
Clock und Daten übertragen werden. Die RX-Abfrage in der Interrupt 
Routine wird aber nicht angesprungen. Entweder empfange ich CLK nicht 
richtig oder SDI. Dass die Leitungen am richtigen Pin liegen, habe ich 
mehrmals überprüft. Ich benutze nicht die Standard-Pins, sondern 
verbiege diese auf RB2-RB4 mit dem PPS.

Hat jemand einen SPI Slave Beispiel für das neue Modul?

Hier die Konfiguration:
1
void spiInit() {
2
    spiTransferComplete=0;
3
    
4
    // Chip not ready
5
    CR=1;
6
    
7
    // clear EN 
8
    SPI1CON0bits.EN=0;
9
    // Set PPS     
10
    SPI1SSPPS=0b00000110; // SS  RA6 > Chip select input            
11
    SPI1SCKPPS=0b00001010; // SCK > RB2
12
    SPI1SDIPPS=0b00001011; // SDI > RB3
13
    RB4PPS=0x32; // SDO > RB4 
14
    TRISB2=1;
15
    TRISB3=1;    
16
    
17
    SPI1CON0=0b00000000; // EN=0, LSBF=0, MST=0, BMODE=0
18
    SPI1CON1=0b00000100; // SMP=0, CKE=0, CKP=0, SSP=1, SDI=0, SDO=0
19
    SPI1CON2=0b00000011; // SSET=0, TXR=1, RXR=1
20
    
21
    // Interrupts
22
    SPI1INTEbits.SOSIE=1;
23
    SPI1INTEbits.EOSIE=1;
24
 
25
    // SPI1INTEbits.RXOIE=1; // overflow test
26
    
27
    PIE3bits.SPI1IE=1;
28
    PIE3bits.SPI1RXIE=1;
29
    PIE3bits.SPI1TXIE=1;
30
    
31
    // enable EN 
32
    SPI1CON0bits.EN=1;
33
}

und hier die Interrupt-Routine:
1
void spiInterruptHandler() {
2
    char test;
3
    // Start SS
4
    if (SPI1INTEbits.SPI1SOSIE==1 && SPI1INTFbits.SPI1SOSIF==1) {
5
        switchSpiBuffer(); // prepare sending
6
        
7
        spiSendCsr=1;
8
        spiRecvCsr=0; 
9
        
10
        spiRecv.pck.U1len=0;
11
        spiRecv.pck.U2len=0;
12
        spiRecv.pck.U3len=0;
13
        spiRecv.pck.U4len=0;
14
        
15
        SPI1TXB=spiSend->cBuf[spiSendCsr]; // preload first byte
16
        CR=0;   // ready to send
17
        SPI1INTFbits.SPI1SOSIF=0;
18
    }
19
    
20
    // end of SS
21
    if (SPI1INTEbits.SPI1EOSIE==1 && SPI1INTFbits.SPI1EOSIF==1) {
22
        CR=1;
23
        if (spiTransferComplete)
24
            spiTransferComplete(&(spiRecv.pck));
25
        SPI1INTFbits.SPI1EOSIF=0;
26
    }
27
    if (SPI1INTFbits.RXOIF) {
28
        test=1;
29
    }
30
    // byte received
31
    if (PIR3bits.SPI1RXIF==1) {
32
        spiRecv.cBuf[spiRecvCsr++]=SPI1RXB;
33
    }
34
    
35
    // byte sent
36
    if (PIR3bits.SPI1TXIF==1) {
37
        SPI1TXB=spiSend->cBuf[spiSendCsr++];
38
    }    
39
}

von Franko P. (sgssn)


Lesenswert?

Servus
hast du Erfahrung mit der PPS-Sache? Ich hab da immer so meine 
Schwierigkeiten. Notfalls würd ich da das Microchip-Forum konsultieren.
Gruß
gerhard

von Tobias S. (herrgesangsverein)


Lesenswert?

Insgesamt ein tolles Feature. Auf die Art kann ich in einem 28pin device 
4 uarts und SPI nutzen. (naja, wenn es mal klappt).

Ich denke schon, dass ich es begriffen habe. Ich versuche mal, es mit 
meinen Worten zu erläutern: dem funktionalen Bezeichner z. B. SPI1SCKPPS 
wird ein Port in 8 Bit codiert zugewiesen. 0b00XXXYYY, wobei XXX: 
000=Port A, 001=B, 010=C und YYY=0..7 die Pin-Nummer ist. Dabei ist zu 
beachten, dass nicht jede
Funktion auf jeden Port gelegt werden kann. Laut Tabelle kann Port B für 
SDI verwendet werden.

SPI1SSPPS=0b00000110; // 000=A, 110=6 SS  RA6 > Chip select input

Umgekehrt finde ich schwieriger: RxyPPS ist ein Port Pin, Port x, Pin y. 
Diesem Bezeichner wird eine Funktion aus der Tabelle zugewiesen in Form 
eines Hexwerts. DIese haben m. E. keine Systematik. Man sie aus der 
Tabelle ablesen. Man korrigiere mich, wenn ich es falsch wiedergegeben 
habe.

RB4PPS=0x32; PortB4 soll SDO sein. Die Senderichtung habe ich allerdings 
noch nicht getestet. Ich scheitere noch am Empfange:n allerdings hat es 
mit SS geklappt, denn die Interrupt Routine reagiert darauf.

Bzgl. Microchip Forum ich warte noch auf die Bestätigung meiner 
Registrierung.

von Pic16 (Gast)


Lesenswert?

TRISA6 für /cs richtig gesetzt?

von Pic16 (Gast)


Lesenswert?

Tobias S. schrieb:
> allerdings hat es mit SS geklappt, denn die Interrupt Routine reagiert
> darauf.

Glatt überlesen

von neuer PIC Freund (Gast)


Lesenswert?

Ohne Lock/Unlock tut sich bei mir nix. Ist allerdings für einen anderen 
PIC.
1
    PPSLOCK = 0x55;
2
    PPSLOCK = 0xAA;
3
    PPSLOCKbits.PPSLOCKED = 0b0;
4
5
    RC1PPS = 0b10100;               // = Rxy source is TX/CK(1)
6
    ...
7
8
    PPSLOCK = 0x55;
9
    PPSLOCK = 0xAA;
10
    PPSLOCKbits.PPSLOCKED = 0b1;

von Tobias S. (herrgesangsverein)


Lesenswert?

neuer PIC Freund schrieb im Beitrag #6581774:
> Ohne Lock/Unlock tut sich bei mir nix.

Das ist eine gute Idee, denn darauf habe ich überhaupt nicht geachtet.
Ich habe das gleich ausprobiert. Zumindest den unlock-Teil. Leider 
ändert das nichts.

von neuer PIC Freund (Gast)


Lesenswert?

O.K. Dieser Typ ist anscheinend ab Reset unlocked.

Vielleicht ein Klassiker: ANSEL auch gelöscht?

von Tobias S. (herrgesangsverein)


Lesenswert?

neuer PIC Freund schrieb im Beitrag #6582056:
> O.K. Dieser Typ ist anscheinend ab Reset unlocked.
>
> Vielleicht ein Klassiker: ANSEL auch gelöscht?

Tatsächlich: Der Klassiker. Ich hatte die Konfiguration mit dem MCC-Pin 
Grid angelegt und erwartet, dass er damit auch ANSEL löscht. Hat in 
anderen Fällen auch geklappt. Hier aber nicht. Ich musste die 
entsprechenden ANSELs händisch löschen.

Danke

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.