Hi,
ich habe einen ATMega2561 (alternativ würde ich auch einen XMega
einsetzen wenn es dort bessere Möglichkeiten gibt) mit 16 Mhz und muss
genau X mal, möglichst schnell an einem Port ein Taktsignal ausgeben
(also den Port togglen). X= immer wieder unterschiedlich zwischen 0 und
5 Millionen
Was wäre da die beste und schnellste Strategie (SPI Clockausgang fällt
leider flach, denn den brauche ich für was anderes)?
Ideal wäe natürlich ein 16 Mhz Taktausgang oder PWM nur die kann ich
beide nicht mitzählen um dann den Taktausgang nach X Takten
abzuschalten. "Normaler" Code ist mir zu langsam (da komme ich
vielleicht auf 1 Mhz, ich brauche aber mehr).
Was gäbe es noch?
Danke für Eure Ideen
Stefan
Stefan schrieb:> Was gäbe es noch?
Externe Zählerstufe (ggf. mit SW-Zähler erweitert) mit Preset und
"Taktabwürgegatter" bei 0.
Mehr Aufwand, aber deutlich schneller als µC-Takt.
>externe Zählerstufe
Danke, aber a) vermutlich zu teuer und b) habe ich leider keinen Platz
mehr dafür auf der Platine.
was ich noch vergaß: der Takt muss NICHT über die Anzahl der Takte (X)
einheitlich rund laufen, wenn zwischendurch mal ein paar ns Pause ist,
ist das egal (wichtig ist die absolute Zeit in der X Takte ausgeschickt
werden, wenn der Takt "stolpert", macht das also nix).
Meine SW Lösung z.B. stolpert, da werden bis zu 3 Schleifen (jeweils max
0-255) ineinandergeschachtelt (alles byteweise zu halten ist immer noch
am schnellsten) und beim Schleifenüberlauf gibt es eine kurze Pause.
Stefan
Mit den Megas ist m.W. kein 16MHz Ausgang möglich, weil per Timer
mindestens halbiert wird.
Es geht jedoch mit den TinyX5, deren Timer mit 64MHz arbeiten kann.
Allerdings nur vom internen RC-Oszillator, also nicht quarzgenau.
A. K. schrieb:> Mit den Megas ist kein 16MHz Ausgang möglich, weil per Timer mindestens> halbiert wird.>> Es geht allerdings mit den TinyX5, dessen Timer mit 64MHz arbeiten kann.> Allerdings nur vom internen R/C-Oszillator, nicht quarzgenau.
Das bringt mich auf eine Idee: Man setzt einen 64MHz-Timer so auf, dass
er ein Signal mit der gewünschten Frequenz erzeugt, zählt die Anzahl der
Takte mit einem synchronen zweiten Timer (welchen man vielleicht sogar
mit Input Capture auf den Taktausgang laufen lässt) und lässt diesen
irgendwann per Output Compare exakt auf die gewünschte Anzahl an Takten
den Taktausgang durch Anhalten des ersten Timers abstellen. Da ist unter
Umständen ein wenig Feintuning nötig, aber es dürfte funktionieren.
Gruß
Jonathan
Die AVRs können zwei Timer ver-multiplexen, üblicherweise Timer 0 und
Timer 1. Nennt sich output-compare-modulator.
Ob sich allerdings damit der Bereich 0...5 Mio einstellen lässt, weiß
ich nicht.
Alternativ mitzählen. Das musst du ja nicht für jeden Zählimpuls machen,
zählen kann der Timer alleine. Du brauchst nur die Überläufe zu zählen,
um dann im letzten Zyklus per CTC auf deine genaue Zykluszahl zu kommen.
In der letzten ISR hälstdu den Timer dann an, die Anzahl Takte für den
Einsprung in die ISR und den out-Befehl ins TCCRB-Register musst du halt
mit berücksichtigen.
Damit bekommst du F_CPU/2 per PWM hin, mit 20Mhz-Quarz sind das lockere
10 Mhz.
Oliver
Stefan schrieb:> Danke, aber a) vermutlich zu teuer und b) habe ich leider keinen Platz> mehr dafür auf der Platine.
a) Ein 74F161 zählt bis 90MHz und kostet 60ct - nicht sooh teuer.
Da käme aber schon noch mehr dazu
b) Dann geht's so nicht :-(
Oliver schrieb:> Die AVRs können zwei Timer ver-multiplexen, üblicherweise Timer 0 und> Timer 1. Nennt sich output-compare-modulator.>> Ob sich allerdings damit der Bereich 0...5 Mio einstellen lässt, weiß> ich nicht.>> Alternativ mitzählen. Das musst du ja nicht für jeden Zählimpuls machen,> zählen kann der Timer alleine. Du brauchst nur die Überläufe zu zählen,> um dann im letzten Zyklus per CTC auf deine genaue Zykluszahl zu kommen.> In der letzten ISR hälstdu den Timer dann an, die Anzahl Takte für den> Einsprung in die ISR und den out-Befehl ins TCCRB-Register musst du halt> mit berücksichtigen.>> Damit bekommst du F_CPU/2 per PWM hin, mit 20Mhz-Quarz sind das lockere> 10 Mhz.>> Oliver
Heh, genau das war auch meine Idee zur selben Zeit. Allerdings muss man
nicht nur den letzten Zyklus per CTC machen, sondern die letzten beiden.
Falls das Abstellen des Timers nämlich exakt einen Takt nach dem letzten
regulären Int kommt, hat man das Problem, dass die ISR noch recht lange
braucht, bis die Ausgabe dann tatsächlich abgestellt ist. Als
Alternative könnte man bei weniger als 512 verbleibenden Takten einfach
per Indirektem Sprung in ein NOP-Feld springen, welches dann die
gewünschte Restverzögerung erzeugt, sodass das Timing immer exakt passt
und man den Timer nicht noch in den CTC umschalten muss.
Gruß
Jonathan
Mit einem Xmega geht das Problemlos. Systemtakt auf 32MHz, Mit
Eventkanal als DMA-Trigger Qelle. Eine Variable mit einem gestzten Bit
für den zu toggelnden Pin und als Zieladresse das Toggelregister eines
Ports.
Mit der Einstellung des Transfercounts der DMA ergibt sich das x-mal
toggeln. fertig. Benötigt nicht mal Prozessorleistung...
Wenn Du mal sagst, was das ganze werden soll, findet man bestimmt eine
viel einfachere Lösung.
Irgendwie beschleicht mich der Verdacht, Du willst nen Zähler-IC als
Output-Expander verwenden.
Ja das klingt in der Tat verdächtig danach. Das wäre aber wirklich eine
Umständliche Lösung. Aber wenn man nur noch ein Pin frei hat... Wobei
man auch dann noch tricksen könnte, je achdem was genau man
beabsichtigt, Z. B. etwas in der Art USART oder 1-Wire. Und sei es auch
nur eine Art Soft-Lösung. Bei mehr als einem Pin oder einem gemeinsamen
Takt käme noch Soft-SPI in Frage. Wobei es bei den soften Lösungen etwas
haarig beim THema möglichst schnell und CPU Zeit wird. Ganz nebenbei
bemerkt:
Wenn das echte SPI nicht permanent kommuniziert, so kann man das
mehrfach belegen wie ein BUS. Man muß sich dann nur entscheiden wie man
die Geräte selektiert. Entweder über das Protokoll per Adressübertragung
oder über ein Chipselekt. Üblich wäre Chipselekt. Aber wir wissen ja
nicht was dranhängt.
Gruß
Carsten
Entweder so wie es Alex mit dem XMega macht, oder einfach mal davon
ausgehen, dass der XMega auch mehr als 1 USART hat mit dem man so etwas
bereit stellen könnte (auch gern im SPI Mode)... der zur Zeit kleinste
aus der A Serie hat schon 5 USARTs und kostet 2,50 €
Grüße
Basti
Wenn Dir 1/6 der Quarzuhr ausreichen, so kannst Du auch eine Schleife in
Form von:
Lade Zähler 0 ... 255
Set Bit in I/O Register 1 Tackzyklus
Dec Zähler 1 T.
Nop 1 T.
Clear Bit in I/O Register 1 Tackzyklus
Breq Set_Bit_Befehl 2 T. bei Sprung
Bei 1/10 Tackt kann man auch 65535 Takte ausgeben.
So war’s zumindest anno ATMega16.
Das ist natürlich nur sinnvoll nur wenn Du's eilig hast und nicht noch
im Hintergrund was machen willst. Sauber und Jitterfrei.