Hallo, hat einer bereits einen AVR als SPI Schieberegister programmiert? Ich habe nach einem Schieberegister gesucht, was wenn einmal Daten über SPI erhalten hat, eine eigenständige PWM durchläuft für insgesamt 3 Kanäle. Ich brauche hierbei eine PWM Freq von ~15kHz. Nun habe ich es noch nicht sinnvoll hinbekommen, dass der Master die Daten an die Slaves schickt. Das erste Register soll 3*256 Bits abrufen. Solange SS den Zustand nicht gewechselt halt, soll er die nächsten Bits an die nächsten Slaves weiterleiten. Erst wenn sich der Status von SS ändert, sollen die Werte an die PWMs weitergeleitet werden. So wie halt ein HC595 oder ähnliches. Dabei soll das ganze System ohne feste Adresse ablaufen. In einen AVR rein und hinten wieder raus. Doch den part bekomme ich nicht hin und bei den Suchbegriffen findet man immer nur das falsche -> AVR Schieberegister. Ich hatte zwischenzeitig schon an ein WS2801 IC gedacht mit getakteter Konstantspannung am Ausgang (s. DB). Jedoch ist die Schaltfrequenz der 3 Ausgänge nur bei etwa 2,5kHz. Gruß
Hallo Peter, Peter schrieb: > Ich habe nach einem Schieberegister gesucht, was wenn einmal Daten über > SPI erhalten hat, eine eigenständige PWM durchläuft für insgesamt 3 > Kanäle. Ich brauche hierbei eine PWM Freq von ~15kHz. Gibt es ein Schaltbild für dein Vorhaben? Was bedeutet es, "eine eigenständige PWM" zu "durchlaufen"? Soll das der AVR tun? > Nun habe ich es noch nicht sinnvoll hinbekommen, dass der Master die > Daten an die Slaves schickt. Das erste Register soll 3*256 Bits abrufen. > Solange SS den Zustand nicht gewechselt halt, soll er die nächsten Bits > an die nächsten Slaves weiterleiten. Erst wenn sich der Status von SS > ändert, sollen die Werte an die PWMs weitergeleitet werden. Wer ändert den Status von SS? Ist das ein Eingang des AVR oder ein Ausgang? > Doch den part bekomme ich nicht hin Würde ich auch nicht... ich hab ihn nicht verstanden. ;-)
Hallo Markus, einen Schaltplan habe ich noch nicht erstellen können. Die KSQ habe ich noch nicht aufgebaut. Derzeit teste ich das ganze mit einfachen RGB Leds (+3Widerstände) an einem Attiny841. Eigenständige PWM soll heißen, ich möchte einmalig Daten an den SPI Slave schicken. zB: 127, 0, 0, Nun wird abgewartet bis der SS wieder HIGH ist. Dann werden die Daten übernommen werden. Nun macht der Slave dauerhaft auf dem roten Kanal eine PWM mit 50%. Wenn ich nun aber 255,127,0,0,55,125 schicke, sollen die ersten 3 Bytes direkt an den nächsten Slave weitergeleitet werden. Habe hier im Forum schon einige Vorschläge gelesen, dass man für das Vorhaben auch direkt einen AVR nehmen kann, da diese meist sogar günstiger als bestimmte Schieberegister sind (von den hc595 rede ich nicht) und man halt diese frei programmieren kann. Einen Code Snippets zum Einstieg habe ich nicht gefunden. Die AppNotes haben nicht weitergeholfen.
Peter schrieb: > 127, 0, 0, > Nun wird abgewartet bis der SS wieder HIGH ist. Dann werden die Daten > übernommen werden. Nun macht der Slave dauerhaft auf dem roten Kanal > eine PWM mit 50%. Wer wartet? Das AVR-basierte Schieberegister, das du verwenden willst? SS = Slave Select, oder? > Wenn ich nun aber 255,127,0,0,55,125 schicke, sollen die ersten 3 Bytes > direkt an den nächsten Slave weitergeleitet werden. Wenn ich es richtig verstehe, soll ein 768 bit langer Bitstrom aufgesplittet werden in Portionen von 24 bit. Jede dieser Portion soll an einen anderen Ausgang gehen...? Oder wird der Strom sowieso an alle 841 gleichzeitig gesendet, und du willst nur die SS-Eingänge der 841 alle 24 bit umschalten Kann aber gut sein, dass meine grauen Zellen schon etwas langsam rotieren um diese Uhrzeit. :-)
Wie stellst du dir die CLK-Leitung vor? Wenn du die auf alle Chips verteils, woher soll ein µC dann wissen an welcher Position es sitzt? Soll da dann jeweils noch eine SS-Leitung von Chip zu Chip, die jeweils vom Vorgänger aktiviert wird, sobald der seine 3 Bytes hat? Dann hast du ein kleines Problem mit dem SPI-Moduls. Selbiges erlaubt dir ja immer erst nach dem vollständigen Empfangen eins Bytes Zugriff auf das Byte, welches du ja gerade schon weiter schicken willst. Du müsstest also schon vorher wissen was du empfangen wirst um das auch im richtigen Moment weiter schicken zu können. Folglich kannst das 1.Byte für den 2. Slave erst mit dem 4. vom Master gesendeten Byte aus dem SPI-Modul des 1.Slave getaktet werden. Das führt dazu, dass dir am Ende Takte fehlen (Jeder Slaver verzögert die Daten ja um 1 Byte). Der Master müsste also für jeden gesendeten 3-Byte-Block ganz am ende ein weiteres Dummy-Byte senden damit die Daten für das letzt Slave auch bei diesem ankommen können. Alternativ musst jeder Slave nach dem 3.Byte das SPI deaktivieren und per Software die Datenleitung "überbrücken". Das führt natürlich zu einer Latenz und kann nach ein paar µCs schon zu Fehlern führen.
Leo B. schrieb: > Selbiges erlaubt > dir ja immer erst nach dem vollständigen Empfangen eins Bytes Zugriff > auf das Byte, welches du ja gerade schon weiter schicken willst. Hallo Leo, berechtigter Einwand. Das Problem tritt aber nicht auf, wenn SPI per Software abgewickelt wird. Dann kann man quasi sofort Bit für Bit reagieren. Bringt mich aber wieder zu Frage 1: ein (zumindest grob skizzierter) Schaltplan wär nicht verkehrt. :-)
Markus Weber schrieb: > Hallo Leo, berechtigter Einwand. > Das Problem tritt aber nicht auf, wenn SPI per Software abgewickelt > wird. Dann kann man quasi sofort Bit für Bit reagieren. Dann schreib 2 software-SPI-Module, sonst wird die Datenleitung über die Chips zu arg verzögert gegenüber dem CLK-Signal. Aber mir kam ein anderer Gedanke: Slave n empfängt 3 Byte, legt dann das 1.Byte zum Senden ins SPI-Datenregister und aktiviert SS von Slave n+1. Möglicherweise kommen jetzt wieder 3 Byte vom Master/Slave n-1. Diese überschreiben dann die vorherigen, wobei die vorherigen jeweils an Slave n+1 übertragen werden. Das wiederholt sich immer und immer wieder bis SS vom Master/Slave n-1 deaktiviert wird. Dann wird auch SS für Slave n+1 deaktiviert und die jetzt im Speicher befindlichen Daten werden verwendet. Das würde zwar die ersten 3-Byte zum letzen Chip durch schieben und nicht wie bei den WSxxx-Chips im 1.Chip behalten aber die Reihenfolge kann der Master ja auch umdrehen. Tut ja nicht weh.
:
Bearbeitet durch User
Leo B. schrieb: > Aber mir kam ein anderer Gedanke: > Slave n empfängt 3 Byte, legt dann das 1.Byte zum Senden ins > SPI-Datenregister und aktiviert SS von Slave n+1. Möglicherweise kommen > jetzt wieder 3 Byte vom Master/Slave n-1. Diese überschreiben dann die > vorherigen, wobei die vorherigen jeweils an Slave n+1 übertragen werden. > Das wiederholt sich immer und immer wieder bis SS vom Master/Slave n-1 > deaktiviert wird. Dann wird auch SS für Slave n+1 deaktiviert und die > jetzt im Speicher befindlichen Daten werden verwendet. > > Das würde zwar die ersten 3-Byte zum letzen Chip durch schieben und > nicht wie bei den WSxxx-Chips im 1.Chip behalten aber die Reihenfolge > kann der Master ja auch umdrehen. Tut ja nicht weh. Eigentlich müßte man es umgekehrt machen: Wenn SS aktiviert wird, liest der Slave die ersten 3 Byte und verwendet sie. Kommen weitere, solange SS immer noch aktiv ist, aktiviert er selbst sein SS-out zum nächsten und schickt die Bytes die er jetzt bekommt weiter, solange sein SS-input immer noch aktiv ist. Wird sein SS-input deaktiviert, macht er das Byte, daß er gerade in Arbeit hat fertig, und deaktiviert sein SS-out. Die Message wird so bei jedem Slave jedesmal um 3 Byte kürzer. Kein Slave braucht zu wissen, wo er in der Kette plaziert ist und wie lang die Message ist oder sein wird. Die ersten 3 Byte sind auf jedenfall für ihn. Die Clock vom Master-SPI der die Daten weiterreicht sollte man frisch erzeugen, dann hat man weniger Probleme mit Delays bei den Daten. MfG Klaus
Wo ist das Problem? Das SS bei AVR ne reine Softwaresache ist, kann man da machen was man will. Und nen beliebig langes Schieberegister ist doch nicht das Problem: CLK und SS an alle Module parallel, DI vom ersten zum Master, DO zum DI des zweiten usw. Jedes Modul hat einen Buffer von n Bytes und einen Index i, der auf das aktuelle Byte zeigt. Vorgehensweise auf allen Modulen: - Der Counter-Overflow-Irq macht folgendes: Input-Register lesen und Daten in buf[i] abspeichern, i incrementieren (modulo n), buf[i] ins Output-Register schreiben. - Der Pin-Change-Irq von SS macht folgendes: Daten aus dem Buffer zur PWM-Routine übergeben, CLK-Counter und Index resetten. Man muss halt nur "rückwärts" senden - die Bytes die als letztes gesendet werden, landen im ersten Modul. Also z.B. bei n=3 und der Bytefolge 00 11 22 33 44 55 landet 33 44 55 im ersten Module und 00 11 22 im zweiten - genau wie bei hintereinandergeschalteten Schieberegistern. Dass am Anfang Müll weitergeschoben wird (im Buffer und Output-Register noch nichts Sinnvolles), ist egal - der Müll fällt am letzten Modul eh hinten raus. Zur Initialisierung sollte der Master eine lange 0-Folge senden (mindestens ein Byte länger als das gesamte Schieberegister aller Module zusammen) und dann einen Puls auf SS zu geben. Dadurch werden alle Bit- und Byte-Counter synchronisiert und alle PWMs auf 0 gesetzt.
Markus Weber schrieb: > Bringt mich aber wieder zu Frage 1: ein (zumindest grob skizzierter) > Schaltplan wär nicht verkehrt. :-) Und wo wir schon bei Dokumentation sind: Ein Impulsdiagramm würde die Sache sicher verständlicher machen und ewaige Probleme aufdecken, insbesondere wenn man das gleich mit dem der SPI-Schnittstelle gegenüber stellt.
Peter schrieb: > So wie halt ein HC595 oder ähnliches. Ganz genau so macht es das AVR-SPI. Das SPI ist ein 8Bit-SRG, einfach MISO des einen mit MOSI des nächsten verbinden. Du sendest 3 Byte, dann hat der erste das letzte, der 2. das mittlere und der letzte das erste Byte empfangen. Peter schrieb: > Wenn ich nun aber 255,127,0,0,55,125 schicke, sollen die ersten 3 Bytes > direkt an den nächsten Slave weitergeleitet werden. Das geht natürlich nicht. Das SRG ist immer 8Bit lang. Du könntest 3 Pakete a 2 Byte draus machen, also 2 Byte, Pause, 2 Byte, Pause usw. Ein Timerinterrupt erkennt dann die Pause und übernimmt das Byte.
Eine Weitere Möglichkeit wäre wohl, Daten und Takt vom Master parallel an alle Slaves zu schicken und nur das SS durch zu schleifen. Jedes Slave empfängt 3 Byte und aktiviert dann den SS des nächsten Slave. Damit das zuverlässig funktioniert sollte der Master vielleicht eine kleine Pause nach jedem 3er-Block einlegen, damit ein Slave zeit hat seinen Nachfolger zu aktivieren, und der dann auch die Daten so empfängt wie gewünscht und nicht evtl. um ein paar Bit verschoben. Möglichkeiten über Möglichkeiten... Der TO sollte sich vielleicht auch mal ein paar Gedanken machen und einfach ausprobieren. Learning by doing...
Hier noch eine Möglichkeit: Beitrag "Equinox-Uhr mit 60 ATtinys" Immerhin schafft jeder ATtiny damit 3 x 12 Bit PWMs und ist damit jeder WS2812-LED haushoch überlegen.
Wo ist das Problem? Man kann doch problemlos die SPI-Slavas kaskadieren, auch mit der Hardware-SPI der AVRs. In der ISR muss nur das letzte empfangende Byte sofort wieder ins Senderegister schreiben und die letzten 3 Bytes speichern. volatile uint8_t spi1; volatile uint8_t spi2; volatile uint8_t spi3; ISR( SPI_STC_vect ) { spi3 = spi2; spi2 = spi1 spi1 = SPDR; SPDR = SPDR; } Der Master sollte dann aber nach jedem Byte die CLK Leitung kurz ruhen lassen, damit die Slaves ihre ISR ausführen können. Eventuell geht das sogar automatisch da der Master ja selbst in einer ISR steckt, um das nächste Byte zu laden. EDIT: Zusätzlich zur SS Leitung am besten noch eine weitere Leitung benutzen, die dann besagt das die Übertragung abgeschlossen ist. Ähnlich wie der RCK-Pin eines 74xx595. Auch wenn die SS-Leitung die ganze Zeit Low ist und am Ende wieder auf HI geht, kannst du das schwer in der Software auswerten. Theoretisch geht es auch mit einer Leitung wenn du sie zusätzlich auf einen weiteren Pin legst der Interrupt fähig ist. Manche AVRs haben auch PIN-Change-Interrupt für jede Ports, darüber kann man dann auch den SS-Pin nochmal abfragen.
:
Bearbeitet durch User
Christian K. schrieb: > Man kann doch problemlos die SPI-Slavas kaskadieren, auch mit der > Hardware-SPI der AVRs. Korrekt, das geht sowohl mit der Hardware-SPI als auch mit dem USI. > In der ISR muss nur das letzte empfangende Byte sofort wieder ins > Senderegister schreiben Wenn mich meine Erinnerung nicht ganz täuscht, muß man zumindest beim USI nicht mal dies tun, es genügt hier, das USIOIF zurückzusetzen. Das Shift-Register behält doch seinen Inhalt, man muß da nicht extra noch einmal exakt dasselbe erneut reinschreiben. Und bei neueren Tinys braucht man nichtmal mehr zwingend sofort jedes empfangene Byte auslesen, sondern hat knapp acht SPI-Bitzeiten lang Zeit, zu ermitteln, ob es einen überhaupt interessiert, um es dann ggf. noch aus dem Bufferregister des USI auszulesen. Beim Hardware-SPI bin ich mir nicht ganz sicher, ob der Schreibvorgang nach SPDR eventuell nötig ist, um die SPI-Logik wieder "freizugeben". Müßte man glatt mal ausprobieren, ob es auch ohne geht. Ich würde fast vermuten, daß es prinizipiell genauso wie beim USI garnicht nötig ist.
c-hater schrieb: > Beim Hardware-SPI bin ich mir nicht ganz sicher, ob der Schreibvorgang > nach SPDR eventuell nötig ist, um die SPI-Logik wieder "freizugeben". > Müßte man glatt mal ausprobieren, ob es auch ohne geht. Ich würde fast > vermuten, daß es prinizipiell genauso wie beim USI garnicht nötig ist. Du könntest recht haben, das die Zeile SPDR = SPDR; unnötig ist. Eine Daisy Chain hab ich mit AVR-SPI-Slaves noch nicht gemacht. Einfach mal ausprobieren.
asdfasd schrieb: > Vorgehensweise auf allen Modulen: > > - Der Counter-Overflow-Irq macht folgendes: Input-Register lesen und > Daten in buf[i] abspeichern, i incrementieren (modulo n), buf[i] ins > Output-Register schreiben. > > - Der Pin-Change-Irq von SS macht folgendes: Daten aus dem Buffer zur > PWM-Routine übergeben, CLK-Counter und Index resetten. Das ist die richtige Antwort. Die SS-Leitung würde ich aber umtaufen zu RCK um mit der einschlägigen Literatur und üblichen Bezeichnungen dieser Leitung konform zu gehen.
Christian K. schrieb: > In der ISR muss nur das letzte empfangende Byte sofort wieder ins > Senderegister schreiben und die letzten 3 Bytes speichern. Nein, er muss sie verzögern, er braucht einen 2 Byte grossen FIFO-Puffer in jedem Device denn wenn der RCK kommt "gehören" jedem Device genau die 3 Byte die es zuletzt bekommen hat (das was noch im Register steht und die anderen zwei aus dem FIFO), und die gehören dem jeweiligen Device alleine, es soll ja keine Überlappungen geben. > Zusätzlich zur SS Leitung am besten noch Er braucht gar keine SS denn es gibt ja nichts zum selecten, es gibt ja nur einen einzigen (sehr langen) Slave, der ist immer aktiv. Er braucht nur MOSI->MOSI, MISO->MOSI,... , SCK (parallel an alle) und RCK (parallel an alle).
:
Bearbeitet durch User
Doch SS wird benötigt, da die Slaves sonst nicht wissen wann das erste Bit los geht, würde SS Hard auf LOW verdrahtet sein, könnten sie aus den Tritt geraten. Aber man kann das gleiche Signal für SS und RCK nehmen. Er hat geschrieben das er ATTiny841 benutzt. Da würde ich den PCINT0 verwenden und diesen nur auf PORTA7 Triggern, das ist der SS-Pin. In der PCINT0-ISR abfragen ob PA7 HI ist, und dann die Variablen SPI1,2 und 3 auswerten.
:
Bearbeitet durch User
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.