Halli Hallo. Ich hab schwierigkeiten mit meiner DMX-Kommunikation zwischen nem AtMega64 und einem AtMega8. Für das DMX-Protokoll habe ich den Code von Hendrik Hoelscher genommen und etwas angepasst. Meine AtMegas laufen beide mit 14,7456 Mhz per externen Quarz und Fuses sind auch alle richtig gesetzt. Ich habe schon diverse Debugging-Versuche gemacht z.B. ein "x" vom Mega8 zum Mega64 gesendet und über den 2. UART ans Terminal geschickt, das funktioniert. Dann habe ich das andersherum ausprobiert indem ich eine PWM programmiert habe und eine LED mit einem übermittelten Zahlenwert gedimmt habe. Auch das geht. Wenn ich aber ein FrameError erzeuge um ein BREAK-Befehl zu geben, passiert beim Mega8 nix. Er kommt nicht in die if-Abfrage rein (getestet mit einfachem Einschalten einer LED) woraus ich schließe, dass er irgendwie das Framing-Error nicht erkennt. Codeabschnitt Sender:
1 | #define F_CPU 14745600UL |
2 | |
3 | ... |
4 | |
5 | #define BAUD 115200UL // USB |
6 | #define BAUD2 250000UL // DMX HighSpeed |
7 | #define BAUD3 50000UL // DMX LowSpeed |
8 | |
9 | |
10 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden |
11 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate |
12 | |
13 | #define UBRR_VAL2 ((F_CPU+BAUD2*8)/(BAUD2*16)-1) // clever runden |
14 | #define BAUD_REAL2 (F_CPU/(16*(UBRR_VAL2+1))) // Reale Baudrate |
15 | |
16 | #define UBRR_VAL3 ((F_CPU+BAUD3*8)/(BAUD3*16)-1) // clever runden |
17 | #define BAUD_REAL3 (F_CPU/(16*(UBRR_VAL3+1))) // Reale Baudrate |
18 | |
19 | ... |
20 | |
21 | ISR (USART1_TX_vect) |
22 | { |
23 | uint8_t DmxState= gDmxState; // aktuellen DMX Status aus Lokal-Variable laden |
24 | |
25 | if (DmxState == BREAK) |
26 | { |
27 | UBRR1H = 0; |
28 | UBRR1L = UBRR_VAL3>>8; // DMX USART auf 50 kBaud senken |
29 | UDR1 = 0; // BREAK senden |
30 | gDmxState= STARTB; |
31 | } |
32 | else if (DmxState == STARTB) |
33 | { |
34 | UBRR1H = 0; |
35 | UBRR1L = UBRR_VAL2>>8; // Vollgas mit 250kBaud |
36 | UDR1 = 0; // StartByte senden |
37 | gDmxState= DATA; |
38 | gDmxChannel= 0; |
39 | } |
40 | else |
41 | { |
42 | _delay_us(WL); // in Header-Datei regeln. Standardmaessig auf 10 |
43 | uint16_t DmxChannel = gDmxChannel; |
44 | UDR1 = DmxAddr[DmxChannel++]; // Daten senden |
45 | if (DmxChannel == sizeof(DmxAddr)) gDmxState= BREAK; // BREAK ausloesen wenn alle Daten gesendet sind |
46 | else gDmxChannel = DmxChannel; |
47 | |
48 | } |
49 | |
50 | } |
Empfänger:
1 | #define F_CPU 14745600UL |
2 | |
3 | ... |
4 | |
5 | #define BAUD 250000UL // DMX |
6 | |
7 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden |
8 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate |
9 | |
10 | ... |
11 | |
12 | ISR(USART_RXC_vect) |
13 | { |
14 | static uint16_t DmxCount; |
15 | uint8_t USARTstate= UCSRA; // Status vor Daten-Empfang bestimmen ! |
16 | uint8_t DmxByte = UDR; // Daten auselesen |
17 | uint8_t DmxState = gDmxState; // just load once from SRAM to increase speed |
18 | |
19 | empfang = DmxByte; // in die Variable kommt der aktuelle Wert, der über UDR übertragen wurde und wird in der Main-Funktion an eine LED übergeben, die entsprechend blinkt |
20 | |
21 | |
22 | if (USARTstate & (1<<FE)) // BREAK-Status ueberpruefen |
23 | { |
24 | UCSRA &= ~(1<<FE); // Reset (fuer Simulation) |
25 | DmxCount = StartAddress; // ChannelCount resetten |
26 | gDmxState = BREAK; |
27 | PORTC |= (1<<PC4); // Andere LED, die angehen soll, wenn ein Framing-Error erkannt wurde |
28 | } |
29 | |
30 | else if (DmxState == BREAK) |
31 | { |
32 | if (DmxByte == 0){ gDmxState= STARTB; } // Normalen StartCode ermittelt |
33 | else { gDmxState= IDLE; } |
34 | } |
35 | |
36 | else if (DmxState == STARTB) |
37 | { |
38 | |
39 | if (--DmxCount == 0) // Startadresse erreicht ? |
40 | { |
41 | DmxCount= 1; // Counter auf benoetigte Kanaele stellen |
42 | DmxAddr[0]= DmxByte; // Ersten DMX-Wert empfangen |
43 | gDmxState= STARTADR; |
44 | |
45 | } |
46 | } |
47 | |
48 | else if (DmxState == STARTADR) |
49 | { |
50 | DmxAddr[DmxCount++]= DmxByte; // Kanal bestimmen |
51 | if (DmxCount >= sizeof(DmxAddr)) // Alles empfangen ? |
52 | { |
53 | gDmxState= IDLE; // Auf naechsten BREAK warten... |
54 | } |
55 | } |
56 | } |
Ich entschuldige mich, wenn der Codeschnipsel zu lang ist und besser als Anhang hätte gesendet werden sollen, aber das ist eben nur ein Ausschnitt und nicht die gesamte Datei (wegen der Übersicht). MfG, Nico.