3.25. CAN-busbasis

CAN (Controller Area Network) werd oorspronkelijk in de jaren 1980 door Bosch ontworpen om alle elektronische regeleenheden in een auto op één korte gedeelde bus aan te sluiten. Het beheerst nog steeds de kabelboom van de auto, maar dezelfde robuustheid, het realtime-gedrag en het multi-masterontwerp maken het tot de standaard veldbus in automatisering, robotica, landbouw- en industriële apparatuur van elke soort.

CAN heeft niet één enkele “controller” en een verzameling “randapparaten” zoals SPI en I2C dat hebben. Elk knooppunt op de bus is een gelijke, en elk knooppunt kan zenden zodra de bus inactief is. Wat dit schaalbaar maakt, is het broadcast-met-arbitrage-ontwerp van de bus.

3.25.1. Broadcast met prioriteitsarbitrage

Elk bericht op een CAN-bus draagt een identifier – 11 bits voor het klassieke standaardframe, 29 bits voor de uitgebreide variant. De identifier is geen adres; hij labelt waar het bericht over gaat (motortoerental, rempedaalstand, accuspanning, enz.). Wanneer een knooppunt een waarde wil verzenden, broadcast het die voorzien van de juiste identifier, en elk knooppunt op de bus ziet de broadcast. Elke ontvanger filtert de bus in hardware om alleen de ID’s eruit te pikken waar het om geeft.

Als twee knooppunten tegelijkertijd proberen te zenden, zorgt het elektrische ontwerp van de bus ervoor dat het bericht met de lagere numerieke identifier wint zonder dat er bits verloren gaan.

De truc zit in de twee elektrische toestanden van de bus: dominant (logisch 0) en recessief (logisch 1). De CAN-draden worden hoog (recessief) gehouden door afsluitweerstanden wanneer geen enkel knooppunt praat; elk knooppunt kan de draden laag trekken (dominant) door stroom te leveren via zijn transceiver. Het resultaat is een wired-AND: als een willekeurig knooppunt de bus dominant aanstuurt, leest de lijn dominant, en hij leest alleen recessief wanneer elk knooppunt hem heeft losgelaten. Dominant wint altijd. (Sommige bronnen noemen dezelfde opzet een wired-OR, waarbij “dominant” als het geactiveerde signaal wordt beschouwd in plaats van de AND van recessieve bits – het fysieke gedrag is in beide gevallen identiek.)

Eén enkele buslijn die hoog wordt gehouden door een afsluitweerstand naar Vcc. Drie knooppunten (A, B, C) hangen aan de bus. De uitgangstrap van elk knooppunt is een diode in serie met een schakelaar naar massa -- de diode wijst van de bus omlaag naar de schakelaar, dus het sluiten van de schakelaar trekt de bus laag via de diode, maar geen enkel knooppunt kan de bus hoog aansturen.

De wired-AND in conceptvorm. Echte CAN voert dezelfde logica uit over een differentieel paar (CAN_H / CAN_L) met de transceivers en afsluitweerstanden verdeeld over beide draden, maar de regel op de bus is dezelfde: elk knooppunt kan dominant trekken, alleen wanneer elk knooppunt heeft losgelaten leest hij recessief.

Arbitrage maakt rechtstreeks gebruik van deze asymmetrie. Elk zendend knooppunt verzendt zijn ID één bit per keer, MSB eerst, en bewaakt de bus terwijl het zendt. Een knooppunt dat een recessief bit op de draad zet maar dominant terugleest, weet dat een ander knooppunt met een lagere ID op datzelfde moment zendt en die bitpositie heeft gewonnen. Het stopt onmiddellijk met het aansturen van de bus en luistert. Het winnende knooppunt ziet ondertussen zijn eigen bits onveranderd uitgaan – vanuit zijn standpunt is er niets ongewoons gebeurd. De ID met het laagste nummer wint omdat zijn dominante bits de recessieve bits overschrijven die de ID’s met hogere nummers anders op dezelfde posities zouden hebben verzonden.

De verliezer wacht vervolgens tot de bus inactief wordt en probeert het automatisch opnieuw. Er zijn geen botsingen, geen verloren berichten – alleen deterministische prioriteitsordening.

Dit is de publish/subscribe-stijl die CAN op grote schaal laat werken: iedereen kan praten, iedereen kan luisteren, en de ID’s maken de dispatching impliciet.

3.25.2. De fysieke bus

De CAN-controller van de MCU stuurt de bus niet rechtstreeks aan. Hij stelt slechts twee 3,3 V CMOS-pinnen beschikbaar – TX (het bit dat hij wil verzenden) en RX (het bit dat hij op de bus ziet) – en die pinnen gaan naar een aparte chip die de CAN-transceiver of PHY wordt genoemd. De transceiver bevindt zich tussen de controller en de werkelijke CAN-draden; het is wat weet hoe het met de bus moet communiceren.

De bus zelf is een differentieel paar van 5 V:

  • CAN_H – de “hoge” draad van het paar.

  • CAN_L – de “lage” draad.

In de recessieve toestand bevinden beide draden zich op ongeveer 2,5 V (het middelpunt van de 5 V-voeding van de bus). In de dominante toestand trekt de transceiver CAN_H omhoog naar ongeveer 3,5 V en CAN_L omlaag naar ongeveer 1,5 V, wat een verschilspanning van ongeveer 2 V over het paar oplevert. Ontvangers bemonsteren het verschil tussen de twee draden, waardoor het signaal immuun is voor common-mode ruis die over lange kabeltrajecten wordt opgepikt.

De tweerichtingstaak van de transceiver:

  • Aan de TX-kant leest hij de single-ended 3,3 V TX-pin van de controller en stuurt hij CAN_H en CAN_L uit elkaar voor dominant of laat hij beide los voor recessief.

  • Aan de RX-kant leest hij het differentiële CAN_H / CAN_L-paar en rapporteert hij een single-ended 3,3 V-niveau op zijn RX-pin terug aan de controller.

Twee afsluitweerstanden van 120 ohm, één aan elk fysiek uiteinde van de kabel, houden de bus op het recessieve middelpunt wanneer geen knooppunt aanstuurt en dempen reflecties die anders het differentiële signaal over lange trajecten zouden verstoren.

3.25.3. Het dataframe

Een standaard CAN-dataframe ziet er op de draad zo uit:

Acht velden in volgorde getekend: SOF (1 bit), ID (11 bits), RTR (1 bit), control (6 bits), data (0 -- 8 bytes), CRC (16 bits), ACK (2 bits), en EOF (7 bits).

Een standaard CAN-dataframe: de velden SOF, ID, RTR, control, data, CRC, ACK en EOF.

Elk veld heeft een specifieke taak:

  • SOF (start of frame). Eén dominant bit dat aangeeft dat een nieuw frame begint en de bitklok van elk knooppunt synchroniseert.

  • ID (identifier). De 11-bits identifier waarop de bus arbitreert. Lager nummer = hogere prioriteit.

  • RTR (remote transmission request). Ingesteld bij een verzoek om data in plaats van een levering van data; ontvangers met een overeenkomende ID reageren door de data zelf te verzenden.

  • Control. Een 6-bits veld dat de datalengte (DLC) en enkele administratieve bits codeert.

  • Data. 0 tot 8 bytes payload (CAN Classic; CAN FD breidt dit uit tot 64 bytes).

  • CRC. In totaal 16 bits: een 15-bits CRC over de voorgaande velden plus een 1-bits CRC-scheidingsteken.

  • ACK. In totaal 2 bits. In het eerste bit – het ACK-slot – laat de zender de lijn los en trekt elk knooppunt dat het frame correct heeft ontvangen hem laag; het tweede bit is een recessief scheidingsteken. Het ontbreken van een ACK vertelt de zender dat geen enkel knooppunt het frame heeft gehoord en dat hij het opnieuw moet proberen.

  • EOF (end of frame). Zeven recessieve bits die het frame afsluiten.

Dit alles wordt door de CAN-controller in hardware gegenereerd en gedecodeerd; software ziet alleen de ID, de data en een paar vlaggen.

3.25.4. Waar CAN past

De ontwerpkeuzes van CAN bepalen zijn niche:

  • Robuust. Differentiële signalering op een getwist aderpaar, ingebouwde foutdetectie, deterministische prioriteitsarbitrage en automatische herhalingen zorgen ervoor dat CAN overleeft in elektrisch lawaaierige omgevingen waar UART en SPI data zouden beschadigen.

  • Multi-master. Elk knooppunt kan op elk moment praten. Er is geen centrale controller vereist en geen enkel knooppunt vormt een single point of failure.

  • Bandbreedtebeperkt. Klassieke CAN bereikt zijn maximum rond 1 Mbit/s; CAN FD breidt dit uit. CAN is het juiste antwoord wanneer de verbinding tussen borden of modules ligt, vaak over meters kabel, met betrouwbaarheid als prioriteit.

  • Protocollen op hogere lagen. De kale CAN-bus zegt niet wat een ID betekent of hoe een lang bericht in fragmenten moet worden opgesplitst. Protocollen op applicatieniveau – CANopen, J1939, ISO-TP/UDS, NMEA 2000 – leggen die regels erbovenop. Een apart item dat het waard is om te kennen is het DBC-bestand: een leverancierspecifiek tekstformaat dat vastlegt welke ID’s welke signalen op bitniveau dragen op een bepaald voertuig of systeem. DBC-bestanden zijn een metadataformaat dat de berichtindeling van één bus beschrijft, geen protocol op zichzelf.

De driver in CAN-bus in code verwerkt het CAN-frame op draadniveau; het mappen van ID’s naar betekenissen is de taak van de applicatie.