Forum: Mikrocontroller und Digitale Elektronik Hardware SPI Fragen


von Paul F. (zwanzischmark)


Lesenswert?

hallo,
ich habe versucht möglichst viele der 16 Seiten mit SPI Themen zu lesen 
und habe dort auch einige Seiten gefunden wo SPI allgemein gut erklärt 
ist, aber mir fehlt noch immer ein gut erklärtes C-Programmbeispiel.

Aus dem Datenblatt habe ich den folgenden code:
(nur die Zeile "DDRB = (1<<PB5)|(1<<PB7);" angepasst)

ATMEGA 644P
1
void SPI_MasterInit(void)
2
{
3
/* Set MOSI and SCK output, all others input */
4
DDRB = (1<<PB5)|(1<<PB7);
5
/* Enable SPI, Master, set clock rate fck/16 */
6
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
7
}
8
9
void SPI_MasterTransmit(char cData)
10
{
11
/* Start transmission */
12
SPDR = cData;
13
/* Wait for transmission complete */
14
while(!(SPSR & (1<<SPIF)));
15
}

also rufe ich einmal
1
SPI_MasterInit();
 zum initialisieren des Hardware SPI auf und kann dann mit z.B.
1
SPI_MasterTransmit(0xFF);
 ein byte senden.
Ist das korrekt soweit?

der Slave richtet sich nach dem Takt den der Master vorgibt?

der Master gibt die Daten auch aus wenn nichts angeschlossen ist?

von Paul F. (zwanzischmark)


Lesenswert?

so, ich füge jetzt mal den code von master und slave an, vielleicht 
schaut mal einer drüber:

Master:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
void SPI_MasterInit(void) {
5
  /* Set MOSI and SCK output, all others input */
6
  DDRB = (1<<PB5)|(1<<PB7);
7
  /* Enable SPI, Master, set clock rate fck/16 */
8
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
9
}
10
11
void SPI_MasterTransmit(char cData) {
12
  /* Start transmission */
13
  SPDR = cData;
14
  /* Wait for transmission complete */
15
  while(!(SPSR & (1<<SPIF)));
16
}
17
18
int main (void) {
19
20
  SPI_MasterInit();
21
  while(1) {
22
    SPI_MasterTransmit(0xFF);
23
    _delay_ms(200);
24
    SPI_MasterTransmit(0x00);
25
    _delay_ms(200);
26
  }
27
28
  return 0;
29
}


Slave:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
void SPI_SlaveInit(void) {
5
  /* Set MISO output, all others input */
6
  DDRB = (1<<PB6);
7
  /* Enable SPI */
8
  SPCR = (1<<SPE);
9
}
10
11
12
char SPI_SlaveReceive(void) {
13
  /* Wait for reception complete */
14
  while(!(SPSR & (1<<SPIF)));
15
  /* Return Data Register */
16
  return SPDR;
17
}
18
19
20
int main (void) {
21
22
  DDRD = 0xFF;
23
  SPI_SlaveInit();
24
  while(1) {
25
    PORTD = SPI_SlaveReceive();
26
  }
27
  return 0;
28
}

von JÜrgen G. (Firma: 4CKnowLedge) (psicom) Benutzerseite


Lesenswert?

Hast du das Kapitel über /SS gelesen?

von Paul F. (zwanzischmark)


Lesenswert?

ja, sorry... hatte ich nicht erwähnt, /SS hab ich am Slave einfach an 
GND gelegt, oder ist /SS zwingend erforderlich zur syncronisation?

Es soll ja einfach PortD am Slave im 200ms Abstand getoggelt werden. 
Dazu hab ich natürlich simplerweise eine LED dran. Die LED geht auch an, 
allerdings nicht mehr aus!

Sind denn die Programme so richtig?

von Udo (Gast)


Lesenswert?

Hallo,

wenn du in der Senderoutine 2 Byte sendest, solltest du auch 2x die 
Bytes auslesen:
1
int main (void) {
2
3
  DDRD = 0xFF;
4
  SPI_SlaveInit();
5
  while(1) {
6
    PORTD = SPI_SlaveReceive();
7
    _delay_ms(200);
8
    PORTD = SPI_SlaveReceive();
9
  }
10
  return 0;
11
}

Gruß
Udo

von Paul F. (zwanzischmark)


Lesenswert?

hm? ist doch in ner Schleife, also wird ständig ausgelesen...

ist ja nur ein testprogramm...

komischerweise geht es jetzt, obwohl ich nichts geändert hab :/

von Udo (Gast)


Lesenswert?

Ups, sorry, hab die Schleife überlesen.....

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.