mikrocontroller.net

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


Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
// 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;
}

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

#define  led_1    PD5
#define button_1  PIND2

int main(void) {

  DDRD |= (1<<led_1);
  DDRB |= (1<<PB4);    //SS Leitung
  SPI_MasterInit();
    
  while(1) {

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

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

  return 0;
}

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

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

  return tmp;
}

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

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

void SPI_MasterTransmit(char cData)
{
  /* Start transmission */
  SPDR = cData;

  /* Wait for transmission complete */
  while(!(SPSR & (1<<SPIF)));
}

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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',

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
MOSI gehört an MISO, und MISO an MOSI

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Maxim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: roboterheld (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
}

Autor: roboterheld (Gast)
Datum:

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

mfg

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.