Forum: Mikrocontroller und Digitale Elektronik AVR als SPI Slave-Peripherie


von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Guten Tag!

Ich überlege, aus ATMEGA88PA oder aus ATMEGA644PA einen 
Peripherie-Baustein zu machen. Zuerst als SPI-Slave, aber im Prinzip 
später auch als UART- oder I2C-Slave.

Natürlich habe ich zuerst gekuckt, ob jemand das schon gemacht hat (um 
kein Fahrrad zu erfinden). Leider nichts gefunden. Deshalb die Frage: 
hat jemand das schon gemacht?

Ich stelle mir das vor so etwa wie bei MCP23S17: SPI-Slave bekommt ein 
paar Bytes und interpretiert sie als Befehle und Daten. Als Beispiel 
könnte alles in einen Puffer kommen und letzte Byte, nach dem ~SS in 1 
geht, wird als Befehl verstanden und alle Bytes vorher abhängig von 
Befehl als Daten benutzt... Das wäre eine Möglichkeit. Ein Beispiel habe 
ich beigelegt.

Also, die Frage: hat jemand so etwas schon gemacht? Für den Fall, wo 
fertige SPI-Bausteine nicht ausreichen?

Viele Grüße!

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Das ist ungleich schwieriger, als einen SPI Master zu implementieren, 
weil so ein Slave jederzeit bereit sein muss, Daten zu empfangen. Leider 
hat die Schnittstelle keinen Puffer, der Verzögerungen ausgleichen 
könnte.

Natürlich kann man einen Puffer in Software implementieren und mit einer 
ISR füllen. Allerdings darfst du dann praktisch keine Interrupts mehr 
sperren, bzw. nur für sehr kurze Zeit.

Das hängt natürlich von der Taktrate der Schnittstelle ab. Die ist aber 
bei SPI typischerweise sehr viel höher, als bei UART. Und UART hat 
wenigstens ein Byte Puffer, die SPI nicht.

von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Stefan ⛄ F. schrieb:
> Natürlich kann man einen Puffer in Software implementieren und mit einer
> ISR füllen. Allerdings darfst du dann praktisch keine Interrupts mehr
> sperren, bzw. nur für sehr kurze Zeit.

Das ist mir klar, besonders wenn Controller mit RC-Takt 8 MHz arbeiten 
wird. Also, etwas nicht zu sehr schnelles, aber fähig, komplexere 
Handlungen zu machen.

Z.B. graphische 128x64-LCD: statt alle Pins zu Steuerung über ISP und 
MCP23S17 und mit einer Menge von 3-Bytes-Befehlen für jede Bytes, 
schickt ein Controller nur einzigen Befehl: "zeichne mir mal eine Linie 
von xy bis xy", 5 Bytes insgesamt. Zentrale Mikrocontroller wird 
natürlich wissen, daß er nicht zu schnell nacheinander Befehle schicken 
kann. Dazu kann er auch per MISO Zustandsbyte bekommen und somit sehen, 
ob Controller mit voriger Aufgabe schon fertig ist.

Zum Vergleich: wenn ich EA DIP128-6 über SPI und MCP23S17 steuere, muß 
ich für jedes geschriebene Bytes 9 Bytes über SPI schicken, zum Lesen 
sogar 15 Bytes.

Andere Beispiel: WS2812B steuern ohne Zentrale Mikrocontroller für lange 
Zeit unfähig für alles Andere zu machen: es wird Befehl geschickt, und 
danach kann Peripherie-Mega so lange hunderte WS2812B überschreiben wie 
sie will...
Heute kostet ATMega88A schon unter 1 €, d.h. billiger sogar als schon 
genannte MCP23S17, deshalb hat das Sinn.
Ich habe irgendwo gelesen, daß manche Peripheriebausteine von Microphip 
in Wirklichkeit auf dem Werk festprogrammierte PIC-COntrollern sind. 
D.h. hier finde ich nichts Neues. Nur möchte ich natürlich andere 
Projekte ankucken, wenn jemand das schon gemacht hat...

Hier ist eine Versuchsplatine, die ich schon bei JLCPCB bestellt habe

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Nein, einen SPI Slave tut man sich nicht an auf einem Controller. Auf 
einem CPLD/FPGA schon. Dort hat man hinreichend Reserve.

von Peter D. (peda)


Lesenswert?

Maxim B. schrieb:
> hat jemand das schon gemacht?

Versucht schon, aber auch bestimmt daran gescheitert.
SPI unterstützt kein Handshake, d.h. der Master sendet/empfängt auf gut 
Glück.
Und die klassik AVRs haben nichtmal ein Byte Sendepuffer und auch keine 
Interruptlevel.

von Ingo W. (uebrig) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:
> Das ist ungleich schwieriger, als einen SPI Master zu implementieren,
> weil so ein Slave jederzeit bereit sein muss, Daten zu empfangen. Leider
> hat die Schnittstelle keinen Puffer, der Verzögerungen ausgleichen
> könnte.

Naja, einen Puffer für das letzte, vom Master empfangene Byte gibt es 
schon (USIBR), hier hat man Zeit, bis das nächste Byte empfangen ist.
Eine riesige Herausforderung ist es allerdings, wenn der Slave 
zeitgerecht antworten soll, also ins USIDR zu schreiben, während der 
Master u.U. schon die ersten 3 Pulse ausgegeben hat, dann wird es 
haarig.

Das geht mit I2c wesentlich entspannter, hier kann der Slave den Master 
ausbremsen (die USI macht das in Hardware).

von Maxim B. (max182)


Lesenswert?

Peter D. schrieb:
> SPI unterstützt kein Handshake, d.h. der Master sendet/empfängt auf gut
> Glück.

Slave kann in SPDR Zustandsbyte legen. Master wird wissen, daß bei 
bestimmten Zustandswort die Übertragung nicht geklappt hat. F_SCK sollte 
nicht zu hoch gewählt werden. Zustang von ~SS nach dem Byte-Empfang kann 
Slave mit PCINT12 (PB4, ~SS) speichern, Puffer kann verdoppelt werden, 
nach Übertragung und ~SS=1 kann zwischen Puffern umgeschaltet werden, 
welche für Empfang und für Analyse stehen...

So ein Baustein darf sich nur auf eine einzige Aufgabe konzentrieren, so 
kommt es nicht zu vielen überlappenden ISR, max. 3: SPI, PCINT und 
vielleicht nich Timer für verschiedene interne Operationen. Man kann 
also ISR auch während ISR wieder erlauben, ohne zu viel Stack zu 
nutzen...

Ich denke, das ist machbar.
Und daß F_SCK nicht auf Maximum gesetzt sein sollte - ich finde das 
nicht so schlecht. Es gibt auch andere Bausteine, die das brauchen. Z.B. 
von mir benutzte DIP203B-4 von EA kann nicht über 2 MHz gehen...

Es geht nicht um selbständiges Gerät und Kommunikation dazwischen. Es 
geht quasi um selbst gemachten Controller so etwa wie MAX7219 oder 
MCP23S17, nur für eigene Aufgaben bestimmt.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Maxim B. schrieb:
> Slave kann in SPDR Zustandsbyte legen. Master wird wissen, daß bei
> bestimmten Zustandswort die Übertragung nicht geklappt hat. F_SCK sollte
> nicht zu hoch gewählt werden. Zustang von ~SS nach dem Byte-Empfang kann

 Ja.
 Siehe hier:
Beitrag "Re: SPI 16-Bit Problem"

von Maxim B. (max182)


Lesenswert?

Danke.
Na gut: ich habe gedacht, diese Idee ist so selbstverständlich, daß 
schon längst realisiert... Ich muß das wohl selber ausprobieren, die 
Lösung von Anfang selbst durchdenken... Schließlich macht das Microchip 
schon mit ihren PICs...

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Maxim B. schrieb:
> Schließlich macht das Microchip
> schon mit ihren PICs...

Welche denn?
Mit den PIC32 (DMA) könnte das klappen.

Es gibt TFTs mit SPI am AVR:
https://www.lcd-module.de/produkte/ediptft.html
Da muß der Master Wartezeiten von 100µs bzw. 6µs einhalten. Damit ich 
keine Zeit vertrödeln muß, habe ich mich daher für die UART entschieden.

von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Bald kommt Platine aus Hongkong, dann kucke ich, was machbar ist... 
Vielleicht hilft hier Assembler? Einfache Routinen kann man mit 
Assembler wirklich flott machen: man reserviert bestimmte Register für 
SPI-ISR... Deshalb habe ich auf der Platine DIP-Gehäuse gewählt: um 
unendlich spielen zu können :) Dort sind auch I2C und UART oder USART 
möglich, Buchsen sind mit meiner früheren Versuchsplatine kompatibel, 
die hier als Master arbeiten wird...

Wie gesagt, "Obduktion wird zeigen..." :)

von Falk B. (falk)


Lesenswert?

Maxim B. schrieb:
> Also, die Frage: hat jemand so etwas schon gemacht?

Hab ich. Es geht, wenn gleich mit Einschränkungen. In meinem Fall habe 
ich nach dem Aktivieren des Slave Select im Master 10us Pause eingelegt, 
bevor die Daten an den AVR gesendet wurden. Die hat der auch gebraucht 
(real ca. 3-4us @ 8MHz), um den Interrupt auszuführen und zu reagieren 
(Lesedaten in den Sendepuffer schreiben). Als Trick habe ich das 
SS-Signal parallel auch an INT0 angeschlossen und den auf Pegelwechsel 
konfiguriert. Mit "moderneren" AVRs kann man sich das sparen und einfach 
das SS-Pin auf Pin Change Interrupt konfigurieren. Am Ende der 
Übertragung habe ich dann im Master auch wieder 10us gewartet, bis ich 
SS deaktiviert habe, damit sich die Interrupts vom Pin Change bzw. INT0 
und SPI TXC nicht überschneiden.
Ist nicht super doll, hat für meinen Fall aber gereicht.
Bei Gelegenheit kann ich ja mal den Quelltext hier hochladen.

von Dirk F (Gast)


Lesenswert?

Hi,
ich habe ein Projekt umgesetzt, bei dem ein PIC32  (SPI Master) bis zu 
15 SPI Slaves (PIC18)  ansteuert.
Klappt wunderbar.
Allerdings ist das Protokoll sehr einfach:
2 Bytes vom Master zum Slave. An jedem Slave hängen 24 Relais dran.
Wir nur zum Ein-Ausschalten der Relais verwendet.

LG Dirk

von Oliver S. (oliverso)


Lesenswert?

Ist prima. Einfache SPI IO-Expander hätte es aber doch auch getan, oder?

Oliver

von Dirk F (Gast)


Lesenswert?

Oliver S. schrieb:
> Ist prima. Einfache SPI IO-Expander hätte es aber doch auch getan, oder?

Also ich wollte keine 24 Pins vom PIC32 für die SS (Slave select) 
Funktion opfern.
Daher habe ich 3 PIC18 an eine SS Leitung angeschlossen.
Jeder PIC18 hat eine eigene Adresse, die er kennt.

Im ersten Byte vom Master zum Slave sende ich dann die Adresse des 
PIC18, den ich ansprechen möchte.
Nur er reagiert dann, die anderen beiden halten still.

Wäre das auch mit einem SPI IO-Expander gegangen ?

von Falk B. (falk)


Lesenswert?

Dirk F schrieb:
> Oliver S. schrieb:
>> Ist prima. Einfache SPI IO-Expander hätte es aber doch auch getan, oder?
>
> Also ich wollte keine 24 Pins vom PIC32 für die SS (Slave select)
> Funktion opfern.
> Daher habe ich 3 PIC18 an eine SS Leitung angeschlossen.
> Jeder PIC18 hat eine eigene Adresse, die er kennt.
> Im ersten Byte vom Master zum Slave sende ich dann die Adresse des
> PIC18, den ich ansprechen möchte.
> Nur er reagiert dann, die anderen beiden halten still.

Nennt sich Bussystem mit "in band addressing" und wurde schon erfunden.
Z.B. I2C.

https://www.mikrocontroller.net/articles/Port-Expander_PCF8574

Mit 8x den Normaltypen + 8x den A-Typen hat man 16x8 IOs, welche über 
ZWEI Leitungen ansteuerbar ist. Für Relais 10mal schnell genug.

> Wäre das auch mit einem SPI IO-Expander gegangen ?

Sicher, einfach eine beliebige Zahl 74HC595 anschließen, dafür reicht 
ein einziges SS Signal.

von c-hater (Gast)


Lesenswert?

Maxim B. schrieb:

> Bald kommt Platine aus Hongkong, dann kucke ich, was machbar ist...
> Vielleicht hilft hier Assembler?

Mit Assembler ist schon einiges machbar, aber Wunder kannst du auch mit 
Assembler nicht vollbringen. Beispiel:

Wenn du drei höher priorisierte ISRs im System hast (selbst wenn diese 
erstmal nur aus einem RETI in der Vektortabelle bestehen), dann brauchst 
du insgesamt im worst case schon 34 Takte, bis der Nutzcode deiner 
SPI-ISR erreicht ist.

Wenn du also an einer definierten Byteposition im Protokoll eine 
Antwort an den Master absetzen möchtest (was eine Reaktion innerhalb 
eines halben SPI-Taktes erfordert) und man ganz optimistisch annimmt, 
dass du nur zwei Systemtakte brauchst, um die Antwort zu posten (1x IN 
von irgendeiner Peripherie, 1x OUT nach SPDR/USIDR), dann bist du schon 
in der Situation, dass dein SPI-Takt auf Systemtakt/(2*36) beschränkt 
sein muss, um auch im worst case noch zu funktionieren.

Das bedeutet bei 8MHz Systemtakt, dass du beim SPI-Takt schon bei diesem 
sehr optimistisch skizzierten Fall auf ca. 111kHz beschränkt bist.

D.h.: da kannste auch gleich I2C nehmen, das ist viel gutmütiger, weil 
der Slave hier bremsen kann (und obendrein nur soviel bremst, wenn es 
aktuell nötig ist).

SPI-Slave mit AVR8 kommt deshalb eigentlich nur sinnvoll in Frage, wenn 
es  keine konkurrierenden Interrupts gibt und/oder die Datenrichtung 
ausschließlich Master->Slave ist. Vor allem letzteres entspannt nämlich 
das Timing drastisch, weil man statt 0.5 SPI-Takten dann 7.5 Takte 
Antwortzeit hat, also das 15fache.

Als Alternative kommt aber auch noch ein anderes Kommunikationsschema in 
Frage, bei dem nur mit dem "SS"-Interrupt gearbeitet wird (also 
eigentlich via PCINT) und der Rest per Polling im exklusiven Code von 
deren ISR abgewickelt wird. Mit diesem Schema geht sehr viel mehr. Hat 
allerdings auch noch den Nachteil, recht lange den SPI-Bus zu belegen 
(wegen der Zwangswartezeit des Masters, denn der muss nunmehr hier den 
worst case des Slave abwarten) und auf den Slave bezogen: lange Zeit 
jegliche konkurrierenden Interrupts dort zu unterbinden. Also auch nicht 
wirklich schön.

Zusammenfassend kann man wohl sagen, dass die SPI-Hardware der AVR8 
ziemlich Scheisse ist, was den Betrieb als Slave betrifft. Das 
allerdings ist keine ganz neue Erkenntnis, wurde hier schon unzählige 
Male thematisiert.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Dirk F schrieb:
> Daher habe ich 3 PIC18 an eine SS Leitung angeschlossen.
> Jeder PIC18 hat eine eigene Adresse, die er kennt.
>
> Im ersten Byte vom Master zum Slave sende ich dann die Adresse des
> PIC18, den ich ansprechen möchte.
> Nur er reagiert dann, die anderen beiden halten still.

 Das stimmt schon mal nicht.
 Wenn SS aktiv ist, wird beim Slave immer SPDR rausgetaktet.
 Bei dir senden also immer 3 Slaven gleichzeitig.

von Sascha W. (sascha-w)


Lesenswert?

Marc V. schrieb:
> Dirk F schrieb:
>> Daher habe ich 3 PIC18 an eine SS Leitung angeschlossen.
>> Jeder PIC18 hat eine eigene Adresse, die er kennt.
>>
>> Im ersten Byte vom Master zum Slave sende ich dann die Adresse des
>> PIC18, den ich ansprechen möchte.
>> Nur er reagiert dann, die anderen beiden halten still.
>
>  Das stimmt schon mal nicht.
>  Wenn SS aktiv ist, wird beim Slave immer SPDR rausgetaktet.
>  Bei dir senden also immer 3 Slaven gleichzeitig.
Die Richtung wird er gar nicht Nutzen für die Relais.

Sascha

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Sascha W. schrieb:
> Die Richtung wird er gar nicht Nutzen für die Relais.

Maxim B. schrieb:
> schickt ein Controller nur einzigen Befehl: "zeichne mir mal eine Linie
> von xy bis xy", 5 Bytes insgesamt. Zentrale Mikrocontroller wird
> natürlich wissen, daß er nicht zu schnell nacheinander Befehle schicken
> kann. Dazu kann er auch per MISO Zustandsbyte bekommen und somit sehen,
> ob Controller mit voriger Aufgabe schon fertig ist.

 Der TO hat nichts von irgendwelchen Relais erwähnt, aber sehr wohl von
 einer Antwort.

von Falk B. (falk)


Angehängte Dateien:

Lesenswert?

OK, hier der Quelltext zu meinem Beitrag.

Beitrag "Re: AVR als SPI Slave-Peripherie"

Der Controller (ATmega32@8MHz RC-Oszi) arbeitet als SPI-Slave, welcher 2 
Bytes zum Master zurück schickt sowie 32 Bytes vom Master empfängt. Die 
2 Bytes sind die Infos des Tastencodes einer Matrixtastatur, die 32 
Bytes die Daten für ein 2x16 LCD.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

c-hater schrieb:
> Wenn du drei höher priorisierte ISRs im System hast (selbst wenn diese
> erstmal nur aus einem RETI in der Vektortabelle bestehen), dann brauchst
> du insgesamt im worst case schon 34 Takte, bis der Nutzcode deiner
> SPI-ISR erreicht ist.

 Das ist nicht optimistisch, das ist eher unrealistisch - niemand
 erlaubt Interrupts die nix tun in derart zeitkritischen Systemen.
 Es wird also (in worstcase) viel länger dauern...
 Und die richtige Rechnung ist:
 (Anzahl_der_Takte_pro_ISR * Benutzte_HöherePrioritet_ISR) / 8


> Das bedeutet bei 8MHz Systemtakt, dass du beim SPI-Takt schon bei diesem
> sehr optimistisch skizzierten Fall auf ca. 111kHz beschränkt bist.

 Beschränkt ja, aber nur beim ersten Byte.
 Danach MASTER auf MaxSpeed und ab geht die Post.
 SLAVE wird sowieso vom MASTER getaktet, für den ist es vollkommen egal
 ob mit 100KHz oder mit fClk/2 gesendet wird.
 Wenn SS als PCINT gesetzt ist, kann der ganze Empfang in der PCINT-
 -Routine abgewickelt werden.
 Und wenn die Befehlslänge vorher festgelegt ist, funktioniert das Ganze
 sogar bei 2MHz ohne Probleme - selbst eine Abfrage auf überschrittene
 Empfangszeit ist drin.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Marc V. schrieb:

> c-hater schrieb:
>> Wenn du drei höher priorisierte ISRs im System hast (selbst wenn diese
>> erstmal nur aus einem RETI in der Vektortabelle bestehen), dann brauchst
>> du insgesamt im worst case schon 34 Takte, bis der Nutzcode deiner
>> SPI-ISR erreicht ist.
>
>  Das ist nicht optimistisch, das ist eher unrealistisch - niemand
>  erlaubt Interrupts die nix tun in derart zeitkritischen Systemen.
>  Es wird also (in worstcase) viel länger dauern...
>  Und die richtige Rechnung ist:
>  (Anzahl_der_Takte_pro_ISR * Benutzte_HöherePrioritet_ISR) / 8

Genau das schrieb ich doch. 3*8 sind 24. Dazu kommt aber noch mindestens 
3 Takte variable Latenz aus main (wenn dort gerade ein RET abgearbeitet 
wird, bei Interruptsperren in main können es auch ein "paar" Takte mehr 
sein). Und die Zeit, bis der Nutzcode in der SPI-ISR erreicht wird, 
nachdem diese dann endlich wirklich ausgelöst wurde, das sind weitere 6 
Takte, 4 für für den Eintrittsteil der ISR (Rücksprungadresse pushen) 
und 2 für den RJMP vom Vektor zum Nutzcode.

>  Beschränkt ja, aber nur beim ersten Byte.

Nein.

>  Danach MASTER auf MaxSpeed und ab geht die Post.

Das ist einfach nur eine Variante des Ansatzes mit Polling im 
SS-Interrupt. Die Wirkung (und alle systemimmanenten Nachteile) sind 
exakt dieselben.

Der einzige Unterschied ist, ob die lange nutzlose Busbelegung vor oder 
nach dem ersten Byte stattfindet.

>  SLAVE wird sowieso vom MASTER getaktet

Natürlich. So ist das halt bei SPI.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

c-hater schrieb:
>>  Danach MASTER auf MaxSpeed und ab geht die Post.
>
> Das ist einfach nur eine Variante des Ansatzes mit Polling im
> SS-Interrupt. Die Wirkung (und alle systemimmanenten Nachteile) sind
> exakt dieselben.

 Selbstverständlich nicht.
 6 Bytes beim I2C und 100KHz dauern min. (Adresse + 6 Byt) * 9 + 2 =
 65 * 10μs = 650μs.
 5 Bytes beim SPI und 2MHz dauern 5*8 = 40 * 500ns = 20μs und wenn man
 sogar noch 80 Takte Bearbeitungszeit für ev. Fehler und überschreiten
 der Zeit zwischen den Byten dazurechnet, sind es knapp 60μs.
 Da hat man mehr als 250μs Zeit (2000 Takte bei 8MHz), um die höheren
 ISR abzuarbeiten bzw. den ersten Byte zu empfangen und ist immer noch
 mehr als doppelt so schnell.

 Also:
 a) SPI ist mindestens 20 Mal schneller als I2C, genauso einfach zu
 realisieren, man muss nur wissen wie - nur die Meisten wissen es halt
 nicht und da ist es viel einfacher zu schreiben, daß SPI Mist ist...
 b) SPI ist bidirectional - Empfangen und senden geht also gleichzeitig,
 beim I2C braucht man mehr als doppelt so viel Zeit dazu.

 Was aber für worstcase noch schlimmer ist:
 TWI-Interrupt hat sogar noch niedrigere Priorität als SPI-Interrupt.

 Einziger Nachteil: Braucht mehr Pins als I2C.

von Marc V. (Firma: Vescomp) (logarithmus)


Angehängte Dateien:

Lesenswert?

Frage an den schwachsinnigen, anonymen an meinen Beiträgen munter
 klickenden retardeten Feigling:

 Glaubst du, daß deine negative Bewertung etwas ändert an der Tatsache,
 daß du ein Idiot bist?

 Antworte und sage was dir nicht gefällt, feiges piece of chit.

: Bearbeitet durch User
von Dirk F (Gast)


Lesenswert?

Marc V. schrieb:
> Das stimmt schon mal nicht.
>  Wenn SS aktiv ist, wird beim Slave immer SPDR rausgetaktet.
>  Bei dir senden also immer 3 Slaven gleichzeitig.

Nö.
Das ist der Vorteil eines MCU basierenden SPI SLave.
Alle 3 MISO der Slaves sind parallel geschaltet und normal hochohmig 
(Auf Input geschaltet)
Erst wenn er sich angesprochen fühlt (1. Byte Master>Slave Adresse) dann 
setzt nur er den MISO auf Output und sendet an den Master.

von Stefan F. (Gast)


Lesenswert?

Marc V. schrieb:
> Frage an den schwachsinnigen, anonymen ... feiges piece of chit.

Anonyme User können Bewertungen weder sehen noch ändern. Nach deiner 
persönlichen Beleidigung hast du keine Antwort auf deine Frage verdient.

von Peter D. (peda)


Lesenswert?

Marc V. schrieb:
> TWI-Interrupt hat sogar noch niedrigere Priorität als SPI-Interrupt.

Weil das überhaupt keine Rolle spielt. Der Slave setzt SCL erst wieder 
auf High, wenn er den Interrupt bearbeitet hat. Und der Master kriegt 
dann auch erst den nächsten Interrupt. Niemand muß also unnütz warten 
oder andere Tasks warten lassen.
Bei I2C ist keine Aktion zeitkritisch. Für alle Zeiten gibt es nur 
Minimalwerte.

von Stefan F. (Gast)


Lesenswert?

Peter D. schrieb:
> Niemand muß also unnütz warten oder andere Tasks warten lassen.

Der Master muss warten, dass der Slave fertig wird. Aus Sicht des Master 
kann das Warten "unnütz" oder gar störend sein.

von ot (Gast)


Lesenswert?

Stm32 oder stm8 haben bessere spi slave Voraussetzungen ....

von Peter D. (peda)


Lesenswert?

Marc V. schrieb:
> niemand
>  erlaubt Interrupts die nix tun in derart zeitkritischen Systemen.

Ich hab aber keine Lust auf unnötig zeitkritische Systeme. Daher benutze 
ich grundsätzlich keinen SPI-Slave auf AVRs.

Z.B. die AT89LP51-Serie von Microchip ist deutlich besser geeignet als 
SPI-Slave. Er hat sowohl Sendepuffer als auch 4 Interruptlevel. Der 
Master muß also nirgends umständlich vor sich hin warten. Lediglich die 
Bedingung F_CPU/4 muß er einhalten, d.h. max sind 5MBit erlaubt.

von Peter D. (peda)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der Master muss warten, dass der Slave fertig wird.

Bei I2C kostet das Warten auf den Interrupt aber keine CPU-Zeit. I2C 
kann ganz bequem im Hintergrund ablaufen.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Peter D. schrieb:
> Bei I2C kostet das Warten auf den Interrupt aber keine CPU-Zeit. I2C
> kann ganz bequem im Hintergrund ablaufen.

Ja das stimmt wohl. Es sei, denn Master muss mit einem anderen Slave 
kommunizieren.

Jeder Slave kann den ganzen Bus blockieren, bei vielen Slaves kann das 
schnell zum Schwachpunkt werden. Andererseits ist es eine simple Methode 
der Synchronisation, deswegen nutze ich I²C oft und gerne.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Peter D. schrieb:
> Stefan ⛄ F. schrieb:
>> Der Master muss warten, dass der Slave fertig wird.
>
> Bei I2C kostet das Warten auf den Interrupt aber keine CPU-Zeit. I2C
> kann ganz bequem im Hintergrund ablaufen.

 Das geht beim SPI (fast) auch. Beispiel für 4MHz SPI:
 1) Master zieht SS auf Low, wartet 2μs.
 2) Slave hat SS als PCINT, springt in die ISR-Routine, SPDR = 0x55.
 3) Master sendet 0xAA, jede Antwort vom Slave die anders als 0x55 ist,
  wird als ungültig betrachtet. Dauert bei 4MHz knapp 2μs.
 4) Falls 0x55 erhalten, sendet der Master weitere 5 Bytes mit Pausen
 von 1μs dazwischen damit der Slave genügend Zeit hat, um Pointer zu
 erhöhen und SPDR mit neuen Werten zu aktualisieren.
 Dauert (für Master) insgesammt 18μs.

 I2C sendet (Adress_RD+5 Bytes) * 9 + Start + Stop = 56 * 10μs = 560μs.
 560μs / 18μs = 31 Mal langsamer oder 542μs (8672 Takte) vertrödelt.

 Oder I2C-Master hat (mit TWI_ISR) 5 Mal Einsprung in die ISR-Routine
 mit pushs, pops, in, out, ldi, st, ld, mov, reti usw.
 D.h. alle 90μs kommt ein INT der etwa 3μs dauert.
  90μs /  3μs = 3.33% CPU-Zeit für I2C.
 560μs / 18μs = 3.21% CPU-Zeit für SPI.
 Und zwischen 55KHz und 1.7KHz besteht doch ein Unterschied...

 Natürlich ist Hintergrund meistens besser aber eben nicht für alles
 und nicht um sooo viel.
 Ohne DMA ist das alles praktisch nur Geschmacksache, deswegen liebe
 ich STM und DMA.

: Bearbeitet durch User
von Maxim B. (max182)


Angehängte Dateien:

Lesenswert?

Dirk F schrieb:
> Also ich wollte keine 24 Pins vom PIC32 für die SS (Slave select)
> Funktion opfern.
> Daher habe ich 3 PIC18 an eine SS Leitung angeschlossen.
> Jeder PIC18 hat eine eigene Adresse, die er kennt.
>
> Im ersten Byte vom Master zum Slave sende ich dann die Adresse des
> PIC18, den ich ansprechen möchte.
> Nur er reagiert dann, die anderen beiden halten still.
>
> Wäre das auch mit einem SPI IO-Expander gegangen ?

MCP23S17 unterstützt bis 8 IC auf einem ~SS. Das kostet aber zusätzliche 
Byte bei Übertragung: Adresse von IC - Adresse in IC - Daten, entweder 
schreiben oder lesen, aber nicht gleichzeitig. So arbeitet MCP23S17.

Diese zwei Eigenschaften (drei Bytes und Unmöglichkeit, gleichzeitig 
senden und lesen) sind Grund, warum ich ab und zu mit einfachen 
Schieberegister arbeite. Beispiel hier: nur je 2 Bytes pro Operation, 
gleichzeitig Schreiben und Lesen, außerdem kann man einige Operationen 
zusammensetzen (z.B. E1=0 + DB-Schieberegister von Z zu Aktiv, wofür 
MCP23S17 mehrere 3-Bytes-Befehle braucht).

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

c-hater schrieb:
> Wenn du also an einer definierten Byteposition im Protokoll eine
> Antwort an den Master absetzen möchtest (was eine Reaktion innerhalb
> eines halben SPI-Taktes erfordert) und man ganz optimistisch annimmt,
> dass du nur zwei Systemtakte brauchst, um die Antwort zu posten (1x IN
> von irgendeiner Peripherie, 1x OUT nach SPDR/USIDR), dann bist du schon
> in der Situation, dass dein SPI-Takt auf Systemtakt/(2*36) beschränkt
> sein muss, um auch im worst case noch zu funktionieren.
>
> Das bedeutet bei 8MHz Systemtakt, dass du beim SPI-Takt schon bei diesem
> sehr optimistisch skizzierten Fall auf ca. 111kHz beschränkt bist.

Es ist aber nicht notwendig, daß Slave gleich Antwort-Byte bereit legt. 
Manche "fertigen" IC können das auch nicht. Wenn Master auch 8-bit-SPI 
hat, wird er nach edem Byte sowieso eine kleine Pause machen, SCK wird 
nach 8 Pulse unterbrochen. Keine Schwierigkeit, dazwischen ein paar NOPs 
zu setzen, damit Slave genug Zeit hat, Byte zu holen. Ich glaibe nicht, 
daß Geschwindigkeit dadurch auf I2C-Niveau runter geht. Für F_CPU=8 MHz 
kann SCK nicht über 2 MHz sein. Notfalls kann SCK auf 1 MHz runter 
gehen, immer noch besser als 100 kHz bei I2C. Es gibt zwar IC, die sogar 
3,4 MHz I2C können, aber wenn man mehrere verschiedenen IC auf der 
Schiene hat, wird man kaum über 400 kHz gehen oder gar nicht über 100 
kHz.

Für mich ist Grund, bei SPI zu bleiben: wenn andere IC auf der Platine 
schon SPI brauchen. I2C kann man für etwas sonst reservieren.

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Falk B. schrieb:
> OK, hier der Quelltext zu meinem Beitrag.

Vielen Dank! Sehr interessant!

von Maxim B. (max182)


Lesenswert?

Marc V. schrieb:
> Wenn SS als PCINT gesetzt ist, kann der ganze Empfang in der PCINT-
>  -Routine abgewickelt werden.
>  Und wenn die Befehlslänge vorher festgelegt ist, funktioniert das Ganze
>  sogar bei 2MHz ohne Probleme - selbst eine Abfrage auf überschrittene
>  Empfangszeit ist drin.

Ich habe es mir zuerst so vorgestellt:
SPI-ISR steuert Byte-Empfang. Puffer wird continuierlich mit Daten 
gefüllt.
PCINT-ISR setzt Bit in GPIOR0, mit Bit-Adressieren, somit kann ISR_NAKED 
verwendet werden. Dieser Bit zeigt für Programm, daß letzte Byte (evtl. 
Command) empfangem wurde und Analyse darf beginnen. Somit ist wechselnde 
Länge von Sendungen möglich. Evtl. wird Puffer für Alternative 
umgeschaltet, um weitere Empfang zu ermöglichen.

Welche Pause zwischen Bytes sollte Master machen, das sollte Praxis 
zeigen...

: Bearbeitet durch User
von Maxim B. (max182)


Lesenswert?

Peter D. schrieb:
> Z.B. die AT89LP51-Serie von Microchip ist deutlich besser geeignet als
> SPI-Slave.

Den würde ich gerne verwenden. Irgendwann habe ich mit 89 gearbeitet, 
vor 20 Jahren. Aber mir fehlt IDE und Programmiergerät, für AT Mega habe 
ich das einschließlich JTAG. Wieder 89 wie damals per Hand und mit 
Maschinencode zu programmieren - dafür bin ich jetzt zu verwöhnt :) 
Lieber etwas Bremse in Kauf nehmen :)

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Maxim B. schrieb:
> Aber mir fehlt IDE und Programmiergerät

Die AT89LP51RD2-ED2-ID2 haben einen UART-Bootloader und lassen sich mit 
Flip programmieren.
Als C-Compiler gibt es den SDCC.

von Maxim B. (max182)


Lesenswert?

Danke. Interessant. Aber ich muß zuerst viel darüber lesen :)

von c-hater (Gast)


Lesenswert?

Maxim B. schrieb:

> Es ist aber nicht notwendig, daß Slave gleich Antwort-Byte bereit legt.

Das ist auch überhaupt nicht das Problem. Das Problem ist, die Antwort 
an einer definierten Stelle (bezogen auf den Beginn der Kommunikation 
durch den Master) in das Schieberegister zu packen. Der Master hat 
nämlich keine Chance, zu überprüfen, ob das geklappt hat, er wird an der 
erwarteten Stelle immer irgendetwas empfangen, entweder die erwartete 
Antwort oder das Byte, was er zuletzt selbst gesendet hat. Er kann halt 
nur nicht zuverlässig unterscheiden, was von beidem er nun tatsächlich 
empfangen hat...

Ja, mit hingedengelten Protokollen auf höherer Ebene kann man das 
Problem auf die eine oder andere Art "lösen"...

> Manche "fertigen" IC können das auch nicht.

Jepp. Die nutzen dann auch solche hingedengelten Protokolle. Genau das 
ist, was SPI (was eigentlich sehr trivial ist) so verdammt 
fehlerträchtig macht, denn jeder macht's anders...

> Wenn Master auch 8-bit-SPI
> hat, wird er nach edem Byte sowieso eine kleine Pause machen, SCK wird
> nach 8 Pulse unterbrochen.

Das ist eine sehr optimistische Annahme, die schon dann nicht stimmt, 
wenn du nur mal als SPI-Master die UART eines AVR8 im SPI-Master-Modus 
verwendest. Die kann kontinuierlich, also ohne jede zwischenzeitliche 
"Taktdehnung" eine beliebig lange Folge von Bytes rausballern...

von Peter D. (peda)


Lesenswert?

Das Problem ist hauptsächlich, daß der Slave eben nicht 99% der 
CPU-Leistung verbrauchen soll, nur um ja kein Paket des Masters zu 
verpassen. Einen MC nimmt man ja gerade deshalb, daß der Slave 
komplexere Dinge ausführen soll, z.B. auch andere Interrupts, die 
durchaus länger brauchen können.
Z.B. der Slave soll Töne ausgeben oder einen LED-Würfel multiplexen. 
Dann darf während des SPI eben nicht der Ton aussetzen oder die LEDs 
flackern.

Für einfaches IO kann man besser die 74HC165/74HC595 verwenden. Die 
lassen sich beliebig kaskadieren und der Master kann full Speed 
sprechen. In einer Anwendung habe ich mal 21 Stück 74HC595 kaskadiert.

von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:

> Der Master muss warten, dass der Slave fertig wird.

Nein, jedenfalls nicht im Sinne eines busy-wait. Dafür gibt's ja 
schließlich den Interrupt. Der Master kann also in der Zeit tun, was 
immer er für wichtig hält.
Das einzige, was er in dieser Zeit nicht tun kann, ist andere Geräte am 
selben I2C-Bus ansprechen, wer der halt belegt ist.
Und der Slave muss ebenfalls nicht sinnlos warten, denn er braucht immer 
bloß die ganz normal den/die TWI-Interrupts zu behandeln.

Bei diesen schrägen SPI-Implementierungen hingegen muß der Master 
wirklich warten oder zumindest einen zusätzlichen Timer und dessen 
Interrupt benutzen. Der Bus ist natürlich in dieser Zeit ebenfalls tabu.
Der Slave hingegen muss sogar wirklich busy-wait in der ISR machen 
(entweder PCINT oder halt SPI/USI, je nachdem, wie man es nun genau 
umsetzt). D.h.: er kann in der Zeit wirklich garnichts nützliches tun, 
nichtmal wirklich wichtige Sachen wie konkurrierende Interrupts 
behandeln.

Was diese Sache im Vergleich zu I2C richtig schlimm macht, ist die 
Tatsache, dass immer die Wartezeiten des worst case anfallen (wenn die 
Sache zuverlässig funktionieren soll), bei I2C hingegen nur dann, wenn 
dieser tatsächlich mal eintritt.
Das hat dramatische Konsequenzen für den effektiven Nettodurchsatz des 
Busses. Und in der Folge ist die effektiv erreichbare Durchsatz halt auf 
I2C-Niveau oder sogar noch darunter. Es sei denn, mann nutzt sehr lange 
Datenbursts in der exklusiven Polling-Phase. Dann hat man aber eben auch 
entsprechend lange Zeiten, in denen der Slave auf keinen anderen 
Interupt reagieren kann.

Und wo sollen dann die Daten herkommen oder hingegehen, die man so 
schnell befördert hat, wenn die Lieferanten oder Abnehmer blockiert 
sind...

von MCUA (Gast)


Lesenswert?

> Leider hat die Schnittstelle keinen Puffer, der Verzögerungen ausgleichen
> könnte.
Wie hier schon öfters und auch hier genannt, AVR-SPI -RX hat 
1BytePuffer, -TX hat keinen!
(mit den bekannten Nachteilen, lange Wartezeiten, Extra Handshake usw)
Neuere AVRs sollen lt. MCH aber auch einen SPI-TX 1BytePuffer haben (ist 
glaubich auch den DS's zu sehen).
Also, das hätte MCH gelernt. Können se auch gleich die 4x RX/TX-Buffer 
(FIFO) von den PIC24 mit übernehmen.

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.