DMX512-Sender

Hier stelle ich 2 DMX512-Sender vor: der Erste nutzt die Hardware-USART und Bascom Highlevel Befehle. Beim Zweiten bilde ich das DMX-Signal Bit für Bit nach und erreiche so ein exakt normkonformes Signal. Das Timing ist jedoch auf 8 MHz berechnet, es kann kein anderer Quarz verwendet werden.

DMX512-Sender mit Bascom

Die USART eines AT-Mega bietet eigentlich schon alles, was man zum Senden von DMX-Signalen braucht. Jedoch muß man ein Problem mit Arrays > 255 umschiffen. Deshalb habe ich die 512 Kanäle auf 3 Arrays verteilt. Wenn nicht alle Kanäle gesendet werden müssen, kann man die unnötigen einfach weglassen.

Quellcode

$regfile = "m8def.dat"
$crystal = 16000000
$baud = 250000

Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 2 , Databits = 8 , Clockpol = 1

Dim Puffer1(255) As Byte
Dim Puffer2(255) As Byte
Dim Puffer3(2) As Byte
Dim Null_byte(1) As Byte

Usart_tx Alias Portd.1
Config Usart_tx = Output

Do
Ucsrb.txen = 0                                          'Usart ausschalten
Usart_tx = 0                                            'Reset abfallende Flanke
Waitus 200                                              'minimale Länge des Resets
Usart_tx = 1                                            'Reset aufsteigende Flanke
Ucsrb.txen = 1                                          'Usart einschalten
Waitus 16                                               'MARK zw. RESET und Startbyte min. 8us
Printbin Null_byte(1) ; 1 ; Puffer1(1) ; 255                    'jetzt die Daten
Printbin Puffer2(1) ; 255
Printbin Puffer3(1) ; 2
'Hier dein genialer Code rein...
Loop

DMX512-Sender mit Assemblercode

Für das Senden von DMX512-Signalen habe ich das Signal laut Datenblatt komplett nachgebildet. Das Array Puffer() hält alle Werte der 512 Kanäle. Alle 512 Kanäle werden auch gesendet! Die DMX-Routine liegt in einem Interrupt um ungestört senden zu können.

Achtung! Das Senden mit der Usart des Microcontrollers ist in den meisten Fällen komfortabler und einfacher zu verstehen. Wer jedoch einen Testsender als Ziel hat kann mit der hier vorgestellten Nachbildung Einfluß auf alle Parameter des DMX-Signals nehmen. Dies macht man durch Einfügen von Schleifen mit NOPs, die länger oder kürzer eingestellt werden.

Quellcode

'###############################################################################
'#
'#    DMX 512 Sender 1.2c
'#
'#    (c) Günter Gerold
'#
'#    DMX 512 Signale senden mit Bascom-Basic
'#    Das Timing stimmt nur bei 8 MHz Quarz andere Quarze erfordern eine
'#    Neuberechnung des Timings!
'###############################################################################

$regfile = "m8def.dat"
$crystal = 8000000
'Der Timer0 löst einen Interrupt aus und sendet dann das DMX-Signal
On Timer0 Ontimer0
Timsk.toie0 = 1
Tccr0 = &B00000101
'Der Pin D7 sendet das DMX-Signal
Config Portd.7 = Output
Dmxout Alias Portd.7

'hält den Wert des aktuellen Kanals in der Schleife
Dim Temp As Word
'der aktuelle Kanal in der Schleife
Dim Kanal As Word
'in das Array müssen die Werte der Kanäle reingeschrieben werden
Dim Puffer(513) As Byte

Enable Interrupts

Do
'Hier muß noch dein genialer Code rein!
'Puffer(2) = 123 setzt z.B. DMX-Kanal 2 auf den Wert 123
Loop


'###############################################################################
'#
'#   Das ist der eigentliche DMX512 Generator. Das Einfügen oder Weglassen
'#   selbst von scheinbar unnötigen NOPs führt zu Timingproblemen.
'#
'###############################################################################

Ontimer0:
Timer0 = 70
Dmxout = 1
$asm
.def Tmp1 = R17                                             'Marker
.def Tmp2 = R18
            ldi  Tmp1, $5
Make_loop1:
            dec  Tmp1
            brne Make_loop1
            nop
            nop
$end Asm
For Kanal = 0 To 512                                        '8   'Anzahl der Kanäle
   Temp = Puffer(kanal)                                     '20
   $asm
   .def Temp1 = R17
   .def Temp2 = R18
   .def Txbyte = R19
   Putchar:
      LDS Txbyte, {Temp}                                    '2
      LDI Temp1 , 9                                         '1
      COM Txbyte                                            '1
      SEC                                                   '1
   Putchar0:
      BRCC Putchar1                                         '1 oder 2
      nop                                                   '1
      CBI Portd,Pd7                                         '2
      RJMP putchar2                                         '2
   Putchar1:
      SBI Portd,Pd7                                         '2
      NOP                                                   '1
      nop                                                   '1
   Putchar2:
      LDI Temp2 , $7                                        '1
   Sd_loop0:
      DEC Temp2                                             '1
      BRNE Sd_loop0

      nop
      LSR Txbyte                                            '1
      DEC Temp1                                             '1
      BRNE putchar0                                         '1 oder 2
   $end Asm
   nop
   nop
   nop
   Dmxout = 1                                               '2 genauso schnell wie SBI PORTD,PD7 in Assembler
   $asm
   .def Tmp1 = R17
   .def Tmp2 = R18
   ldi  Tmp1, $1                                            '1
   Make_loop0:                                              '2 Stoppbits
      dec  Tmp1                                             '1
      brne Make_loop0                                       '1 oder 2
   $end Asm
Next Kanal                                                  '10
   $asm
   .def Tmp1 = R17
   .def Tmp2 = R18
   ldi  Tmp1, $7
   Make_loop3:                                              'zusätzlich für Kanal 512
      dec  Tmp1
      brne Make_loop3
   $end Asm
Dmxout = 0
Waitus 88
Dmxout = 1
Return