Senden mag ja 'einfach' sein weil das andere Gerät ja bereit sein muss.
Empfangen geht wohl nur per IRQ & ASM.
Hier im Forum fand ich mal auch Bascomcode mit ASM dazu.
Gento
Hallo NG,
nachdem ich bereits DMX-512 Signale senden kann, kommt nun der Empfang dran.
Folgender erster Ansatz:
Ist der Code vom Ansatz her korrekt?Code:$regfile = "m8def.dat" $crystal = 16000000 $baud = 250000 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 2 , Databits = 8 Dim Buffer(513)as Byte Dim Kanal As Word On Urxc Empfang Enable Urxc Enable Interrupts Do Loop Empfang: If ucsra.Fe = 1 Then Kanal = 0 Else If Kanal > 0 Then Buffer(kanal) = Udr End If Incr Kanal End If Return
Günter
Senden mag ja 'einfach' sein weil das andere Gerät ja bereit sein muss.
Empfangen geht wohl nur per IRQ & ASM.
Hier im Forum fand ich mal auch Bascomcode mit ASM dazu.
Gento
Hallo Gento,
Interrupt hab ich doch:
On Urxc Empfang
Das Abspeichern des Kanals müsste doch zu schaffen sein, bis das nächste Byte ansteht.
Wo soll hier Basic zu langsam sein?
Günter
so Code gefunden.
Quelle steht drin.
DMX ist recht Zeitkritisch wegen der hohen Baudrate.Code:'-------------------------------------------------------------------- ' Original von: ' DMX - Dimmer 512 / by DW-Soft ' Dirk Wegener - 2004 - the_clown@web.de '-------------------------------------------------------------------- ' Bearbeitet von Jochen Steinmann ' DMX - SwitchPack ' AVR-Bascom '-------------------------------------------------------------------- ' "Deklaration" m³sste klar sein $regfile = "m32def.dat" 'AT90S2313 $crystal = 16000000 '8MHz Quarz $baud = 250000 'Baudrate 250Kbaud ' ben÷tigete Variablen Dim Dmx_count As Word 'Pakete die auf Ausgõnge zielen Dim Dmx_count_temp As Byte 'Gesendete Pakete Dim Dmx_byte As Byte 'DMX Wert Dim Dmx_clock As Byte 'Spielerei Dim Dmx_adr As Word 'DMX-Adresse Dim Dmx_adr_temp As Byte 'DMX-Adresse (Temp) Dim Dmx_adr_c As Word 'DMX-Adresse (Counter) Dim Dmx_off As Byte 'DMX-Signal noch da? ' UART initialiesieren Print "Start" On Urxc Rec_isr Enable Urxc ' Ports setzen und configurieren Config Pind.6 = Output 'StatusLED Config Portb = Output 'Schaltausgõnge Set Portd.6 ' Anfangsvariablen Festlegen Dmx_count = 0 'kein Paket empfangen Dmx_clock = 16 ' Dmx_adr = 2 'DMX_Adresse 2 Enable Interrupts ' ****************************************************************************** ' Hauptschleife ' ****************************************************************************** Do Waitms 10 Decr Dmx_off If Dmx_off = 0 Then Set Portd.6 End If Loop ' ****************************************************************************** ' Funktion: DMX-Signal emfangen und auswerten ' Dieser Interupt wird beim eintreffen von seriellen Daten ausgef³hrt Rec_isr: $asm 'Programmteil f³r das Auswerten der .def Uart_status = R16 'emfangenen Daten .def Uart_byte = R17 .def Uart_temp1 = R18 IN Uart_status,USR IN Uart_byte,UDR SBRC Uart_status,FE 'Auswertung ob Datenbyte OK RJMP Asm_reset 'bei ³berlõnge des Datenbyte = DMX Reset RJMP Asm_Loop1 'Daten OK---> Asm_reset: LDI Uart_temp1,$00 'Adesszõhler zur³cksetzen STS {Dmx_count_temp} , Uart_temp1 'Daten dem Basicvariablen ³bergeben STS {Dmx_byte} , Uart_byte RJMP Asm_exit Asm_loop1: STS {Dmx_byte} , Uart_byte Asm_exit: $end Asm If Dmx_count_temp <> 0 Then 'emfangene Daten im "Dmx_buf" ablegen Incr Dmx_count 'und den jeweiligen Kanal zuordnen If Dmx_adr_c = Dmx_count Then If Dmx_adr_temp < 9 Then Select Case Dmx_adr_temp Case 1: If 127 <= Dmx_byte Then : Reset Portb.0 : Else : Set Portb.0 : End If Case 2: If 127 <= Dmx_byte Then : Reset Portb.1 : Else : Set Portb.1 : End If Case 3: If 127 <= Dmx_byte Then : Reset Portb.2 : Else : Set Portb.2 : End If Case 4: If 127 <= Dmx_byte Then : Reset Portb.3 : Else : Set Portb.3 : End If Case 5: If 127 <= Dmx_byte Then : Reset Portb.4 : Else : Set Portb.4 : End If Case 6: If 127 <= Dmx_byte Then : Reset Portb.5 : Else : Set Portb.5 : End If Case 7: If 127 <= Dmx_byte Then : Reset Portb.6 : Else : Set Portb.6 : End If Case 8: If 127 <= Dmx_byte Then : Reset Portb.7 : Else : Set Portb.7 : End If End Select Incr Dmx_adr_temp Incr Dmx_adr_c End If End If Else 'bei DMX Reset Variablen setzen Dmx_count = 0 : Dmx_count_temp = 1 Dmx_adr_c = Dmx_adr : Dmx_adr_temp = 1 Decr Dmx_clock 'nur eine Spielerei Toggelt eine LED am PortD.6 beim eintreffen von korrekten DMX Daten If Dmx_clock = 0 Then : Toggle Portd.6 : Dmx_clock = 16 : End If End If Dmx_off
Gento
Hallo Gento,
im Interrupt Rec_ISR wird erst mit ASM superschnell das Byte abgeholt um dann mit Basic im selben Interrupt superlangsam das Byte auszuwerten. Also wenn DAS läuft, dann kann ich beruhigt den ersten Prototyp zusammenlöten...
danke für deine Hilfe!
Günter
ach was ... asm brauchts nicht unbedingt ...
hab mir nen 4-Kanaligen Dimmer für DMX512 gebastel, der
läuft in Bascom einwandfrei ... gar kein Thema
selbst bei 250000 Baud hat der AVR bei 16MHz noch mächtig
zeit für anderes.
Du brauchst den URXC Interrupt, den haste ja und das
Framing Error Flag der UART
Über das Flag setzt Du dann Deinen Bytezähler auf 0 und
im URXC Int zählste dann diesen wieder hoch und schreibst
auf den entsprechenden Platz Deinen Wert ... fertig ist die Laube
Vor den Erfolg haben die Götter den Schweiß gesetzt
Hallo Vitis, hallo Gento,
jetzt hab ich mal nachgerechnet:
ein Frame des DMX-Signals dauert kürzestenfalls 44µs.
Das bedeutet, mein Interrupt darf maximal 44µs dauern denn dann könnte das nächste Byte anstehen. Bei 16MHz dauert:
$asm
.def Uart_status = R16
.def Temp_var = R17
IN Uart_status,USR
SBRC Uart_status,FE0
RJMP Asm_reset
RJMP Asm_kanal
Asm_reset:
ldi temp_var, $00
sts {Kanal}, temp_var
RJMP Asm_exit
Asm_kanal:
$end Asm
Buffer(kanal) = Udr
Incr Kanal
$asm
Asm_exit:
$end Asm
fast genau so lange wie:
If Ucsr0a.fe0 = 1 Then
Kanal = 0
Elseif Kanal > 0 Then
Buffer(kanal) = Udr
Incr Kanal
End If
nämlich ca. 10,875µs. Darum verbleiben 33µs pro Frame für weiteres.
Gespeichert werden alle Werte aller Kanäle in einem riesigen Array ob sie gebraucht werden oder nicht. Das hält den Interrupt kurz und Platz ist ja genug.
Der Rest kommt jetzt in die Mainloop
Günter
sag ich ja ... es bleibt noch massig Zeit.
Zumal das DMX ja meist nicht permanent läuft
Vor den Erfolg haben die Götter den Schweiß gesetzt
@Vitis
kannst du den Bascom-Empfänger-Dimmer-Code veröffentlichen, dann kann Guenter und Andere ihn ev. für sich umstricken.
Vielen Dank dafür!
Hallo Stromi,
sobald ich Hardwaretechnisch soweit bin, werde ich meine Fortschritte melden. Es geht mir dabei in erster Linie darum einen sauberen Code hinzulegen, nicht um einen Code der irgendwie läuft.
Bis jetzt sieht das so aus:
Code:$regfile = "m88def.dat" $crystal = 16000000 $baud = 250000 Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 2 , Databits = 8 Dim Buffer(513)as Byte Dim Dmx_byte As Byte Dim Kanal As Word On Urxc Empfang Enable Urxc Enable Interrupts Do 'Hier werden die Ausgänge von Buffer() bestückt Loop Empfang: If Ucsr0a.fe0 = 1 Then Kanal = 0 Else If Kanal = 0 Then Incr Kanal Else Buffer(kanal) = Udr Incr Kanal End If End If Return
Lesezeichen