Forum: Mikrocontroller und Digitale Elektronik AVR: Daten seriell mit min 1 Mbaud ausgeben. Wie?


von Nido (Gast)


Lesenswert?

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!

von user (Gast)


Lesenswert?

spi nehmen

daten in SPDR schreiben
dann pollen auf SPIF im SPSR register
dann neue daten in SPDR schreiben usw

von Marco S. (masterof)


Lesenswert?

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

von Jens (Gast)


Lesenswert?

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...

von Marco S. (masterof)


Lesenswert?

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

von Achim M. (minifloat)


Lesenswert?

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

von baldo_der_baer (Gast)


Lesenswert?

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.

von Achim M. (minifloat)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@  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

von Nido (Gast)


Lesenswert?

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 Modus

Falk 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.

von Peter D. (peda)


Lesenswert?

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

von Mark L. (m2k10) Benutzerseite


Lesenswert?

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

von Achim M. (minifloat)


Lesenswert?

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. ;)

von Falk B. (falk)


Lesenswert?

@  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

von Falk B. (falk)


Lesenswert?

@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 ;-)

von Nido (Gast)


Lesenswert?

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.

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.