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
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.
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
Nein, einen SPI Slave tut man sich nicht an auf einem Controller. Auf einem CPLD/FPGA schon. Dort hat man hinreichend Reserve.
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.
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).
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.
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"
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
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.
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..." :)
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.
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
Ist prima. Einfache SPI IO-Expander hätte es aber doch auch getan, oder? Oliver
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 ?
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.
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.
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.
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
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.
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.
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
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.
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.
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
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.
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.
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.
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.
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.
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
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.
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
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
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
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
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
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.
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...
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.
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...
> 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.