Hi Community.
Mit einem AVR, z.B. Mega16 bei 16 MHz Takt, muss ich ein serielles
Datensignal ausgeben mit eigentlich 1,33 Mbaud, d.h. 750 ns breiten
Bits. Ich könnte aber vermutlich auch mit 1 Mbaud leben. Die Ausgabe
soll kontinuierlich Byte für Byte erfolgen, ohne irgendein Protokoll
oder Pausen dazwischen. UART kommt also nicht in Frage.
Nun habe ich mir überlegt, den SPI zu vergewaltigen, denn der ist auch
eigentlich nicht für kontinuierliches Senden ausgelegt. Mit etwas
Trixerei ist es mir fast gelungen, aber so ganz hab ich den Durchbruch
noch nicht.
Ihr werdet mich schlagen... Also: Ich hab den SPI als Slave laufen, denn
erstens kann man den Slave mit beliebigen krummen Taktraten takten und
zweitens kann der SPI Slave über den !SS-Pin in Hardware resettet
werden. Also hab ich mit nem Timer einen 1,33 MHz Takt gemacht und auf
einen Timer-Pin gelegt und diesen außenrum wieder in den SCK-Pin vom SPI
geführt. Dann bleibt noch das Verhängnis, dass der SPI single buffered
ist, ich also eigentlich warten muss, bis eine Übertragung beendet ist
und dann erst das neue Byte ins SPDR legen kann, wodurch eine Pause
entstünde. Wenn ich aber den Timer nutze (CTC-Mode, auch auf externen
Pin und wieder rein in den !SS-Pin) und kurz vor Beendigung der
Byteausgabe den SPI über den !SS-Pin abschieße, dann kann ich pünktlich
im Zeitfenster des nächsten Bytes mit der Ausgabe beginnen und bin
sogesehen kontinuierlich. Das Abschießen des SPI Slave muss dann
passieren, wenn gerade das letzte Bit am MISO gesetzt wurde. Laut
Datenblatt und Praxis bleibt der MISO im letzten Zustand, wenn !SS auf
high geht. Soweit die Theorie und bei etwas langsameren Taktraten klappt
das auch, z.B. mit 0,5 MHz. Leider kommt der SPI bei höheren Frequenzen
nicht mehr klar und das Abschalten per !SS muss früher als beim letzten
Bit passieren.
Hat vielleicht jemand eine Idee dazu oder eine ganz andere Lösung für
die Aufgabe? Im Prinzip muss ich halt Bytes aus dem RAM (liegen in einem
Feld) über nen Pin raustickern.
Danke für Tipps!
Hi Nido,
Wenn du in Assambler programmierst, kannst du die Takte zählen die dein
Prozesser benötig um irgendwelche Befehle zu erledigen. Wenn du jetzt
alle 17 Takte ein Datenbyte in das SPDR-Register schreibst, hast du
maximal Datenrate erreicht. Wenn du vorher noch Abfragst ob das SPIF-Bit
gesetzt ist dauert das zu lange.
In C oder Bascom wird das Vorhaben meiner Meinung nach nicht
funktionieren.
Die nächste wichtige Frage ist ob der AVR es schafft in den 17 Takten
die neue Daten zu erzeugen.
Ich hoffe das ich dir helfen konnte bei deinem Problem
Marco S. schrieb:> alle 17 Takte ein Datenbyte in das SPDR-Register schreibst
Naja, ein Byte hat aber 8 bit, somit erhöht sich der Zeitraum um den
Faktor 8. Trotzdem dürfte es knapp werden, die Sendedaten zu berechnen
und rechtzeitig bereitzustellen.
Btw: Ein Mega16 kann pro Takt einen Befehl abarbeiten? Da bin ich etwas
erstaunt. Ein PIC brauch dafür 4 takte und ich kann mir nicht
vorstellen, dass Microchip da soweit zurück ist...
Hi,
> Naja, ein Byte hat aber 8 bit, somit erhöht sich der Zeitraum um den> Faktor 8. Trotzdem dürfte es knapp werden, die Sendedaten zu berechnen> und rechtzeitig bereitzustellen.
Die SPI braucht mindesten 2 Takte um 1 Bit rauszuschieben.
Da sie maximal fosc/2 als Arbeitstakt erhält.
Des wegen braucht die SPI-Schnittstelle 16 Takte um 8 Bit (1Byte) heraus
zuschieben.
> Btw: Ein Mega16 kann pro Takt einen Befehl abarbeiten? Da bin ich etwas> erstaunt. Ein PIC brauch dafür 4 takte und ich kann mir nicht> vorstellen, dass Microchip da soweit zurück ist...
Das mit dem 4 Takten pro Befehl stimmt. Du darfst nicht vergessen dass
der erste PIC ist von 1975.
Wass mir gerade noch ein gefallen ist, dass wenn man die UART in den
synchronen Übertragungsmodus schaltet. Hast du eine Schnittstelle die
ein zusätzliches Datenregister hat als Buffer, da durch ist das nicht
mehr so zeitkritisch.
Gruß Marco
Jens schrieb:> Ein Mega16 kann pro Takt einen Befehl abarbeiten? Da bin ich etwas> erstaunt. Ein PIC brauch dafür 4 takte und ich kann mir nicht> vorstellen, dass Microchip da soweit zurück ist
Der Takt wird im ATmega intern auf das vierfache, den Core-Takt
hochmultipliziert. Ein Befehl braucht also wie beim PIC immer noch 4
Takte:
Befehl einlesen und Daten#1 holen - Daten#2 holen - Verwursten -
Zieldaten Schreiben. Das geht aber nur mit einfachen Befehlen: In jedem
ATmega-Datenblatt gibt es eine Liste, wieviele Zyklen ein befehl
braucht. Diese Zyklen sind synchron zum Core-Takt, externe Daten von
Portpins usw. müssen aber wegen der Takt-Multipliziererei erst
einsynchronisiert werden. Eine Ausnahme sind hier die ATmegas, die ein
Interface für externe Speicher(zusätzlicher SRAM) besitzen. Dieser muss
nicht erst einsynchronisiert werden.
mfg mf
Das Problem läßt sich meines wissens umgehen wenn man nicht die Standart
SPI Schnittstelle benutzt sondern den USART im syncronen Modus
Damit kann man einen Master Slave Betrieb erreichen aber mit Sende und
Empfangsbuffer
zum senden wird also nur nachgeschaut ob der sendepuffer leer ist und
man kann diesen währen das vorherige Byte noch sendet schon wieder
füllen
Es funtionieren sogar die Interrupts.
Sind 17 Portpins frei?
Dann kannst du vielleicht das hier versuchen:
Der ATmega wird von einem Quarzoszillator versorgt oder gibt den
Haupttakt auf einem Pin aus(kann man bei den kleinen 168/88/48ern so
Konfigurieren).
Den teilst du mit einem Taktteiler-IC(4020?) auf 1MHz runter. Dieser
Takt wird an den Shiftclock von zwei parallel-load serial-out
Schieberegistern gelegt. Deren Dateneingänge kommen an zwei komplette
Ports. Der Load-Pin muss dann vom 17.Portpin bedient werden. Nun hast du
252 Zyklen Zeit, in denen deine Daten aus dem RAM geholt und vorbereitet
werden müssen. Die Fehlenden 4 Zyklen sind der PORT-Out von Data-Lo,
Data-Hi und Load-Pin toggeln.
mfg mf
@ Mini Float (minifloat)
>Der Takt wird im ATmega intern auf das vierfache, den Core-Takt>hochmultipliziert. Ein Befehl braucht also wie beim PIC immer noch 4>Takte:
So ein Quark. Der AVR ist ein RISC Prozessor, der KANN pro Takt einen
Befehl abarbeiten. Stichwort Pipeline.
Die PICs sind vom Design aus den 70ern des etzten Jahrhunderts, dort hat
man das mit dem /4 Taktteiler so gemacht. Das spart u.a. Logikgatter,
die damals noch teuer waren.
"Wenn man keine Ahnung hat, einfach mal Fresse halten."
>ATmega-Datenblatt gibt es eine Liste, wieviele Zyklen ein befehl>braucht.
Eben, und das sind Oszillatortakte, keine Maschinentakte!
> Diese Zyklen sind synchron zum Core-Takt,
Das Wort Core-Takt, abgesehen vom schwachsinnnigen Denglisch, tausch
NIRGENDS in einem Atmel-Dokument auf. Komisch, nicht?
@ Nido (Gast)
>Mit einem AVR, z.B. Mega16 bei 16 MHz Takt, muss ich ein serielles>Datensignal ausgeben mit eigentlich 1,33 Mbaud,
kann man machen, UART auf High Speed Modus stellen, dann braucht ein Bit
= 8 Takte. BRauchst du also einen 10,64 MHz Quarz.
>Bits. Ich könnte aber vermutlich auch mit 1 Mbaud leben. Die Ausgabe>soll kontinuierlich Byte für Byte erfolgen, ohne irgendein Protokoll>oder Pausen dazwischen. UART kommt also nicht in Frage.
Unsinn. Das kann der SEHR gut, der hat nämlich einen Sendepuffer!
>Nun habe ich mir überlegt, den SPI zu vergewaltigen, denn der ist auch>eigentlich nicht für kontinuierliches Senden ausgelegt.
Jain. Aber de Jungs aus der Videoecke Erzeugen per SPI wunderschöne
PAL-Signale, kann also so schlecht nicht sein. Allerdings haben die
Bytes immer eine "Lücke" von zwei CPU-Takten beim AVR.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister#Bekannte_Probleme>Ihr werdet mich schlagen... Also: Ich hab den SPI als Slave laufen, denn>erstens kann man den Slave mit beliebigen krummen Taktraten takten und>zweitens kann der SPI Slave über den !SS-Pin in Hardware resettet>werden. Also hab ich mit nem Timer einen 1,33 MHz Takt gemacht und auf>einen Timer-Pin gelegt und diesen außenrum wieder in den SCK-Pin vom SPI>geführt.
Käse.
>die Aufgabe? Im Prinzip muss ich halt Bytes aus dem RAM (liegen in einem>Feld) über nen Pin raustickern.
Trivial. Geht selbst in C.
Beitrag "Optimierung SPI Ausgabe"
MFG
Falk
Danke für eure ganzen Kommentare.
Jens schrieb:> Trotzdem dürfte es knapp werden, die Sendedaten zu berechnen> und rechtzeitig bereitzustellen.
Nö, die Daten müssen nicht berechnet werden, die liegen im RAM bereit
und es muss nichts weiter gemacht werden, als einen Pointer
durchzuschieben. Ingesamt geht es um 120 Bit = 15 Byte Daten, die
zyklisch ausgegeben werden. Eine weitere Anwendung nimmt gelegentlich
Änderungen an den RAM-Daten vor, die aber nicht zeitkritisch sind.
Marco S. schrieb:> Die SPI braucht mindesten 2 Takte um 1 Bit rauszuschieben.> Da sie maximal fosc/2 als Arbeitstakt erhält.>> Des wegen braucht die SPI-Schnittstelle 16 Takte um 8 Bit (1Byte) heraus> zuschieben.
Ich hab auch immer im Datenblatt gelesen, dass der SPI bis zu fosc/4
Taktrate arbeiten kann. Bei sind es gerade mal fosc/16, d.h. die Lage
müsste doch sehr entschärft sein.
Marco S. schrieb:> Wass mir gerade noch ein gefallen ist, dass wenn man die UART in den> synchronen Übertragungsmodus schaltet. Hast du eine Schnittstelle die> ein zusätzliches Datenregister hat als Buffer, da durch ist das nicht> mehr so zeitkritisch.baldo_der_baer schrieb:> Das Problem läßt sich meines wissens umgehen wenn man nicht die Standart> SPI Schnittstelle benutzt sondern den USART im syncronen ModusFalk Brunner schrieb:> kann man machen, UART auf High Speed Modus stellen, dann braucht ein Bit> = 8 Takte. BRauchst du also einen 10,64 MHz Quarz.
Hier sagen viele, dass UART doch geht. Jetzt bin ich verwirrt oder auch
nur zu doof. Wie kann ich dem UART denn Start- und Stopp-Bits
abgewöhnen? Ich will doch nur Daten senden.
Mini Float schrieb:> Dieser> Takt wird an den Shiftclock von zwei parallel-load serial-out> Schieberegistern gelegt.
In die Richtung habe ich auch schon gedacht. Sollte gehen, ist aber
nicht so elegant. Gute Idee aber trotzdem.
Falk Brunner schrieb:> Jain. Aber de Jungs aus der Videoecke Erzeugen per SPI wunderschöne> PAL-Signale, kann also so schlecht nicht sein. Allerdings haben die> Bytes immer eine "Lücke" von zwei CPU-Takten beim AVR.
Die Lücke tut weh, zumindest wenn sie zur Bytedauer hinzukommt. Wenn ich
es so erreichen könnte, dass die zwei Takte dem letzten Bit im Byte
fehlen, dann wärs super, aber ich weiß nicht wie.
Falk Brunner schrieb:>>die Aufgabe? Im Prinzip muss ich halt Bytes aus dem RAM (liegen in einem>>Feld) über nen Pin raustickern.>> Trivial. Geht selbst in C.>> Beitrag "Optimierung SPI Ausgabe"
Naja, der Beitrag findet eigentlich keine funktionierende Lösung für das
Problem und hat auch nur am Rande etwas damit zu tun.
Die moderneren AVRs (ATmega164) können die UART als SPI-Master
konfigurieren.
Damit hast Du einen Sendepuffer und die Daten können lückenlos gesendet
werden mit max 8MBit bei 16MHz CPU-Takt.
Peter
Nido schrieb:> Hier sagen viele, dass UART doch geht. Jetzt bin ich verwirrt oder auch> nur zu doof. Wie kann ich dem UART denn Start- und Stopp-Bits> abgewöhnen? Ich will doch nur Daten senden.
Du kannst bei einigen AVRs(bspw.164P) den USART im SPI-Master-Modus
(ohne Start/Stop) betreiben und dort dann die Doppelpufferung verwenden,
damit fällt auch die Lücke weg (zumindest habe ich keine am Fernseher
sehen können).
Mark
Falk Brunner schrieb:> schwachsinnnig
Danke, die Freude ist ganz meinerseits. Schön, dass du dir auch mal die
Aggression des heutigen Tages von der Seele schreiben konntest. Aber mal
zurück zum Thema:
Du glaubst doch selber nicht, dass die dir im Datenblatt genau erklären,
wie der Aufbau ist.
Es muss mindestens einen doppelphasigen oder schnelleren Takt geben,
anders kann die Befehls-/Ablaufsteuerung, welche auf steigende und
fallende Flanke kommt(so die schönen Diagramme), nicht realisiert
werden. Es sei denn, man setzt hier auf eine nichtsynchrone Verzögerung
aus Dreckeffekten und Gatterlaufzeiten. Davon gehe ich nicht aus. Das
muss ein deterministischer Automat sein.
mfg mf
PS: Ich habe gerade einen ATmega mit dem Seitenschneider aufgemacht.
Nun nach deiner Art eine Beschreibung von dem, was ich wirklich sehen
konnte.
Falk Brunner schrieb:> Stichwort Pipeline
Mir sind keine Ölfelder, Punpen und auch keine dicken Rohre aufgefallen.
Von Pipelining kann also niemals die Rede sein. ;)
@ Nido (Gast)
>Hier sagen viele, dass UART doch geht. Jetzt bin ich verwirrt oder auch>nur zu doof. Wie kann ich dem UART denn Start- und Stopp-Bits>abgewöhnen?
Gar nicht.
>Die Lücke tut weh, zumindest wenn sie zur Bytedauer hinzukommt. Wenn ich>es so erreichen könnte, dass die zwei Takte dem letzten Bit im Byte>fehlen, dann wärs super, aber ich weiß nicht wie.
Geht nicht.
MFG
Falk
@Mini Float (minifloat)
>> schwachsinnnig>Du glaubst doch selber nicht, dass die dir im Datenblatt genau erklären,>wie der Aufbau ist.
Müssen sie gar nicht.
>Es muss mindestens einen doppelphasigen oder schnelleren Takt geben,
Es muss gar nicht. Nur weil DU es nicht kennst bzw. weißt, haißt das
noch lange nix.
>anders kann die Befehls-/Ablaufsteuerung, welche auf steigende und>fallende Flanke kommt(so die schönen Diagramme), nicht realisiert>werden.
Unsinn.
[ ] Du hast Ahnung von CPUs.
Schau dir mal den Picoblaze von Xilinx an, dort ist recht detailiert der
innere Aufbau beschrieben. Und dann wird dir klar, wie sowas
funktioniert.
> Es sei denn, man setzt hier auf eine nichtsynchrone Verzögerung>aus Dreckeffekten und Gatterlaufzeiten.
Tut man nicht, aus gutem Grund.
> Davon gehe ich nicht aus. Das>muss ein deterministischer Automat sein.
Ist er auch ;-)
Peter Dannegger schrieb:> Die moderneren AVRs (ATmega164) können die UART als SPI-Master> konfigurieren.> Damit hast Du einen Sendepuffer und die Daten können lückenlos gesendet> werden mit max 8MBit bei 16MHz CPU-Takt.
Das ist ja klasse und war mir bisher unbekannt. Damit komme ich auf
einen grünen Zweig. Vielen Dank!
Falk Brunner schrieb:> @ Nido (Gast)>>>Hier sagen viele, dass UART doch geht. Jetzt bin ich verwirrt oder auch>>nur zu doof. Wie kann ich dem UART denn Start- und Stopp-Bits>>abgewöhnen?>> Gar nicht.>>>Die Lücke tut weh, zumindest wenn sie zur Bytedauer hinzukommt. Wenn ich>>es so erreichen könnte, dass die zwei Takte dem letzten Bit im Byte>>fehlen, dann wärs super, aber ich weiß nicht wie.>> Geht nicht.
Entschuldigung, Falk, aber deine Posts sind destruktiv und inhaltlich ja
teils nichtmal korrekt. Bitte nicht persönlich nehmen, aber das ist
nunmal nicht hilfreich. Die erste abschmetternde "Gar nicht"-Aussage im
zitierten Post wurde ja von Mark L. und Peter Dannegger schon
wiederlegt. UART ohne Start und Stop geht doch: AVR Typ wechseln und
UART in den SPI-Mode schalten. Laut Datenblatt geht damit ein
kontinuierlicher Datenstrom. Praxistest folgt, wenn ich das IC hab.
Das zweite "Geht nicht" hab ich ja selbst schon widerlegt: Mit dem
rechtzeitigen Abschalten des SPI per Hardware (!SS-Pin im Slave-Mode)
während das Byte noch nicht ganz raus ist, und Wiedereinschalten des SPI
fürs nächste Byte kann ich auch mit dem standard SPI einen Datenstrom
ohne Lücke ausgebenen. Das steht hier vor mir und bei Bedarf könnte ich
ein Bild vom Oszi machen. Läuft derzeit auf einem Mega16, habs auch mit
dem Mega8 schon gemacht. Hier ist das Aber, dass ich damit nicht viel
mehr als 0,5 MBaud schaffe, aber man kann nicht sagen, dass es
prinzipiell nicht geht.