Forum: Mikrocontroller und Digitale Elektronik SPI - uC "empfängt" nur ein bestimmtes Byte


von Maxim (Gast)


Lesenswert?

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
}

von holger (Gast)


Lesenswert?

>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',

von Matthias (Gast)


Lesenswert?

MOSI gehört an MISO, und MISO an MOSI

von holger (Gast)


Lesenswert?

>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.

von Simon K. (simon) Benutzerseite


Lesenswert?

Matthias wrote:
> MOSI gehört an MISO, und MISO an MOSI

QUATSCH.

Master-In-Slave-Out kommt natürlich ebenfalls wieder an 
Master-In-Slave-Out. resp. MOSI.

von Maxim (Gast)


Lesenswert?

>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.

von roboterheld (Gast)


Lesenswert?

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;
}

von roboterheld (Gast)


Lesenswert?

wie soll es gehen : char SPI_SlaveReceive(void)....Aha, danke! Jetzt 
geht es.

mfg

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.