LIN-Bus-Unterstützung für MKT-View III/IV

Autor: Wolfgang Büscher, MKT Systemtechnik
Datum: 2016-02-26 (ISO 8601)
Quelldatei ("Master"): <WoBu><ProgrammingTool>..help\LIN_Bus_49.htm
Online: www.mkt-sys.de/MKT-CD/upt/help/LIN_Bus_49.htm

Inhalt

  1. Einleitung
  2. LIN-Bus-Konfiguration im Programmiertool
    1. Verknüpfen von LIN-Bus-Signalen mit UPT-Display-Variablen
    2. Optionen (Einstellungen) für die LIN-Bus-Schnittstelle(n)
    3. Testen der LIN-Bus-Schnittstelle(n)
  3. Zusammenspiel von LIN-Bus und dem Script (in der Applikation)
    1. Senden eines (kompletten) LIN-Frames
    2. Empfang eines (kompletten) LIN-Frames
    3. LIN.SetResponse() : Vorbereiten einer vom LIN-Slave zu sendenden Antwort
Siehe auch (Links zu weiteren Dokumenten):
Handbuch zum Programmiertool : 'Display-Variablen mit Anbindung an openABK', Stichwort-Verzeichnis ('von A bis Z'),
Feature Matrix (mit Übersicht in welchen MKT-Geräten ein LIN-Bus-Monitor, Slave oder Master enthalten ist),
Wikipedia : Grundlagen zum Thema 'Local Interconnect Network' (LIN).

1. Einleitung

Dieses Dokument beschreibt die LIN-Bus-Funktionalität, die in verschiedenen (aber nicht allen) programmierbaren Anzeige-Geräten von MKT Systemtechnik optional zur Verfügung steht.

Hinweis:
Mangels einer geeigneten 'Testumgebung' konnte der im MKT-View (III/IV) implementierte LIN-Master bislang nur unzureichend auf Kompatibilität getestet werden. Bei Interesse am Einsatz der in diesem Dokument beschriebenen Funktionalität nehmen Sie bitte Kontakt mit dem Hersteller auf ( info@mkt-sys.de ).

LIN (Local Interconnect Network) ähnelt in einigen Punkten dem CAN-Netzwerk, basiert aber (bis auf das 'Break-Feld') auf einer einfachen UART-Schnittstelle (Universal Asynchronous Recever / Transmitter). Da (im Gegensatz zu CAN) nahezu jeder Mikrocontroller mindestens eine UART-Schnittstelle enthält, ist LIN (als Slave) kostengünstig implementierbar. Der Konfigurationsaufwand auf der Master-Seite ist allerdings nicht zu unterschätzen.
In jedem LIN-Bus-Frame ("Rahmen") ist ein Identifier, und ein bis zu 8 Bytes großes Datenfeld enthalten. Aufgrund dieser Ähnlichkeit zwischen LIN und CAN wird im MKT-View (und ähnlichen Anzeigegeräten von MKT) auf der Applikationsebene für beide Bussysteme die gleiche Funktionalität verwendet:
  • Empfangene Frames werden, abhängig vom Identifier (6 Bit für LIN, 11 oder 29 Bit für CAN) in 'Signale' zerlegt
  • Jedem im Frame enthaltenen Signal kann eine Display-Variable zugeordnet werden
  • Jede mit CAN oder LIN verbundene Display-Variable enthält eine Beschreibung des Frame-Aufbaus
  • Bei CAN stammt diese Beschreibung i.A. aus einer DBC-Datei
  • Bei LIN stammt diese Beschreibung evtl. aus einer LDF-Datei
        (geplant aber bislang nicht realisiert: Import von LDF, ähnlich wie DBC, im UPT-Programmiertool)
  • Notfalls kann der Aufbau eines LIN-Frames auch wie hier beschrieben direkt im Programmiertool eingegeben werden

Um eine RS-232-kompatible Schnittstelle 'als LIN-Bus' nutzen zu können, ist ggf. ein Pegelwandler erforderlich.
Bei RS-232 erscheint ein logisches '0'-Bit als positive Spannung am 'TXD'-Ausgang des Senders.
Bei LIN wird ein logisches '0'-Bit als 'dominantes Signal' ausgegeben, indem der Sender die LIN-Bus-Leitung per Transistor auf Masse zieht.
Am Ausgang des RS232/LIN-Adapters erscheint das LIN-Signal daher 'positiv' (logisch '0' = 0 Volt, logisch '1' = ca. 12 Volt, je nach Bordspannung).
Ein geeigneter RS232/LIN-Adapter (passend zum MKT-View III / IV) kann ggf. über MKT Systemtechnik bezogen werden.

2. LIN-Bus-Konfiguration im Programmiertool


2.1 Verknüpfen von LIN-Bus-Signalen mit UPT-Display-Variablen


  (Die LIN-Bus-Anbindung an UPT-Variablen war 2016 in Planung; mangels Interesse an der Option 'LIN' wurde der Support im Programmiertool aber nicht weiter entwickelt.)

2.2 Optionen (Einstellungen) für die LIN-Bus-Schnittstelle(n)


Bei neueren Geräten (z.B. MKT-View III / IV) stehen zwei asynchrone serielle Schnittstellen zur Verfügung, die prinzipiell auch als LIN-Bus-Schnittstellen geeignet sind.
Dazu ist allerdings ein externer Pegel-Konverter erforderlich, da weder die Schnittstelle mit 'RS-232'-Pegel, noch die serielle 'GPS-Schnittstelle' (im MKT-View III/IV) mit dem LIN-Bus kompatibel sind.


Abbildung 1: Konfiguration der logischen Schnittstelle 'CAN4' als LIN-Bus im Programmiertool

Mit dem oben gezeigten Einstelldialog (erreichbar unter Optionen .. CAN-/LIN-Bus-Einstellungen) wird aus der 'logischen Schnittstelle' (vorzugsweise CAN4, notfalls auch CAN3) eine LIN-Bus-Schnittstelle. Beim MKT-View IV stehen dazu sowohl die serielle Schnittstelle mit RS-232-Pegel an der LEMO-Buchse (Name: "serial1"), als auch die eigentlich zum Anschluss eines GPS-Empfängers vorgesehene Schnittstelle ("serial2") zur Verfügung.
Hinweis
Serielle Schnittstellen, die wie oben beschrieben 'als LIN-Bus' betrieben werden, sollten von der Applikation nicht mit den Funktionen zum Zugriff auf die serielle Schnittstelle umkonfiguriert werden.

Die Zuordnung von 'logischen' CAN-Ports zu 'physikalischen' als LIN-Bus nutzbaren seriellen Schnittstellen kann gegebenenfalls auch am Gerät im Setup kontrolliert werden. Rufen Sie dazu im Setup den Eintrag 'User Settings' .. 'more CAN settings' auf. Wenn das Gerät neben CAN auch LIN unterstützt, finden Sie unterhalb der Einstellungen für CAN1 und CAN2 auch z.B. die folgenden Einträge für CAN3 und CAN4 (die nur bei manchen MKT-Views auch als LIN-Port nutzbar sind) :

 Main system menu (9)
 EXIT !
 Load program from FILE
 Transfer via CAN = OFF/Auto
 Other transfers ... ▶
 Audio Recorder
 CAN snooper mode
 CAN logger config
 User Settings              
 ...
User settings (5)
 EXIT !
 Save and EXIT
 CAN1 Baudrate = 500
 CAN2 Baudrate = 500
 more CAN settings..   
 nv[0] = 00001234
 nv[1] = 00000815
 nv[2] = 00000000
 ...
 User CAN-bus settings (11)
 EXIT !
 Save and EXIT
   ...
 CAN3: LIN on Serial1 = 0
 CAN3: LIN on Serial2 = 0
 CAN4: LIN on Serial1 = 1   
 CAN3: LIN on Serial2 = 0
   ...

Abbildung 2 : Konfiguration der logischen Schnittstelle 'CAN4' als LIN-Bus im MKT-View
nach dem Laden der weiter oben per Programmiertool erstellten Konfiguration.
Der eingestellte Wert '1' bedeutet in diesem Zusammenhang 'Ja', '0' = 'Nein'.

Durch die oben beschriebene Verknüpfung der Schnittstelle "CAN4" (eventuell auch "CAN3") mit einer seriellen Schnittstelle als LIN-Interface werden fehlerfrei empfangene LIN-Frames automatisch auch an den CAN-Logger / CAN-Snooper weitergegeben. Diese ursprünglich nur für den CAN-Bus entwickelten Zusatzfunktionen sind daher auch als LIN-Logger bzw. LIN-Monitor einsetzbar. Ein kleiner 'Schönheitsfehler' sind dabei noch die z.T. als "CAN3" / "CAN4" angezeigten LIN-Frames. Ferner muss der LIN-Frame-Decoder z.T. 'raten', aus wievielen Datenbytes ein empfangener Frame besteht, denn im Gegensatz zu CAN (mit dem "Data Length Code") fehlt bei LIN-Frames die Angabe der Größe des Datenfelds völlig. Die Entwickler der LIN-Spezifikation gingen wohl davon aus, dass der Empfänger eines LIN-Frames immer die Länge eines empfangenen LIN-Frames 'kennt' (anhand des Frame-Identifiers).
Ein nicht konfiguierter LIN-Bus-Monitor, der zu Testzwecken an ein LIN-Netzwerk ("Cluster") angeschlossen wird, hat dieses 'Wissen' nicht. Solange nicht mit den im folgenden Kapitel vorgestellten LIN-spezifischen Script-Befehlen etwas anderes eingestellt wurde, geht die Firmware im MKT-View davon aus, dass empfangene LIN-Frames genau acht Nutzdatenbytes enthalten.


2.3 Testen der LIN-Bus-Schnittstelle(n)


Zum Testen der LIN-Bus-Schnittstelle (bzw des externen Pegel-Konverters) eignet sich z.B. die im Programmiertool enthaltene Applikation script_demos/LINbusT1.cvt.
Laden Sie diese in zwei geeignete MKT-Views. Verbinden Sie beide per LIN. Starten Sie auf dem einen Gerät die 'Slave'-Emulation (Button 'Slave'), und auf dem anderen Gerät den 'Master mit SCAN-Funktion' (Button 'Scan').
Mit etwas Glück kann als Ersatz für das eine Gerät auch der PC verwendet werden, mit dem im Programmiertool laufenden Simulator. Ein präzises Timing (im Bereich weniger Mikrosekunden) für LIN-spezifischen Besonderheiten wie dem Senden von BREAK und der Slave-Response (nachdem der Slave vom Master zum Senden eines Datenfelds aufgefordert wurde) ist unter Windows nur schwer realisierbar. Das von der LIN-Spezifikation geforderte Timing ist daher nur mit dem 'echten' Gerät erreichbar.


LIN-Bus-Timing mit vom Master gesendeten LIN-Header (gelb, mit RS-232-Pegeln)
  und der vom Slave (MKT-View IV) gesendeten Antwort (blau).

Zur Kontrolle der vom MKT-View empfangenen und gesendeten Telegramme kann z.B. die Trace-Historie verwendet werden.
LIN-Frames können dort (mit der unten gezeigten Einstellung) wie CAN-Messages angezeigt werden.

 Main system menu (9)
 EXIT !
 Load program from FILE
 ...
 CAN snooper mode
 CAN logger config
 User Settings
 ...
 Diagnostics                
 ...
 Diagnostic menu (6)
 EXIT !
 Show version info
 Call Bootloader
 Restore BIOS defaults
 Error History (1)
 Trace History (512)        
 Ethernet Capture (1024)
 Execution Profiler
 ...
 Trace #1 .. 512 of 512; F1=quit, F2=run
 0075.509 4 03C   Rx d 8 7F 06 B2 FF 7F FF FF FF
 0075.547 4 03D   Tx d 8 11 22 33 44 55 66 77 88
 0075.699 4 03C   Rx d 8 7F 06 B2 FF 7F FF FF FF
 0075.737 4 03D   Tx d 8 11 22 33 44 55 66 77 88
 0075.919 4 03C   Rx d 8 7F 06 B2 FF 7F FF FF FF
 0075.956 4 03D   Tx d 8 11 22 33 44 55 66 77 88
 0076.099 4 03C   Rx d 8 7F 06 B2 FF 7F FF FF FF
 0076.136 4 03D   Tx d 8 11 22 33 44 55 66 77 88
         Pg UP    Pg DN    F2:RUN    Menu  
 Trace History Options (8)
 Exit Trace Display
 Back to Trace Display
 Save Trace as file
 Trace file index = 0000
 Show messages from CAN1 = 1
 Show messages from CAN1 = 1
 Show openABK messages   = 1
 Show CAN-via-UDP or LIN = 1 
 ...
Aufruf und Einstellungen der Trace-Historie zur Anzeige von LIN-Frames.

3. Zusammenspiel von LIN-Bus und Script

Da LIN-Bus-Frames ähnlich wie CAN-Bus-Telegramme einen eindeutigen Identifier, und bis zu acht Datenbytes enthalten können, wird zur Kommunikation per LIN (statt CAN) -bis auf eine Ausnahme- keine spezielle API (Application Interface) verwendet.

Stattdessem können LIN-Frames (nicht "LIN-Messages"! (*) ) mit den gleichen Script-Funktionen und Event-Handlern gesendet und empfangen wie CAN-Telegramme. Zur Unterscheidung zwischen CAN und LIN dienen die höchstwertigen Bits (Bit 31 und 30) im Identifier-Feld des Script-Datentyps tCANmsg :
  • durch eine bitweise ODER-Verknüpfung des LIN-Frame-Identifiers (0..63) mit der Konstanten cCanIdBit_LIN (0xC00000000)
    werden die oben genannten höchstwertigen Bits gesetzt;
  • wie in Kapitel 2.2 erläutert wurde, muss eine der seriellen Schnittstellen
    per Konfiguration (im Programmiertool) für die Verwendung als LIN-Bus-Port konfiguriert werden;
  • eine derart initialisierte Variable vom Typ tCANmsg kann zum Senden an die Funktion can_transmit übergeben werden.
    Statt einer CAN-Message wird dann ein LIN-Frame gesendet.
    (*) Man beachte die unterschiedliche Bedeutung von 'frames' und 'messages' in der LIN-Spezifikation !
        Ein 'Frame' ist der 'Transport-Rahmen', eine 'Message' wird nur im Zusammenhang mit der Transportschicht (transport layer) verwendet.

3.1 Senden eines (kompletten) LIN-Frames


Hinweis: Das Senden eines 'kompletten' LIN-Frames (mit 'Header' und Datenfeld und Prüfsumme) ist nur für einen LIN-Master zulässig. Ein LIN-Slave darf lediglich Datenfelder senden, nachdem er vom Master dazu aufgefordert wurde ! Details zu dieser LIN-spezifischen Besonderheit folgen in Kapitel 3.3 .

Zum Senden eines kompletten LIN-Frames verwenden Sie die auch für CAN geeignete Funktion can_transmit.

Beispiel zum Senden eines LIN-Frames per Script :

//----------------------------------------------------------------------------
proc LIN_SendRequest(int lin_frame_id)
  local tCANmsg myFrame; 

  myFrame.id    := lin_frame_id | cCanIdBit_LIN;
  myFrame.len   := 8;
  myFrame.dw[0] := 0x44332211; // first four bytes in the data field (as a 32-bit 'DWORD')
  myFrame.dw[1] := 0x88776655; // last  four bytes in the data field (as a 32-bit 'DWORD')
  can_transmit( myFrame ); // if LIN is supported by the hardware, use the CAN-API for LIN !

endproc; // LINSendRequest()
Bei LIN darf nur der 'Master' auf eigene Initiative hin senden. Alle Slaves dürfen nur nach Aufforderung senden, d.h. direkt nachdem sie vom LIN-Master dazu aufgefordert sind. Der (LIN-Frame-)Identifier wird auch in dem Fall nur (aussschliesslich) vom Master 'auf den Bus gelegt'; der (oder die) angesprochenen Slaves müssen innerhalb einer genau festgelegten Zeitspanne ihr Datenfeld anhängen.
Details dazu finden Sie in der LIN-Spezifikation (ehemals bei www.lin-subbus.org), z.B. in V2.2A auf Seite 34 ... 36, Kapitel 2.3.3.2, "Event Triggered Frame" :
      Auch bei 'Event Triggered Frames' bestimmt der Master, wer / wann / was sendet !

Die Implementierung eines 'kompletten' LIN-Masters in der Terminal-Firmware war bei der Erstellung dieser Beschreibung noch nicht vorgesehen. Das Senden von LIN-Frames ist zwar möglich, die Komplexität eines LIN-Masters geht aber weit darüber hinaus (Stichwörter: Scheduling, Signal Management, Task Behaviour, Collision Handling, ....)

Um einen einfachen LIN-Bus-Slave auch im Script implementieren zu können, wurden die folgenden Kapitel beschriebenen LIN-spezifischen Befehle in der Script-Sprache implementiert.

3.2 Empfang eines (kompletten) LIN-Frames



Zum Empfangen kompletter LIN-Frames (mit 'Header' und Datenfeld und Prüfsumme) verwenden Sie die auch für CAN geeignete Funktion can_receive.



3.3 LIN.SetResponse() : Vorbereiten einer vom LIN-Slave zu sendenden Antwort

Dieser Befehl ist ausschliesslich für einen 'per Script' implementierten LIN-SLAVE einsetzbar.
Durch den Aufruf wird dem LIN-Bus-Treiber mitgeteilt, welche Daten als Slave Response gesendet werden sollen, wenn ein externer LIN-MASTER den Slave durch Senden eines bestimmten Frame-Identifiers (im Header) dazu auffordert. Die folgende Abbildung verdeutlicht den zeitlichen Ablauf:

 Struktur eines LIN-Frames (nach LIN-Spezifikation Rev. 2.2A, Kapitel 2.3.1, Seite 29)
                                                                                                      
                      "break                "inter-byte         "response space"                      
                       delimiter"            space"                  .                                
                "Break  .                      .    "Protected       .    maximal 8                   
                 Field" .       Sync field     .     Identifier"     .    Datenbytes    Prüfsumme
               |<----->|.   |<------------->|  .  |<------------->|  .   |<-------->| |<---------->|  
 rezessiv  ____         __   _   _   _   _   ___   _ _ _ _ _ _ _ _ ___..............._   _ _ _  _ ____
 (logisch "H") | min.  |  |s| | | | | | | | |s| |s| | | | | | | | |s|    :::::::::: s |s| | |  | |s|  
               |  13   |  |t|b|b|b|b|b|b|b|b|t  |t|b|b|b|b|b|b|p|p|t     :::::::::: t |t|b|b|..|b|t   
               | Bits  |  |a|0|1|2|3|4|5|6|7|o  |a|0|1|2|3|4|5|0|1|o     :::::::::: o |a|0|1|  |7|o   
 dominant      |_______|  |_| |_| |_| |_| |_|p  |_|_|_|_|_|_|_|_|_|p     :::::::::: p |_|_|_|..|_|p   
 (logisch "L")                                                                                        
                        ^        0x55         ^     0x3D + Parity  ^     ^                         ^   
                       /|\                   /|\                  /|\   /|\                       /|\  
                        |                     |                    |     |                         |   
                       (a)                   (b)                  (c)   (d)                       (e)
                                                                                                      
                                                                                                      
               |<------------ vom LIN-Master gesendet ------------->|    |<--- Antwort vom SLAVE -->| 
                                                                                                      
               |<-- "T_frame,max" = 9 ms für eine LIN-Botschaft mit 8 Datenbytes bei 19.2 kBit/s -->| 
                                                                                                      
Struktur eines LIN-Frames

(a) Ende des vom LIN-Master gesendeten, mindestens 13 Bit langen 'Break'-Felds.

(b) Ende des Sync-Felds, 1 Startbit, 8 Datenbits (Konstante 0x55), 1 Stopbit.

(c) Ende des Frame-Identifiers. Der adressierte Empfänger (LIN-Slave) erkennt daran, ob und wie viele Datenbytes gesendet werden müssen.

(d) Der Slave (in der Lin-Spezifikation: "die Slave-Task") beginnt mit dem Senden des Datenfelds.

(e) Der Slave sendet das Stopbit nach der Prüfsumme. Der LIN-Bus ist wieder 'frei' (rezessiver Zustand).


Würde das vom Slave zu sendende Datenfeld (d) erst in dem Moment per Script erstellt, in dem der vom Master gesendete Frame-Identifier empfangen wurde (c), dann stünden im Script maximal etwa 2.5 Millisekunden (Differenz zwischen "T_frame,max" und "T_frame,min") dafür zur Verfügung. Selbst ein einzelner Task-Wechsel könnte diese Zeit überschreiten. Abhilfe:

Der Slave stellt die von ihm zu sendenden Daten bereits vorher zusammen (z.B. nach dem Empfang eines entsprechenden 'Master-Requests' mit dem Frame-ID 0x3C), und gibt dabei den Frame-ID an, bei dessem Empfang das Datenfeld gesendet werden soll (z.B. 'Slave-Response' mit dem Frame-ID 0x3D).

Ein Beispiel für den Einsatz der Funktion LIN.SetResonse() finden Sie in der Applikation script_demos/LINbusT1.cvt .