Forum: Mikrocontroller und Digitale Elektronik Frame Error Flag rücksetzen


von Amir B. (sticky)


Lesenswert?

Hallo an alle.
Ich Versuch gerade mit der UART meines ATMega168 eine LIN-Nachricht zu 
empfangen (ATA6662 LIN-Transceiver vorgeshaltet).
Das Erste was ich empfange ist das Sync-Break. Das erkenne ich am 
gesetzten Frame Error Flag im Statusregister. Dieses Frame ist laut 
Datenblatt Read-Only. Ich habe aber das gefühl das ich kein weiteres 
Daten-Byte (Sync-Field entspricht 0x55) erhalten kann, weil das Frame 
Error Flag noch gesetzt ist.

Meine Frage wäre nun, weiß jemand wie man das Frame Error Flag 
rücksetzen kann?

Danke

Gruß Sticky

von Amir B. (sticky)


Lesenswert?

kennt sich echt keiner damit aus?

von Stefan E. (sternst)


Lesenswert?

Amir B-a schrieb:

> Ich habe aber das gefühl das ich kein weiteres
> Daten-Byte (Sync-Field entspricht 0x55) erhalten kann, weil das Frame
> Error Flag noch gesetzt ist.

Dein Gefühl täuscht dich.

> Meine Frage wäre nun, weiß jemand wie man das Frame Error Flag
> rücksetzen kann?

Gar nicht. Das setzt sich selber zurück, sobald in UDR ein Zeichen 
steht, das korrekt empfangen wurde.

von Lutz (Gast)


Lesenswert?

Na ja: Das Datenblatt sagt, daß das Flag gültig ist, bis der 
Receive-Buffer UDRn gelesen wird (es gilt ja auch für ihn speziell). 
Also Buffer auslesen und Inhalt im Zweifelfall verwerfen. Es steht 
übrignes noch viel mehr im Datenblatt zum Thema wann was wie ausgelesen 
und geschrieben werden muß. Ehrlich.

von spess53 (Gast)


Lesenswert?

Hi

>Meine Frage wäre nun, weiß jemand wie man das Frame Error Flag
>rücksetzen kann?

Schon mal Datenblatt gelesen?

S.192 (bei mir):
'Always set this bit to zero when writing to UCSRnA.'

MfG Spess

von Lutz (Gast)


Lesenswert?

S.192 (bei mir):
'Always set this bit to zero when writing to UCSRnA.'

Schon, aber es ist readonly und soll nur "for compatibility with future 
devices" so geschrieben werden.

von Amir B. (sticky)


Lesenswert?

@ Spess
Na klar habe ich das Datenblatt gelesen. Was soll immer diese dumme 
Unterstellung!

Ist es nun wahr, daß das Flag von selbst zurück resetzt wird, wenn im 
Empfangsregister ein gültiges Byte steht?

Wie gesgt ich hatte die Vermutung, daß es nicht zurückgesetzt wird, weil 
ich beim Empfangen des Sync-Felds eine Rote LED einschalte (bei einem 
Frame Error eine grüne) diese rote LED leuchtet nur nie.

Hier der Code
1
//Funktion Empfangen
2
uint8_t Receive_Byte(){
3
4
uint8_t status;
5
6
while (!(UCSR0A & (1<<RXC0)))  // warten bis Zeichen verfuegbar
7
        ;
8
status = UCSR0A;
9
if (status & (1<<FE0)){      //wurde ein Break empfangen?
10
return 1;
11
}
12
13
else{
14
return UDR0;          // Zeichen aus UDR an Aufrufer zurueckgeben
15
}
16
}
17
//---------------------
18
void main(){
19
//do_Stuff;
20
}
21
22
ISR (USART_RX_vect) {    //Die Interupt Service Routine wird ausgeführt wenn ein zeichen empfangen wird
23
              
24
  uint16_t TMPchecksum = 0;
25
  uint8_t checksum;      //Hier steht die Enhanced Checksumme
26
  uint8_t ID;          //Hier steht die vom Master versandte ID (ohne Paritätsbits)
27
  uint8_t PID;        //Hier steht die vom Master versandte ID (mit Paritätsbits)
28
  uint8_t ID_adr;        //Hier stehen die oberen drei Bits der ID mit der die Baugruppe angesprochen wird
29
  uint8_t ID_func;      //Hier stehen die unteren drei Bits der ID mit der die Funktionen ausgeführt werden
30
  uint8_t SyncFeld;
31
  uint8_t Sync_Break;
32
33
  //LIN KOMMUNIKATION STARTET HIER
34
  Sync_Break=Receive_Byte();
35
    
36
  if (Sync_Break){        //Ein Frame Error wird durch ein Sync-Break hervorgerufen
37
      
38
    SyncFeld=Receive_Byte();
39
  
40
41
    if (SyncFeld){
42
      //rote LED an (pseudo)    
43
        //grüne LED aus
44
45
      PID    = Receive_Byte();
46
      ID    = PID & 0b00111111;               //ID (ohne Paritätsbits)
47
      ID_adr  = ID >> 3;
48
      ID_func = PID & 0b00000111; 
49
50
      if(Paritaet_Berechnen(PID)) {
51
      
52
      DDRC = (0 << DDC4);
53
      PORTC &= (0<<PC4);//gelbe LED ausschalten
54
55
        if ((ID==0) && (Slave_Address==ID_adr)){        
56
        
57
          for (uint8_t i=0; i<=6; i++){
58
            Send_Byte(Daten[i]);              //gesammelte Daten senden
59
            TMPchecksum= TMPchecksum + Daten[i];  //Checksumme berechnen (CARRY-BIT fehlt noch)!!!!!!!
60
          }
61
        
62
          TMPchecksum = TMPchecksum+PID;        //Enhanced Checksumme!  
63
          //Low-Byte der checksumme + High-Byte der checksumme
64
          checksum  = (uint8_t) ((TMPchecksum & 0x00FF) + (TMPchecksum >> 8));        
65
          checksum= ~checksum;        //Checksumme invertieren
66
          Send_Byte(checksum);        //anschließend die Checksumme senden
67
        }
68
69
        if ((ID == 1) && (Slave_Address==ID_adr)){    
70
          Set_RelaisPB1(1);          //Relais1 einschalten
71
        }
72
73
        if ((ID == 2) && (Slave_Address==ID_adr)){    
74
          Set_RelaisPB1(0);          //Relais1 ausschalten
75
        }        
76
77
        if ((ID == 3) && (Slave_Address==ID_adr)){    
78
          Set_RelaisPB2(1);          //Relais2 einschalten
79
        }
80
81
        if ((ID == 4) && (Slave_Address==ID_adr)){    
82
          Set_RelaisPB2(0);          //Relais2 ausschlaten
83
        }
84
85
        if ((ID == 5) && (Slave_Address==ID_adr)){    
86
          Set_RelaisPB1(1);
87
          Set_RelaisPB2(1);          //Relais1+2 einschlaten
88
        }
89
90
        if ((ID == 6) && (Slave_Address==ID_adr)){    
91
          Set_RelaisPB1(0);
92
          Set_RelaisPB2(0);          //Relais1+2 ausschlaten
93
        }
94
95
        if ((ID == 7) && (Slave_Address==ID_adr)){    
96
          SW_Reset();              //Reset auslösen
97
        }
98
      }//parität
99
      
100
      else 
101
        DDRC = (1 << DDC4);
102
        PORTC |= (1<<PC4);             //gelbe LED eischalten, somit liegt ein Paritätsfehler vor
103
    }//syncfeld
104
  }//FE
105
}//ISR

von Stefan E. (sternst)


Lesenswert?

> Ist es nun wahr, daß das Flag von selbst zurück resetzt wird, wenn im
> Empfangsregister ein gültiges Byte steht?

Ja, ist es.
Aber damit ein gültiges Byte in das Empfangsregister nachrücken kann, 
musst du daraus das fehlerhafte erst mal rausholen. Und genau das tust 
du in deinem Code nicht.

von Falk B. (falk)


Lesenswert?

@  Amir B-a (sticky)

>ich beim Empfangen des Sync-Felds eine Rote LED einschalte (bei einem
>Frame Error eine grüne) diese rote LED leuchtet nur nie.

Besser so.
1
uint8_t Receive_Byte(){
2
3
  uint8_t status, data;
4
5
  while (!(UCSR0A & (1<<RXC0)))  // warten bis Zeichen verfuegbar
6
        ;
7
  status = UCSR0A;
8
  data = UDR0;
9
10
  if ((status & (1<<FE0)) && data==0){      //wurde ein Break empfangen?
11
    return 1;
12
  }
13
  else{
14
    return data;          // Zeichen aus UDR an Aufrufer zurueckgeben
15
  }
16
}

Wie bereits gesagt, UDR muss man IMMER lesen, sonst gibts Stau, denn 
dann wird RXC0 nicht gelöscht! Siehe Datenblatt. Ausserdem sollte man 
ein Break sicherer detektieren, indem man das empfangene Byte auf Null 
prüft.

MfG
Falk

von Stefan E. (sternst)


Lesenswert?

Noch was:
1
Sync_Break=Receive_Byte();
2
    
3
  if (Sync_Break){
Wenn Receive_Byte entweder eine 1 oder das Datenbyte liefert, hat dieser 
Code mit dem Erkennen eines Sync-Break nichts zu tun. Auch wenn 
irgendein Datenbyte empfangen wurde ist die Bedingung true.

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.