mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik SPI Slave Receive


Autor: Deyn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo

Wir wollen Daten per SPI von einem ATMega88 zu einem anderen ATMega88 
schicken.

Wir verwenden folgenden Code:

SIGNAL (SIG_SPI)
{
  received_character = SPDR;
}

void SPI_SlaveInit (void)
{
  DDRB |= (1<<PB4);
  SPCR = (1<<SPE) | (1<<SPIE) | (1<<SPR0);
}

Beim Simulieren springt er auch nach dem setzen der SPI Interrupt Flag 
in SIGNAL (SIG_SPI) nun wird aber kein Wert vom SPDR in 
received_character übernommen.

received_character haben wir als uint8_t definiert.

Kann uns jemand helfen?

Deyn

Autor: Peter Mahlknecht (pmahlknecht)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
habt ihr die Variable received_character auch als volatile deklariert?
Grüße Peter

Autor: Deyn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wir haben es nun so deklariert:
volatile uint8_t received_character;

Funktioniert aber immer noch nicht.

Autor: Deyn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal unser kompletter c-Code

volatile uint8_t received_character;

//Variablen
bool takt_1s = false;
bool takt_100ms = false;
bool takt_10ms = false;
unsigned int vorteiler = VORTEILER;
unsigned int zehntel = ZEHNTEL;
unsigned int hundertstel = HUNDERTSTEL;

//Funktionsprototypen
void SPI_SlaveInit (void);
void timer0 (void);



int main ()
{
  //Init
  sei();
  SPI_SlaveInit();          //set enable interrupt
  timer0();

  DDRB = 0x0f;
  DDRC = 0x0f;
  DDRD = 0xff;

  PORTC = 0x0f;

  while(1)
  {
    if (takt_1s == true)
    {
      takt_1s = false;
      if (received_character == 1)
      {
        PINC = 0xFF;
        PIND = 0xFF;
      }      
    }
  }
}

// Timer 0 Initialisierung

void timer0 (void)
{
  TCCR0A |= (0<<WGM00) | (0<<WGM01);
  TCCR0B |= (0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
  TIMSK0 |= (1<<TOIE0);
}

// Interrupt-Routine

ISR (TIMER0_OVF_vect)
{
  vorteiler --;

  if (vorteiler == 0)
  {
    vorteiler = VORTEILER;
    takt_10ms = 1;
    hundertstel --;
  }
  

  
  if (hundertstel == 0)
  {
    hundertstel = HUNDERTSTEL;
    takt_100ms = 1;
    zehntel --;
  }

  
  if (zehntel == 0)
  {
    zehntel = ZEHNTEL;
    takt_1s = true;
  }
}

SIGNAL (SIG_SPI) 
{
  received_character = SPDR;  
}

void SPI_SlaveInit (void) 
{
  DDRB |= (1<<PB4);          
  SPCR = (1<<SPE) | (1<<SPIE) | (1<<SPR0);        
}

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Beim Simulieren springt er auch nach dem setzen der SPI Interrupt Flag
> in SIGNAL (SIG_SPI) nun wird aber kein Wert vom SPDR in
> received_character übernommen.

JTAG oder Simulator?

Stimmen die CPOL / CPHA Parameter?

Wird SS richtig angesteuert? Wenn SS nach HIGH wechselt und die CPOL / 
CPHA
nicht passt, dann wird das Datenbyte verworfen.

Zur näheren Analyse wäre der Sourcecode des Senders hilfreich.

Autor: deyn (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
cpol cpha sagt uns nichts...
wir haben es simuliert im avr studio...
hier mal der c-code des sender (masters) :
//Variablen
bool takt_1s = false;
bool takt_100ms = false;
bool takt_10ms = false;
unsigned int sekunden = 50;
unsigned int minuten = 59;
unsigned int stunden = 23;
unsigned int vorteiler = VORTEILER;
unsigned int zehntel = ZEHNTEL;
unsigned int hundertstel = HUNDERTSTEL;
unsigned int wert = 1;

//Funktionsprototypen
void SPI_MasterInit (void);
void SPI_MasterTransmit (unsigned int cData);

void Stellfunktion (void);
void timer0 (void);


int main ()
{
  //Init
  sei();
  SPI_MasterInit();          
  timer0();

  DDRC = 0x0f;
  DDRD = 0xff;

  PORTC = 0x0f;

  while(1)
  {
    if (takt_1s == true)
    {
      takt_1s = false;
      
      SPI_MasterTransmit(wert);
    }
  }
}

// Timer 0 Initialisierung

void timer0 (void)
{
  TCCR0A |= (0<<WGM00) | (0<<WGM01);
  TCCR0B |= (0<<WGM02) | (0<<CS02) | (1<<CS01) | (0<<CS00);
  TIMSK0 |= (1<<TOIE0);
}

// Interrupt-Routine

ISR (TIMER0_OVF_vect)
{
  vorteiler --;

  if (vorteiler == 0)
  {
    vorteiler = VORTEILER;
    takt_10ms = 1;
    hundertstel --;
  }
  

  
  if (hundertstel == 0)
  {
    hundertstel = HUNDERTSTEL;
    takt_100ms = 1;
    zehntel --;
  }

  
  if (zehntel == 0)
  {
    zehntel = ZEHNTEL;
    takt_1s = 1;
  }
}

void SPI_MasterInit(void)
{  
DDRB |= (1<<PB2)|(1<<PB3)| (1<<PB5);
  DDRB &= ~(1<<PB4);
  PORTB |= (1<<PB2)| (1<<PB5);
  SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}

void SPI_MasterTransmit(unsigned int cData)
{
  PORTB &= ~(1<<PB2);
  SPDR = wert;      
  while(!(SPSR & (1<<SPIF)));
  PORTB|=(1<<PB2);
  
}

Autor: tt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ersetzt doch mal:
SPCR = (1<<SPE) | (1<<SPIE) | (1<<SPR0);
durch:
SPCR |= (1<<SPE) | (1<<SPIE) | (1<<SPR0);

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> cpol cpha sagt uns nichts...

Also, wenn ihr den Atmega 88 einsetzt, dann schaut mal auf die Seite 164
im Datenblatt (SPCR-Register). Da gibt es zwei Bits CPHA CPOL. Diese 
müssen bei beiden Controllern identisch sein.

Zum Thema Simulation im AVR Studio:

Woher soll das Datenbyte kommen, wenn "außen" kein zweiter Controller 
dranhängt? Ich würde empfehlen eine Schaltung mit zwei Controllern 
aufzubauen und an beide Controller ein AVR JTAG-ICE-MKII oder einen AVR 
Dragon (geht bis 32k Flashgröße) dranzuhängen. Und dann das Ganze per 
ICE durchspielen.
Beim SPI kann man normalerweise nicht viel falsch machen, wenn man das 
Datenblatt aufmerksam gelesen hat und weiss, wie ein Schieberegister 
funktioniert.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also mal zur Codeanalyse:
// Ich würde statt "unsigned int" einen "uint8_t" nehmen. Der int ist 
// mit einer Kanone auf den Spatz geschossen!
void SPI_MasterTransmit(unsigned int cData)
{
  uint8_t dummy;
  PORTB &= ~(1<<PB2);
  SPDR = wert;                // Wieso "wert"? hier sollte doch cData stehen?
  while(!(SPSR & (1<<SPIF))); // Hier wird auf das IRQ-Flash gewartet...
  PORTB|=(1<<PB2);            // SS wierder auf High
 
  //Und wo wird das IRQ-Flag gelöscht?
  //Laut Datenblatt wird das Flag gelöscht wenn man das Statusregister  
  //abfragt und dann einen Zugriff auf das Datenregister macht. Ihr lest zwar 
  //das Statusregister in der while() oben, aber dann fehlt:
  dummy = SPDR;
}

Bei der Empfangsroutine solltet ihr darauf achten, dass das Datenbyte 
sicher verarbeitet ist, bevor ein weiteres kommt. Ansonsten liegt der 
Fehler wohl
beim Sender....

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.