Forum: Mikrocontroller und Digitale Elektronik PIC SPI-Receive liefert immer null


von Student (Gast)


Lesenswert?

Hallo,

ich nutze gerade das erste Mal den SPI Modus des MSSP eines PIC18F.

Testweise wird ein Register des (Slave-) Chips beschrieben und dann 
wieder ausgelesen. Auf dem Oszi sieht das ganze auch gut aus (Befehl 
wird empfangen und es wird korrekt geantwortet).

In der Software allerdings gibt mir meine SPI-receive Funktion immer 
0x00 zurück. Mir gehen mittlerweile die Ideen aus, an welchen Stellen 
ich weiter nach Fehlern suchen sollte.

Ich habe bereits folgendes probiert:

- SPI Modus von 0 auf 1 geändert (2 und 3 lassen sich ausschließen)
- PPS geprüft; die Anschlusszuordnungen sind korrekt

-> Im Datenblatt wird angedeutet, dass es einen Unterschied zwischen 
Senden und Empfangen gibt, allerdings finde ich keine Möglichkeit ein 
Empfangen anzustoßen ohne Dummy-Daten zu senden.

Ich hoffe ihr könnt mir helfen :).
1
void main()
2
{
3
  [...]
4
    SRAM_CS = 0;
5
    spi_transmit(0x05); // Read Mode Register
6
    uint8_t mode_register = spi_receive();
7
    SRAM_CS = 1;
8
  [...]
9
}
1
uint8_t __inline spi_receive() // <-- liefert immer null?!
2
{
3
    SSP2BUF = 0x00;// transmit dummy data
4
    while(!SSP2IF)
5
        ;
6
    SSP2IF = 0;
7
    return SSP2BUF;
8
}

von volksvorg (Gast)


Lesenswert?

Bräuchten ein paar mehr Infos.
Init der SPI.
Init der GPIO. Klassiker hast du auch die entsprechenden GPIO Pins als 
Ausgang bzw. als Eingang konfiguriert. ?
Ist der uC SPI Master oder Slave. Was für ein Chip hängt als Slave am 
SPI-Bus ?

von Jim M. (turboj)


Lesenswert?

Wie sieht spi_transmit() aus? Ich frage das, weil SPI gerne mal einen 
FIFO hat und Du dann in spi_receive() ein "altes" Bye lesen würdest.

von Student (Gast)


Lesenswert?

Der Chip wird im Master Mode betrieben. Es soll ein SRAM (23LC1024) 
angesteuert werden.

volksvorg schrieb:
> Init der SPI.
1
void spi_init(uint8_t spi_mode)
2
{
3
    SSP2STATbits.CKE = !(spi_mode       & 0x01);
4
    SSP2STATbits.SMP =  (spi_mode >> 1) & 0x01;
5
    
6
    SSP2CON1 |= 0x02; // Mode: SPI Master; Clock = Fosc/64
7
    SSP2CON1 |= _BS(5); // Enable MSSP2
8
}


volksvorg schrieb:
> Init der GPIO.
1
/* MSSP2 SPI */    
2
    LATB  &= ~ _BS(2); // Idle Level: Low
3
    TRISB &= ~ _BS(2); // SPI_CLOCK Output
4
    TRISB &= ~ _BS(3); // SPI_SO Output
5
    TRISB |=   _BS(1); // SPI_SI Input
6
    LATB  |=   _BS(0); // SPI_CS = High (unselect slave)
7
    TRISB &= ~ _BS(0); // SPI_CS Output

SPI Transmit sieht folgendermaßen aus:
1
void __inline spi_transmit(uint8_t data)
2
{
3
    SSP2BUF = data;
4
    while(!SSP2IF)
5
        ;
6
    SSP2IF = 0;
7
    // Read SSP2BUF to clear the Buffer Full (BF) Bit
8
    uint8_t trash_data = SSP2BUF;
9
}

Das mit dem FIFO gucke ich mir gleich nochmal an. Danke :).

von Student (Gast)


Lesenswert?

Habe folgendes vergessen:

spi_init() wird folgendermaßen aufgerufen
1
spi_init(0x00);

von volksvorg (Gast)


Lesenswert?

Wie hast du Chip Select gelöst? Ist eine weile her das ich mit PICs 
gearbeitet habe. Generell Vor dem Lesen muss CS HIGH sein. Um lesen zu 
können ziehst du CS auf LOW sendest vom Master Dummy Daten und zwar 
solange du Daten lesen möchtest. Und wenn du fertig bist ziehst du CS 
wieder auf HIGH. Z.B. Datenwort 16Bit. und du möchtest 1 Datenwort 
einlesen.
1
CS auf LOW. 
2
3
SPI_recieve();
4
5
CS auf HIGH

bei Zwei Datenworte
1
CS auf LOW. 
2
3
SPI_recieve();
4
SPI_recieve();
5
6
CS auf HIGH

usw.

von Student (Gast)


Lesenswert?

Guten Abend,

danke für die Hinweise. Es gibt aber kein Problem mit dem Empfangen an 
sich.

Der Chip sendet als Antwort auf den Lese-Befehl 0x80. Der PIC liefert 
als empfangenen Wert aber immer 0x00 (anstatt 0x80), unabhängig von den 
(laut Oszi) tatsächlich empfangenen Daten.

von Volker S. (vloki)


Lesenswert?

Der unbekannte PIC hat auf dem Pin für den SPI Eingang eine 
Analogfunktion, die nicht deaktiviert wurde?

So, oder ähnlich...
1
ANSELBbits.ANSB2 = 0;

: Bearbeitet durch User
von Student (Gast)


Lesenswert?

Volker S. schrieb:
> Der unbekannte PIC hat auf dem Pin für den SPI Eingang eine
> Analogfunktion, die nicht deaktiviert wurde?
>
> So, oder ähnlich...ANSELBbits.ANSB2 = 0;

Gute Idee, leider ist das die richtige Lösung.

Das dürfte aber eigentlich nicht der Fall sein, denn ich habe alle 
Analogen Eingänge deaktiviert:
1
[Etwas über dem I/O-Setup vom MSSP2]
2
/* Disable ALL analog functions */
3
    ANCON0 = 0xFF;
4
    ANCON1 = 0x1F;

Ich habe einfach mal hinter der Init-Routine einen Breakpoint gesetzt 
und nachgesehen was in den ANCONx Registern drinsteht. Es sind nicht die 
obigen Werte. Nach etwas gesuche habe ich festgestellt, dass ein 
Programmteil diese Werte (falsch) neu schreibt. Wow. Ich stell mich dann 
mal in die Ecke.

danke :D

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.