Frame Error Flag rücksetzen

OP #1262856
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
#1263251
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.
Gast #1263254
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.
Gast #1263255
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
Gast #1263259
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.
OP #1263324
@ 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
#1263333
> 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.
#1263432
@  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
#1263441
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.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.