SPI - uC "empfängt" nur ein bestimmtes Byte

Gast #646030
Es sind zwei uCs miteinander verbunden (MOSI - MOSI, MISO - MISO).

Der Mega16 läuft als Master. Der Mega8 als Slave. Ein Programmchen soll 
zum Testen ein Byte '0b00110011' an den Slave schicken. Das Problem ist, 
dass ich immer nur '0bxx110101' im SPDR habe. Was an den zwei Bits xx 
steht, weiß ich nicht, da ich nur an den Pins PC0 bis PC5 den Pegel 
messen kann.

Selbst wenn der Master gar nichts gesendet hat (also direkt nach dem 
Reset) und ich den SPDR auslese, bekomme ich dieses komische Byte. Wenn 
der Master etwas sendet, ändert sich auch nichts.

Hier der Quellcode beider Programme. Die SPI-Routinen habe ich aus dem 
Datenblatt übernommen.

SLAVE
1
// SLAVE-PROGRAMM
2
#include <avr/io.h>
3

4
#define  led_1    PD6
5
#define button_1  PIND3
6

7
int main(void) {
8

9
  DDRD |= (1<<led_1);
10
  DDRC |= 0b00111111;
11
  SPI_SlaveInit();
12
    
13
  while(1) {
14

15
    if(but() == 1) {      //Sobald Taster (PD3) gedrückt,
16
      PORTD |= (1<<led_1);  //Kontroll-LED einschalten und
17
      PORTC = SPDR;      //SPDR nach PORTC schreiben.
18

19
    } else {
20
      PORTD &= ~(1<<led_1);  //Kontroll-LED aus
21
    }  
22
  }
23

24
  return 0;
25
}
26

27
int but(void) {      //Liefert '1', wenn PD3 == true
28
  
29
  int tmp;
30

31
  if(PIND & (1 <<button_1)) {
32
    tmp = 1;
33
  } else {
34
    tmp = 0;
35
  }
36

37
  return tmp;
38
}
39

40
void SPI_SlaveInit(void)
41
{
42
  /* Set MISO output, all others input */
43
  DDRB = (1<<PB4);
44

45
  /* Enable SPI */
46
  SPCR = (1<<SPE);
47
}
48

49
char SPI_SlaveReceive(void)
50
{
51
  /* Wait for reception complete */
52
  while(!(SPSR & (1<<SPIF)));
53

54
  /* Return data register */
55
  return SPDR;
56
}

MASTER
1
//MASTER-PROGRAMM
2
#include <avr/io.h>
3

4
#define  led_1    PD5
5
#define button_1  PIND2
6

7
int main(void) {
8

9
  DDRD |= (1<<led_1);
10
  DDRB |= (1<<PB4);    //SS Leitung
11
  SPI_MasterInit();
12
    
13
  while(1) {
14

15
    if(but() == 1) {          //Wenn Taster (PD2) gedrückt,
16
      PORTD |= (1<<led_1);      //Kontroll-LED einschalten.
17
      PORTB |= (1<<PB4);        //SS-Leitung auf 'high',
18
      SPI_MasterTransmit(0b00110011);  //Test-Byte senden und
19
      PORTB &= ~(1<<PB4);        //SS-Leitung wieder auf 'low'.
20

21
    } else {
22
      PORTD &= ~(1<<led_1);    //Kontroll-LED aus.
23
    }  
24
  }
25

26
  return 0;
27
}
28

29
int but(void) {      //Liefert '1', falls PD2 == true
30
  
31
  int tmp;
32

33
  if(PIND & (1 <<button_1)) {
34
    tmp = 1;
35
  } else {
36
    tmp = 0;
37
  }
38

39
  return tmp;
40
}
41

42
void SPI_MasterInit(void)
43
{
44
  /* Set MOSI and SCK output, all others input */
45
  DDRB |= (1<<PB5)|(1<<PB7);
46

47
  /* Enable SPI, Master, set clock rate fck/16 */
48
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
49
}
50

51
void SPI_MasterTransmit(char cData)
52
{
53
  /* Start transmission */
54
  SPDR = cData;
55

56
  /* Wait for transmission complete */
57
  while(!(SPSR & (1<<SPIF)));
58
}
Gast #646051
>Selbst wenn der Master gar nichts gesendet hat (also direkt nach dem
>Reset) und ich den SPDR auslese, bekomme ich dieses komische Byte.

Das liegt wohl daran das du nichts empfangen hast ;)

SLAVE
Wo benutzt du SPI_SlaveReceive(void) ?

MASTER
Vieleicht doch besser so:

      PORTB &= ~(1<<PB4);        //SS-Leitung wieder auf 'low'.
      SPI_MasterTransmit(0b00110011);  //Test-Byte senden und
      PORTB |= (1<<PB4);        //SS-Leitung auf 'high',
Gast #646060
>MOSI gehört an MISO, und MISO an MOSI

Bist du sicher ? Darauf bin ich auch schon mal reingefallen.
Blockschaltbild im Datenblatt ansehen ! MOSI auf MOSI, MISO auf MISO
ist hier richtig.
Gast #646082
>SLAVE
>Wo benutzt du SPI_SlaveReceive(void) ?
>
>MASTER
>Vieleicht doch besser so:
>
>      PORTB &= ~(1<<PB4);        //SS-Leitung wieder auf 'low'.
>      SPI_MasterTransmit(0b00110011);  //Test-Byte senden und
>      PORTB |= (1<<PB4);        //SS-Leitung auf 'high',

Aha, danke! Jetzt geht es.
Gast #678833
eine verständnisfrage zu diesem spi-slave-beispiel , wie kommt der 
anwender zu dieser routine : char SPI_SlaveReceive(void) , ich sehe kein 
aufruf?

// SLAVE-PROGRAMM
#include <avr/io.h>

#define  led_1    PD6
#define button_1  PIND3

int main(void) {

  DDRD |= (1<<led_1);
  DDRC |= 0b00111111;
  SPI_SlaveInit();

  while(1) {

    if(but() == 1) {      //Sobald Taster (PD3) gedrückt,
      PORTD |= (1<<led_1);  //Kontroll-LED einschalten und
      PORTC = SPDR;      //SPDR nach PORTC schreiben.

    } else {
      PORTD &= ~(1<<led_1);  //Kontroll-LED aus
    }
  }

  return 0;
}

int but(void) {      //Liefert '1', wenn PD3 == true

  int tmp;

  if(PIND & (1 <<button_1)) {
    tmp = 1;
  } else {
    tmp = 0;
  }

  return tmp;
}

void SPI_SlaveInit(void)
{
  /* Set MISO output, all others input */
  DDRB = (1<<PB4);

  /* Enable SPI */
  SPCR = (1<<SPE);
}

char SPI_SlaveReceive(void)
{
  /* Wait for reception complete */
  while(!(SPSR & (1<<SPIF)));

  /* Return data register */
  return SPDR;
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 19 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.