www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LIN synchronisation


Autor: Amir B-a (sticky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo an alle.

Ich habe ein LIN-Slavemodul gebaut auf dem ein ATMega168 und ein ATA6662 
(LIN-Transceiver) sitzt. Nutze auserdem AVRStudio mit gcc

Ich will mein LIN-Slavemodul auf eine LIN-Header-Nachricht des Masters 
synchronisieren.

Dazu habe ich folgendes Datenblatt gefunden.
http://www.atmel.com/dyn/resources/prod_documents/...

ich versteh nur leider nicht wie ich es anwenden muss.

Kann mir jemand bei der Synchronisation meines Slaves helfen?

Ich danke im voraus.

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich will mein LIN-Slavemodul auf eine LIN-Header-Nachricht des Masters
>synchronisieren.

Die Application Note bezieht sich - nach kurzer Sichtung - mehr auf das 
Autobauding, d.h. Abgleich der Slave-Baudrate auf den Master. 
Insbesondere erforderlich bei Eisatz von RC-Oszillatoren.

Du meinst wahrscheinlich mehr die grundsätzliche Synchronisation auf die 
LIN-Nachricht, oder?

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falls Du die grundsätzliche Synchronisation meinst, geht das wie folgt:

- Im Receive-Interrupt als erstes prüfen, ob ein Framing-Error vorliegt 
(Verdacht auf Break)

- Prüfen, ob das empfangene Byte = 0 ist.

- Ich prüfe zusätzlich zu diesem Zeitpunkt noch, ob der Portpin RXD an 
dieser Stelle ebenfalls noch '0' ist. Nur empfehlenswert bei 
Interrupt-basierender Verarbeitung.

- Empfangs-State-Machine an dieser Stelle auf jeden Fall zurücksetzen, 
ein Break hat immer Vorrang.

- Nächstes Byte sollte ein 0x55 sein (An dieser Stelle kann man einige 
Prozessoren auf das Autobauding mittels 0x55 Character vorbereiten, z.B. 
PIC)

- Als nächstes Byte die ID empfangen. Parität prüfen und feststellen, ob 
ID für einen selbst bestimmt ist.

- Je nach geplanter Frame Datenrichtung nun 1..8 Datenbytes senden oder 
empfangen.

- Checksumme empfangen und prüfen oder Checksumme berechnen und senden.

- Fertig.


Die Prüfung mittels Framing Error mag einigen Usern nicht genügen, sie 
hätte theoretisch noch einige Unzulänglichkeiten. In der Praxis machen 
das aber viele Implementationen so. Ich auch.

Autor: Amir B-a (sticky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Harald wrote:


> Du meinst wahrscheinlich mehr die grundsätzliche Synchronisation auf die
> LIN-Nachricht, oder?

ja!

mein code
ISR (USART_RX_vect) {    //Die Interupt Service Routine wird ausgeführt wenn ein zeichen empfangen wird
              //(LIN KOMMUNIKATION STARTET HIER)
  uint16_t TMPchecksum = 0;
  uint8_t checksum;
  uint8_t ID;

    Receive_Byte();
//(LIN KOMMUNIKATION STARTET HIER)
  if (FE0==1){        //Ein Frame Error wird durch ein Sync-Break hervorgerufen
    Receive_Byte();      
    if (SyncFeld==0x55){

      PID = Receive_Byte();
      //ID = PID
      

      if (ID ==0 && Slave_Address==0){        
        
        for (uint8_t i=0; i<=6; i++){
          Send_Byte(Daten[i]);              //gesammelte Daten senden
          TMPchecksum= TMPchecksum + Daten[i];  //Checksumme berechnen (CARRY-BIT fehlt noch)!!!
        }

        
        TMPchecksum = TMPchecksum+PID;        //Enhanced Checksumme!
        
        //Low-Byte der checksumme + High-Byte der checksumme
        checksum  = (uint8_t) ((TMPchecksum & 0x00FF) + (TMPchecksum >> 8));
        
        checksum= ~checksum;        //Checksumme invertieren
        Send_Byte(checksum);        //anschließend die Checksumme senden
      }

      if (ID == 1 && Slave_Address==0){    
        Set_Relais(0,1);          //Relais1 einschalten
      }

      if (ID == 2 && Slave_Address==0){    
        Set_Relais(1,0);          //Relais2 einschalten
      }

      if (ID == 3 && Slave_Address==0){    
        Set_Relais(1,1);          //Relais1 und 2 einschlaten
      }

      if (ID == 4 && Slave_Address==0){    
        SW_Reset();              //Reset auslösen
      }
    }
  }

}//ISR

das ist was ich soweit habe. doch muss ich nicht dafür sorgen, dass sich 
der slave synchronisiert? oder reicht es das ich einen Quarz nutze ?

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du einen Quarz nutzt, sehe ich bei festgelegter Baudrate (nicht 
Norm-konform) für Synchronisation keinen Bedarf. Sonst müsste sich ja 
jede beliebige UART-Schnittstelle auf geeignete Art und Weise 
synchronisieren. Im großen Stückzahl-Bereich tut man sicherlich alles 
dafür, um auf einen Quarz verzichten zu können. Ganz nebenbei sollte ein 
RC-Oszillator auch weniger Ausfallrisiko haben (Quarzbruch etc.). Für 
ein privates Projekt oder Kleinserie indes völlig unerheblich.

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sichte gerade deien Code. Du solltest nicht ernsthaft im Interrupt auf 
neue Bytes warten, das frisst ja deine ganze Rechenzwit auf. Viel besser 
baust Du eine State-Machine auf, stark vereinfacht dargestellt:


if (FramingError) state = 1;

switch (state)
{
case 0 : break; // Standby, nichts zu tun

case 1 : Empfangsbyte==0x55  --> nein= state=0, ja=state++

case 2 : Empfangsbyte==ID ?  --> nein=state=0, ja=state++

case 3 : Bytes in Schleife empfangen/senden

case 4 : Checksumme senden bzw. prüfen --> Gültig=state++ / 
ungültig=state=0

case 5 : Frame an Applikation übergeben, state=0

}

Autor: Amir B-a (sticky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Is es notwendig es in einer statemashine zu machen? Denn ich sammel mit 
meinem Modul Daten mit den ADC und wandle diese um. Das tue ich solange 
bis ich ein Anfrage vom Master erhalte die gesammelten Daten an ihn 
(Master) zu senden.

gibt es eine bessere Möglischkeit?

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie gesagt, ich würde den Code auf State-Machine umstellen. Die meisten 
UART sind ja double-buffered, d.h. ein nachfolgend empfangenes Byte 
schlägt im nächsten Durchlauf auf. In deinem Code gibst Du aber dem 
Break nicht die höchste Priorität. Wenn sich der Master den Abbruch des 
Frames überlegt (ist - glaube ich - in der Norm vorgesehen) würde dein 
Code das nicht berücksichtigen bzw. durcheinander kommen.

Autor: Amir B-a (sticky)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
steht denn im Empfangsregister das Syncbreak solange bis ich es mittels 
receiveByte() abrufe? Erhalte ich beim 2. Aufruf von receiveByte() dann 
das Sync-Field?

tut mir leid die fragen mögen sehr trivial und dumm erscheinen.
uint8_t Receive_Byte(){
  DDRC = (1 << DDC3);       //rote LED einschalten (receive)
    while (!(UCSR0A & (1<<RXC0)))  // warten bis Zeichen verfuegbar
        ;
    return UDR0;          // Zeichen aus UDR an Aufrufer zurueckgeben
  DDRC = (0 << DDC3);       //rote LED ausschalten (receive)
}

Autor: Harald (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin jetzt beim AVR nicht so im Thema. Bei einigen Prozessoren muss 
man nach einem Framing Error erstmal alle Fehler zurücksetzen, bevor es 
weiter geht. In diesem Fall würde es so nicht funktionieren. Baue deine 
Interrupt-Routine so auf, dass immer nur ein Byte verarbeitet wird. Dann 
veranlasst Du alles notwendige und bereitest den Interrupt auf den 
Empfang des nächsten Bytes vor.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.