Forum: Mikrocontroller und Digitale Elektronik Brauche Hilfe bei SPI


von Dshing S. (dshing)


Lesenswert?

Hi, ich will mehrere µC mit einander kommunizieren lassen, und dazu 
dachte ich mir nehme ich das SPI, aber leider finde ich nirgends eine 
gute Erklärung, wie man das programmiert.
Ich hab jetzt versucht für den Anfang einfach nur einen Atmega88 und 
einen Atmega168 zu verbinden und eine zahl zu übergeben. Leider ohne 
Erfolg.

Verdrahtet habe ich angekreuzt und ohne irgendwelche Widerstände o.ä. 
dazwischen, also:

SCK--SCK
MOSI--MOSI
MISO--MISO
SS--SS

Hier meine Code Versuche:

Master:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
#define DDR_SPI DDRB
6
#define DD_MOSI PB3
7
#define DD_SCK PB5
8
#define DD_SS PB2
9
10
void SPI_MasterInit(void)
11
{
12
//Set MOSI and SCK output, all others input 
13
 DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);
14
// Enable SPI, Master, set clock rate fck/128 
15
SPCR = (1<<SPE)|(1<<MSTR) |(1<<SPR0)|(1<<SPR1);
16
}
17
void SPI_MasterTransmit(uint8_t cData)
18
{
19
// Start transmission 
20
SPDR = cData;
21
// Wait for transmission complete
22
while(!(SPSR & (1<<SPIF)));
23
}
24
25
int main(void)
26
{
27
  SPI_MasterInit();
28
  DDRB = (1 << PB0);
29
  
30
    while(1)
31
    {
32
    _delay_ms(500);
33
        SPI_MasterTransmit(3);
34
    }
35
}

Slave:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <avr/interrupt.h>
4
5
6
#define DDR_SPI DDRB
7
#define DD_MISO PB4
8
9
void SPI_SlaveInit(void)
10
{
11
// Set MISO output, all others input 
12
DDR_SPI = (1<<DD_MISO);
13
// Enable SPI 
14
SPCR = (1<<SPE);
15
}
16
17
uint8_t SPI_SlaveReceive(void)
18
{
19
// Wait for reception complete 
20
while(!(SPSR & (1<<SPIF)))
21
;
22
// Return Data Register 
23
return SPDR;
24
}
25
26
int main(void)
27
{
28
  DDRC = (1 << PC4)|(1 << PC5);
29
  SPI_SlaveInit();
30
  
31
    while(1)
32
    {
33
        if ((SPSR & (1<<SPIF)))
34
        {
35
      PORTC ^= (1<<PC5);
36
        }
37
    }
38
}

Es sollte eigentlich direkt nach dem Start eine an den Port PC5 
angeschlossenen LED anfangen zu blinken, wenn es funktionieren würde.

Könnt ihr mir sagen was ich falsch mache? Oder wonach ich gucken soll?
Komme echt nicht mehr weiter.

von Martin M. (capiman)


Lesenswert?

Dshing Sung schrieb:
> Oder wonach ich gucken soll?

Hast Du schon mal geprüft, ob Takte auf SCK zu sehen sind?
Hast Du schon mal geprüft, ob Sendedaten vom Master gesendet werden?
Wenn eines davon nicht da ist, steckt der Fehler vermutlich im Master...
Wenn beides da ist, dann steckt der Fehler vermutlich im Slave
oder die beiden uC verstehen sich nicht, oder Master spricht zu 
schnell...

Hast Du einen Logic Analyzer  Oszi  TTL-Prüfstift / eine LED?
Dann einfach mal die 3 Leitungen ansehen...

GND zwischen den beiden uC hast Du hoffentlich auch verbunden?

von Timmo H. (masterfx)


Lesenswert?

Code sieht soweit richtig aus, aber setze beim Master den SS mal manuell 
vorm Transmit, dann sollte es klappen.

also:
1
while(1)
2
{
3
    _delay_ms(500);
4
    PORTB &= ~(1<<PB2);
5
    SPI_MasterTransmit(3);
6
    PORTB |= (1<<PB2);
7
}

von Dshing S. (dshing)


Lesenswert?

Hallo und danke schon mal für die Anttworten,
also ich hab jetzt beim Master die Hauptschleife wie folgt geändert:
1
    while(1)
2
    {
3
    _delay_ms(500);
4
    PORTB &= ~(1<<PB2);
5
    SPI_MasterTransmit(3);
6
    PORTB |= (1<<PB2);
7
  PORTB ^= (1<<PB0);
8
    }
Also manuell die SS Leitung beschaltet und eine "Prozess LED" um zusehen 
ob er überhaupt was macht, oder sich irgendwo aufhängt.

Das Resultat ist, das die "Prozess LED" erst blinkte, wenn ich ein 10kΩ 
Wiederstand von SS gegen Masse schalte.

Dann hab ich eine anderen LED je von SCK,MISO,MOSI,SS gegen Masse 
schauen wollen ob sich da was tut. Resultat ist, das bei MISO,MOSI,SS 
gar nichts passier, bei SCK, dann aber der Master wieder hängen 
bleibt("Prozess LED" bleibt permanent an).

Dann hab ich mit meiner Soundkarte vom PC versucht noch mal versucht ein 
Oszilloskop zu imitieren, was nur minder geeignet ist, aber damit hab 
ich an der SS Leitung eine Puls-Spannung gemessen, die ca 0.5V beträgt 
und mit ca. 150ms pulst. bei den anderen passiert das gleiche wie mit 
einer LED

Also jetzt bin ich noch verwirrter als ich es vorher war ^^

von ./. (Gast)


Lesenswert?

MOSI und MISO müssen gekreuzt werden.

von ./. (Gast)


Lesenswert?

Nee, stimmt gar nicht. Sorry.

von ./. (Gast)


Lesenswert?

Du überschreibt DDRB:
1
SPI_MasterInit();
2
DDRB = (1 << PB0);

Sollte vielleicht
1
DDRB |= (1 << PB0);

sein.

von Dshing S. (dshing)


Lesenswert?

Jahwohl XD
Das war's :D
Solche blöden Fehler sehe ich immer irgendwie nicht :(

Aber jetzt funktioniert es ja dank euch :)

Hoffe den Rest bekomme ich allein hin.
Danke noch mal!

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.