CAN Bus

banner
This page describes how the CAN drivers are put together. There is no driver with the protocol code can - connect with CANopen (canopen) or GenericCAN (genericcan) instead.

CAN differs from the other buses PLC4X supports in that the wire carries short, identifier-tagged frames rather than a request/response stream. The transports own the bus access and hand the drivers a uniform frame type; each driver then interprets those frames according to its own application-layer protocol.

Transport and frame model

The CAN transport facade provides a single frame representation that all CAN drivers work against:

  • CanFrame (plc4j/transports/can) - an identifier, up to 8 data bytes, and the standard/extended and remote-transmission-request flags. Standard identifiers are 11 bit (MAX_STANDARD_ID), extended ones 29 bit (MAX_EXTENDED_ID).

  • CanFrameBuilder - obtained from CanFrame.builder(), used by the drivers to construct outgoing frames.

  • CanIdFilter - lets a driver subscribe to a subset of identifiers instead of the whole bus.

Two transports implement this facade: can-socketcan (Linux SocketCAN, the usual choice on real hardware) and can-virtualcan (an in-process bus, useful for tests and for running two PLC4X components against each other without a physical interface).

Driver structure

Each CAN driver is a ConnectionBase implementation that owns a message codec translating between CanFrame and its own protocol frame:

  • CANopen - CANOpenConnection with CANOpenMessageCodec, implementing the CANopen service model (SDO, PDO, NMT, heartbeat).

  • GenericCAN - GenericCANConnection, which applies no application-layer semantics at all and simply maps identifiers to typed payload slices.

Incoming frames arrive from the codec and are dispatched to the subscriptions registered for the matching node id; outgoing writes are encoded and handed straight back to the codec.

Earlier releases interposed a separate CANDriverAdapter between the transport and the driver, with a FrameData interface and per-transport frame types such as SocketCANFrame. That indirection was removed when the drivers were ported to the new SPI: the adapter’s work is now done by the driver’s own connection class, and every transport produces a CanFrame directly.