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
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.
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.
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
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.
@ 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 |
> 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.
@ 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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.