Forum: Mikrocontroller und Digitale Elektronik Atmega erkennt Framing Error nicht


von Nico D. (Gast)


Lesenswert?

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.

: Verschoben durch Moderator
von Nico D. (Gast)


Lesenswert?

Hat niemand ne Idee dazu ? Ist das Problem so selten ?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nico D. schrieb:
> Ist das Problem so selten ?

Ja, außer dir hat das wohl niemand (ich habe jedenfalls schon FEs
gesehen).  Außerdem ist dein Code reichlich unübersichtlich, man
kann mental nicht erfassen, wann wie welcher state gewechselt wird.

von Falk B. (falk)


Lesenswert?

@  Nico D. (Gast)

>AtMegas laufen beide mit 14,7456 Mhz per externen Quarz und Fuses sind

Das ist zwar ein Baudratenquarz, aber DMX mit 250kBaud keine 
typische Baudrate. Somit laufen deine beiden AVR ziemlich (gleich) 
falsch mit
-8% Fehler. Wenn die zwei unter sich sind kein Problem, aber mit anderen 
DMX Geräten geht das nicht.
Für DMX nimmt man 8 oder 16 MHz.

>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.

Dein Sender sieht OK aus.


>    uint8_t  USARTstate= UCSRA;        // Status vor Daten-Empfang bestimmen !
>    uint8_t  DmxByte   = UDR;        // Daten auselesen
>    uint8_t  DmxState  = gDmxState;      // just load once from SRAM to increase 
speed


Hier wäre ich vorsichtig. Bei den gefühlt eine Million Sonderregleung 
und vor allem NICHTregelungen von C kann es sein, dass die reale 
Reihenfolge der Abarbeitung bei Zuweisung während der Deklaration nicht 
streng definiert ist.
Muss sie aber, sonst geht deine Auswertung schief. Probier's mal old 
school.
1
    uint8_t  USARTstate; // Status vor Daten-Empfang bestimmen !
2
    uint8_t  DmxByte;      // Daten auselesen
3
    uint8_t  DmxState;  // just load once from SRAM to increase speed  
4
5
     USARTstate= UCSRA;        // Status vor Daten-Empfang bestimmen !
6
     DmxByte   = UDR;        // Daten auselesen
7
     DmxState  = gDmxState;      // just load once from SRAM to increase speed

>  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


>if (USARTstate & (1<<FE))            // BREAK-Status ueberpruefen

Sollte prinzipiell reichen, sicherer ist aber ein zusätzliches Prüfen 
von DmxByte==0

Das mit den diversen else if ist mir etwas diffus, pack das lieber in 
einen switch, das ist übersichtlicher und ggf. sicherer.

MfG
Falk

von Mario Rempfer (Gast)


Lesenswert?

Hallo,

das Thema ist zwar schon sehr alt, aber vllt hilfts doch noch...
Nico hast du das inzwischen hinbekommen?

Ich habe exakt das gleiche Problem! Erster Versuch mit einem Atmega16 
und 16MHz Takt.
Habe fast 2 Tage damit verbracht bis ich festgestellt hab das die USART 
Schnitstelle mit völlig falschem Takt läuft und ich habe keine Ahnung 
warum. Die Register sind eigentlich alle Richtig gesetzt und ich habe 
auch das Adressirungsproblem beachtet.
Dann habe ich das ganze mit einem Atmega8 erst mit 8MHz, später auch mit 
12MHz takt getestet. Die USART funktioniert hier, mit gleichen 
Einstellungen, bis auf den Teiler, richtig.
Habe dazu einfach Daten gesendet (senden und empfangen laufen ja immer 
auf gleiche baudrate) und mit dem Oszi die Bit-Zeit überprüft. Diese 
betrug 4µS, was also passt.

Nur bekommen ich keinen einzigen Frame Error und auch keinen Data 
Overflow. Die Schnittstelle empfängt aber Daten und das DMX Signal liegt 
auch zu 100% richtig am µC Pin an(mit dem Oszi getestet)

Habe wirklich alles Versucht und keine Idee an was das noch liegen kann

Gruß,
Mario

von (prx) A. K. (prx)


Lesenswert?

Falsches Forum. Kein Bezug zu GCC.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:
> Falsches Forum. Kein Bezug zu GCC.

Hab' ich verschoben.

Außerdem kapern eines fremden Threads.

Mario, bitte öffne einen eigenen Thread, und liefere genügend von
deinem Code, dass man erkennen kann, wie du die UART benutzt hast.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.