Hallo!
Vorneweg: Ich hab das Forum nach Einträgen mit DMX im Titel durchsucht
und alle bis ca 2005 gelesen. Und: Ich kenne die AVRs, mag sie auch,
will das aber mit diesem Board schaffen. Assembler kann ich bedingt
lesen, nicht schreiben und die Seiten von Holger dazu kenne ich :)
Ich versuche seit gestern DMX-Daten mit dem EUROScope-Board von Fujitsu
zu senden. Darauf ist ein Fujitsu 96F340HSB mit 56MHz. Inzwischen bin
ich soweit, dass das DMX-Signal auf dem Oszi gut aussieht, hier kurz die
Beschreibung des Algorithmus, bevor ihr euch durch den Code quält:
1. UART aus, PIN auf high level, Timer-Reload auf > 100us (Mark before
break)
2. PIN auf low, Timer-Reload auf 176us (Break)
3. PIN auf high, Timer-Reload auf ca 50us (Mark after Break)
4. UART an, Null-Byte in Senderegister, Timer-Reload auf 39us
5. SOLANGE warten bis Senderegister leer, DMX-wert rein BIS alle
DMX-Werte gesendet
Klappt auch soweit ganz gut, nur ich will die Daten ja auch ändern, also
UART0 (DMX sende ich auf UART1) mit ISR verbinden und immer wenn Daten
reinkommen, diese auswerten. Klappte nicht ganz. Nun zum Test: In der
main() eine LED togglen lassen. Ergebnis auf dem Oszi (siehe Foto): Die
LED wird nur getoggelt, wenn DMX zwischen zwei Paketen steht, nicht aber
wenn Bytes gesendet werden. Okay, da bekomme ich alle 39us einen
Interrupt, aber mal ehrlich: das Ding hat 56MHz, das sind 17,Xns pro
Instruktion, er sollte es doch wohl packen, den Interrupt zu bearbeiten
und zwischen den Bytes (die sendet ja der UART), die LED weiter zu
toggeln ... Oder habe ich irgendwas übersehen? Habe es auch schon
probiert, während den Bytes den Timer auszumachen und mit dem
TX-Interrupt vom UART1 zu arbeiten, gleiches Ergebnis. Brauche ich
wirklich alle 39us einen Interrupt? Könnte das mit DMA (die DMX-Werte
werden ohne CPU-Arbeit direkt vom RAM in das Senderegister kopiert)
besser gehen? Ist das nötig? Hat das schon mal jemand gemacht?
Ideen und Kommentare sind wärmstens willkommen
Ok, hier noch ein kleiner Nachtrag:
Auf diesem Bild sieht man, wie die LED (oberer Kanal im Oszi) während
der ersten paar Bytes (DMX signal unten) noch toggelt, später dann aber
nicht mehr ...
Okay, hat sich ziemlich erledigt, danke trotzdem an alle, die sich den
Kopf drüber zerbrochen haben:
1. 8 Datenbits + 2 Stoppbits = 10 Bits also 40us => Falsch!
richtig ist: 1 Startbit + 8 Datenbits + 2 Stoppbits = 11 bits, also
44us
2. Timer-Reload nach jedem DMX-Byte vergessen. Deswegen (und wegen 1.)
hing der immer länger in der "warte bis Senderegister leer" und konnte
nix Anderes mehr verarbeiten.
Bin trotzdem für weitere Optimierungsvorschläge dankbar!
@ Jannis A. (jannis_)
>1. UART aus, PIN auf high level, Timer-Reload auf > 100us (Mark before>break)>2. PIN auf low, Timer-Reload auf 176us (Break)>3. PIN auf high, Timer-Reload auf ca 50us (Mark after Break)
Kann man so machen. Einfacher ist aber, einfach die Baudrate auf die
Hälfte oder so zu stellen und 0x00 zu senden, damit generiert man
automatisch ein BREAK + Pause.
>4. UART an, Null-Byte in Senderegister, Timer-Reload auf 39us
Was zum Geier machst du denn mit dem Timer immer wider? Den braucht man
hier doch gar nicht. Das kann man alles locker mit dem UART TX Interrupt
machen, auch wenn ich die Details des uC nicht kenne. Als Beispiel schau
mal im Artikel Interrupt.
>5. SOLANGE warten bis Senderegister leer,
Nix Warten, Interruptgesteuert arbeiten. Dann dreht deine CPU Däumchen.
Selbst ein AVR ist damit nur mässig ausgelastet.
>Klappt auch soweit ganz gut, nur ich will die Daten ja auch ändern, also>UART0 (DMX sende ich auf UART1) mit ISR verbinden und immer wenn Daten>reinkommen, diese auswerten. Klappte nicht ganz.
Wo ist das Problem? Leg deine DMX Daten in ein Array. Die
DMX-Senderoutine liest daraus, deine whatever Empfangsroutine schreibt
neu Daten rein. Das Array muss als volatile deklariert sein, siehe
Artikel Interrupt.
>Interrupt, aber mal ehrlich: das Ding hat 56MHz, das sind 17,Xns pro>Instruktion, er sollte es doch wohl packen, den Interrupt zu bearbeiten>und zwischen den Bytes (die sendet ja der UART), die LED weiter zu>toggeln
Eigentlich schon.
>... Oder habe ich irgendwas übersehen?
Sicherlich. Z.B, dass man in einem Timerinterrupt NICHT wartet!
> Brauche ich wirklich alle 39us einen Interrupt?
Nöö, du brauchst eigentlich gar keinen Timer. Siehe oben.
> Könnte das mit DMA (die DMX-Werte werden ohne CPU-Arbeit direkt vom RAM > in das
Senderegister kopiert) besser gehen?
Ja.
> Ist das nötig?
Nein.
>Hat das schon mal jemand gemacht?
Sicher. Ich aber nicht direkt. Hab aber schon einige DMX-Empfänger
gebaut, die funktionieren quasi gleich.
MfG
Falk
Ideen und Kommentare sind wärmstens willkommen