Servus zusammen,
ich arbeite zur Zeit an einem kleinen Beleuchtungsprojekt, und im Zuge
dessen soll mein Mega8 DMX-Daten senden (und empfangen, aber das scheint
zu funktionieren)
angelehnt an die bekannte und informative Seite von Hendrik stelle ich
mir das Senden so vor wie im angehängten Code (etwas naiv, ich weis,
aber wo ist der Fehler?)
der Zugehörige Empfänger wartet auf den "Receive complete" Interrupt,
und ein "Frame Error" wird als Reset gewertet.
Der Empfänger tut aber leider gar nichts...
Eine Debug-LED bestätigt mir, das der DMX-Zyklus auf Sender-Seite
permanent durchlaufen wird!
Sind die Pausen zu kurz? Geht das mit BASCOM generell nicht? (wieso?)
Ist es ein Problem wenn der URXC und der UTXC Interrupt gleichzeitig
aktiviert sind? Das Gerät soll, über Dipschalter einstellbar, entweder
DMX empfangen oder senden...
Fragen über Fragen, ich würde mich freuen wenn Ihr mir einen Tipp geben
könnt!
Danke und Viele Grüße
André
1
On Urxc Receive_isr
2
Enable Urxc
3
4
On Utxc Transmission_isr
5
Enable Utxc
6
7
dim Dmxstatus as byte : dmxstatus = 0
8
9
Ucsrc = &B10001110 '8N2
10
11
Enable Interrupts
12
13
udr = 0 ' Einmalige Ausgabe einer null um den ersten "Transmission Complete" Interrupt zu generieren
14
15
'************************
16
'* *
17
'* DMX-Senderoutine *
18
'* *
19
'************************
20
21
Transmission_isr:
22
23
If Dmxstatus = 0 Then 'Bei "Sende Break"
24
Waitus 9
25
$baud = 90900 'niedrigere Baudrate
26
Udr = 0 'erzeugt Frameerror
27
Dmxstatus = 1 '1 = "Sende Nullbyte"
28
End If
29
30
If Dmxstatus = 1 Then 'Bei "Sende Nullbyte"
31
$baud = 250000 'normale Baudrate
32
Waitus 9
33
Udr = 0 'sendet Nullbyte
34
Dmxstatus = 2 '2 = Sende "Rot"
35
End If
36
37
If Dmxstatus = 2 Then 'Bei "Sende Rot"
38
Waitus 9
39
Udr = 128 'Roten Wert senden auf Kanal 1
40
Dmxstatus = 3 '3 = sende Grün
41
End If
42
43
If Dmxstatus = 3 Then 'Bei "Sende Grün"
44
Waitus 9
45
Udr = 128 'Grünen Wert senden auf Kanal 2
46
Dmxstatus = 4 '4 = sende Blau
47
End If
48
49
If Dmxstatus = 4 Then 'Bei "Sende Blau"
50
Waitus 9
51
Udr = 128 'Blauen Wert senden auf Kanal 3
52
Dmxstatus = 5 '5 = sende Rest-Nuller
53
End If
54
55
If Dmxstatus > 4 And Dmxstatus < 50 Then 'Nach Bluem Wert einige Nullen senden
Ich habe zwar keine Ahnung von der "Programmiersprache" Bascom, aber ich
kann mir nicht vorstellen, das bei solchen seriellen Ausgaben, wo es
aufs Timing ankommt (DMX hat doch 250kBaud, oder?), sowas zur
Realisierung des Timings geeignet ist:
>Waitus 9
Du hast es ja eigentlich schon zugegeben:
>hab' so lange am Timing 'rumgebastelt bis es funktioniert hat
Och, Das bekommt man ziemlich genau hin. Im Simulator von BasCom kannst
Du genau sehen und simulieren, wieviele Takte jeder Befehl benötigt. Und
das Timing beim Senden macht ohnehin die UART. Wenn WAITUS zu ungenau
ist, nimmst Du eben NOP - Assemblerbefehle zwischendurch (auf 1 Takt
genau).
Wenn das Programm weiter ncihts machen soll, kannst Du (glaube ich) auch
auf Interrupts ganz verzichten und einfach das Statusbit
(Senden/Empfangen fertig) in der UART pollen, dann sparst Du Dir die
Zeit zum Einstieg in die ISR
Jo, also das exakte Sendetiming (Stichwort 250 kbaud) macht der UART,
hatt nur noch Probleme beim DMX-Timing mit Reset, interbyte-gap und so
weiter, aber mit dem Oszi wars dann recht einfach...
Ach ja, und ich hab das Senden tatsächlich aus der ISR genommmen,
sondern polle im normalen Programmdurchlauf auf das gesetzte
"Transmission Complete"-Bit, dann kommen die anderen Sachen auch nciht
zu kurz...
ich würde diesen Quelltext auch ganz gerne beutzen;-)
Ich arbeite momentan mit dem Tranciver von
http://www.hoelscher-hi.de/hendrik/light/dmxdimmer.htm
Ich habe schon versucht es zum laufen zu bekommen aber irgendwie will es
nicht
1
$regfile = "M8515.dat"
2
$crystal = 8000000
3
4
5
Enable Utxc
6
7
8
Dim Dmxstatus As Byte : Dmxstatus = 0
9
Dim K1 As Byte
10
Dim K2 As Byte
11
Dim K3 As Byte
12
Dim K4 As Byte
13
Dim K5 As Byte
14
Dim K6 As Byte
15
Dim K7 As Byte
16
Dim K8 As Byte
17
18
19
20
Ucsrc = &B10001110 '8N2
21
22
Ddrd.7 = 1
23
Ddre.0 = 1
24
25
26
Portc = &B11111111
27
28
29
30
31
32
33
34
35
36
Enable Interrupts
37
38
Udr = 0 ' Einmalige Ausgabe einer null um den ersten "Transmission Complete" Interrupt zu generieren
39
40
'************************
41
'* *
42
'* DMX-Senderoutine *
43
'* *
44
'************************
45
46
Main:
47
48
K1 = Pinc.0
49
K2 = Pinc.1
50
K3 = Pinc.2
51
K4 = Pinc.3
52
K5 = Pinc.4
53
K6 = Pinc.5
54
55
56
K1 = K1 * 255
57
K2 = K2 * 255
58
K3 = K3 * 255
59
K4 = K4 * 255
60
K5 = K5 * 255
61
K6 = K6 * 255
62
63
64
65
Transmission_isr:
66
67
If Dmxstatus = 0 Then 'Bei "Sende Break"
68
Waitus 9
69
$baud = 9090 'niedrigere Baudrate
70
Udr = 0 'erzeugt Frameerror
71
Dmxstatus = 1 '1 = "Sende Nullbyte"
72
End If
73
74
If Dmxstatus = 1 Then 'Bei "Sende Nullbyte"
75
$baud = 25000 'normale Baudrate
76
Waitus 9
77
Udr = 0 'sendet Nullbyte
78
Dmxstatus = 2 '2 = Sende "Rot"
79
End If
80
81
If Dmxstatus = 2 Then 'Bei "Sende Rot"
82
Waitus 9
83
Udr = K1 'Roten Wert senden auf Kanal 1
84
Dmxstatus = 3 '3 = sende Grün
85
End If
86
87
If Dmxstatus = 3 Then 'Bei "Sende Grün"
88
Waitus 9
89
Udr = K2 'Grünen Wert senden auf Kanal 2
90
Dmxstatus = 4 '4 = sende Blau
91
End If
92
93
If Dmxstatus = 4 Then 'Bei "Sende Blau"
94
Waitus 9
95
Udr = K3 'Blauen Wert senden auf Kanal 3
96
Dmxstatus = 5 '5 = sende Rest-Nuller
97
End If
98
99
100
If Dmxstatus = 5 Then 'Bei "Sende Blau"
101
Waitus 9
102
Udr = K4 'Blauen Wert senden auf Kanal 3
103
Dmxstatus = 6 '5 = sende Rest-Nuller
104
End If
105
106
If Dmxstatus = 6 Then 'Bei "Sende Blau"
107
Waitus 9
108
Udr = K5 'Blauen Wert senden auf Kanal 3
109
Dmxstatus = 7 '5 = sende Rest-Nuller
110
End If
111
112
If Dmxstatus = 7 Then 'Bei "Sende Blau"
113
Waitus 9
114
Udr = K6 'Blauen Wert senden auf Kanal 3
115
Dmxstatus = 8 '5 = sende Rest-Nuller
116
End If
117
118
119
120
121
122
If Dmxstatus > 7 And Dmxstatus < 50 Then 'Nach Bluem Wert einige Nullen senden
123
Waitus 9
124
Udr = 0 '0 senden
125
Dmxstatus = Dmxstatus + 1 'erhöhen
126
End If
127
128
If Dmxstatus = 50 Then 'letzte null gesendet?
129
Waitus 9
130
Dmxstatus = 0 'Status auf "Sende Break" setzen
131
Udr = 0
132
End If
133
134
135
Goto Main
Was Ist der fehler?
Ich habe leider kein Oszi aber der DMX prüfstecker mit den LED's drin
leuchtet mit beiden farben (zu hohe frequenz?)
er hat verschiedene Fehlerchen drinne ... zum Einen
setzt er in der ISR über $Baud die Baudrate, was
dazu führen kann, das sein obig gesetztes 8n2
aufgehoben wird, $baud konfiguriert normalerweise auf
8n1 ... daher verwendet man wenn man im Nachhinein
die Buadrate verändert einfach über Baud, ohne $.
Aber die Buadrate ändern ist find ich eh nicht so elegant,
ich habs so gelöst, dass ich um den FE auszulösen einfach
die UART deaktivierte und dann den Pin auf low setzte.
um dann den ersten Frame wieder zu senden einfach
UDR enablen und drauflos senden.
Die Slaves müssen um DMX konform zu laufen die einzelnen
Frames ohne Pause empfangen können, das Timing sollte daher
beim Senden unkritisch sein.
Ich habe bei mir einfach ein Array angelegt
DIM DMX_Bytes (255) as byte
und hab dann einfach
for x = 1 to 255
printbin DMX_Bytes(x)
next
wobei DMX_Bytes(1) sollte 0 sein und gut ist
Hier noch von mir zum Ablauf ein paar Anmerkungen:
ISR vs. Polling:
Die ISR hat bei mir eine Ausführungszeit von wenigen us, ich verschwende
keine Zeit mit Warten und halte die Zeiten recht genau ein.
Bei Polling würde entweder dauernd auf Platz im Sendepuffer gewartet
werden oder das Timing wäre hinüber, da ich nur hin und wieder
vorbeischaue, ob ich wieder senden darf.
Baudrate heruntersetzen:
Da Schleifen in ISRs böse sind (!) würde ein Timer für die Erzeugung des
Breaks benötigt werden. Diesen spare ich durch Herabsetzen der Baudrate.
Interbyte Gap:
Sieht nicht schön aus und reduziert den Durchsatz - aber sonst spielen
ein paar Gurken von Eurolite verrückt.
Der aktuelle Code hat schon ein paar Revisionen durch und Eure
'Verbesserungen' waren bislang in der Vergangenheit auch mal eingebaut
;-) Aber ich bin weiterhin gespannt.
PS: Bascom ist nicht gerade für seine Performance bekannt - es kann
sein, dass es mit DMX etwas eng werden könnte. Meine Empfehlung ist
daher C.
Viel Erfolg,
Hendrik