Forum: Mikrocontroller und Digitale Elektronik Von SPI mit Polling zu SPI mit ISR


von spi Anfänger (Gast)


Lesenswert?

Hallo zusammen,

habe Schwierigkeiten SPI mit Interrupt zu schreiben und brauche 
unbedingt Hilfe.

Ich habe folgende Funktion mit Polling und weiß nicht wie ich es 
umschreiben muss um eine ISR zu verwenden.


ISR(SPI_STC_vect){
}

void SPI_MasterWrite(uint8_t Adress, uint8_t Daten)
{
  PORTB &= ~(1<<PB1);

  SPDR = Adresse  ;
  while(!(SPSR & (1<<SPIF)))
    ;
  SPDR = Daten ;
  while(!(SPSR & (1<<SPIF)))
    ;
  PORTB |= (1<<PB1);

}

von spi Anfänger (Gast)


Lesenswert?

Bekomme es einfach nicht hin und bitte um Hilfe.

von Falk B. (falk)


Lesenswert?

@spi Anfänger (Gast)

>Ich habe folgende Funktion mit Polling und weiß nicht wie ich es
>umschreiben muss um eine ISR zu verwenden.

SPI mit Interrupt loht sich nur, wenn man wirklich SPI eher langsam 
betreiben muss, weil die ICs das so brauchen. Ansonsten fährt man SPI 
mit maximal möglicher Geschwindigkeit mit Polling. ISt schneller und 
einfacher.

>ISR(SPI_STC_vect){
>}

Hier springt deine CPU rein, wen eine SPI-Übertragung beendet wurde. Was 
macht man dann?

1.) Die gelesenen Daten speichern, SPDR auslesen
2.) Neue Daten, soweit vorhanden, in SPDR schreiben.
3.) Wenn keine neuen Daten mehr zu schreiben/lesen sind, CS inaktiv 
schalten.

von spi Anfänger (Gast)


Lesenswert?

Könntest du das bitte anhand meines Beispiels mal codieren?

Bei mir hat es irgendwie noch nicht Klick gemacht.

von spi Anfänger (Gast)


Lesenswert?

Hatte im Netz ein Beispiel gefunden mit globaler Variable damit die ISR 
sie auch kennt.

Bekomme es aber einfach nicht hin das auf meins umzuschreiben.




uint8_t globalDaten;


void SPI_MasterInit(void)
{
  uint8_t sreg = SREG;

  DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK)|(1<<DD_SS);        //Set MOSI and 
SCK output, all others input

//Interrupts kurz deaktivieren
  cli();

  SPCR = (1<<SPIE)|(1<<SPE)|(1<<MSTR);

  //Global Interrupt flag wieder herstellen
  SREG = sreg;
}



void SPI_MasterWrite(uint8_t Adresse, uint8_t Daten)
{
  PORTB &= ~(1<<PB1);

  if((SPSR & (1<<SPIF)) >0 )
  SPDR = Adresse  ;        // Start transmission of adress

  if((SPSR & (1<<SPIF)) >0 )
  SPDR = Daten ;          // Start transmission of data (register)

 PORTB |= (1<<PB1);
}


ISR(SPI_STC_vect)
{
  SPDR = globalDaten;
}

von Falk B. (falk)


Lesenswert?

@  spi Anfänger (Gast)

>Hatte im Netz ein Beispiel gefunden mit globaler Variable damit die ISR
>sie auch kennt.

Mit EINEM einzigen Byte ist SPI und Interrupt reichlich sinnlos. Wenn, 
dann muss man ganze Arrays übertragen. Wie das ungefähr geht, sieht man 
hier.

http://www.mikrocontroller.net/articles/Interrupt#UART_mit_Interrupts

Muss man halt für SPI umschreiben. Dazu braucht es u.a. einen Zähler, 
wieviele Bytes noch übertragen werden sollen.

Das ist eine Aufgabe för den Schöler.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Geh nochmal zurück auf "Los!".  Denk drüber nach, warum du
überhaupt SPI mit Interrupt haben willst.  Solange du nichts hast,
was du parallel zum SPI-Transfer abarbeiten kannst, wird die Sache
nur langsamer: das Reinspringen in die ISR benötigt bereits
hardwareseitig genauso lange wie eine Poll-Schleife auf SPIF, dann
kommt aber noch der Prolog und Epilog des Compilers für die ISR
dazu.

Solange du nur versuchst, einen Interrupt zu benutzen, nur weil man das
überhaupt so tun könnte, aber am Ende der main thread nur drauf
wartet, bis die ISR fertig ist, ist das alles ziemlicher Humbug.

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.