CAN FD Node based on a PIC18 Microcontroller

Summary of CAN FD Node based on a PIC18 Microcontroller


Summary: This project implements a CAN FD node using the MCP2517FD Click (MCP2517FD controller + ATA6563 transceiver) interfaced via SPI to a PIC18F4520, with firmware developed in Embedded C using MPLAB C18/IDE. It adapts a PIC32 driver to an 8-bit MCU, implements register- and RAM-level SPI routines, configures FIFOs, filters, bit timing, and validates operation via loopback and real CAN FD tests using a sniffer and oscilloscope.

Parts used in the Embedded C CAN FD project:

  • PIC18F4520 microcontroller
  • MCP2517FD Click module (MCP2517FD CAN FD controller + ATA6563 CAN transceiver)
  • MCP2517FD CAN FD controller (on Click)
  • ATA6563 CAN transceiver (on Click)
  • SPI interface lines (SCK, SDI/MISO, SDO/MOSI, nCS)
  • MPLAB IDE and MPLAB C18 compiler
  • MPLAB ICD 3 (programmer/debugger)
  • WaveShare development board (used in development setup)
  • CAN FD sniffer (for monitoring frames)
  • Oscilloscope (for observing CAN_H and CAN_L signals)

The introduction sets the stage for an embedded systems project that involves developing a Embedded C CAN FD project using the MCP2517FD Click module interfaced with the PIC18F4520 microcontroller. The selected development platform—Microchip’s MPLAB IDE with the C language—implies an emphasis on low-level, register-oriented system design and direct control of microcontroller peripherals.

At its essence, this project interacts with relevant communicate protocol issues, including the movement from Classical CAN to CAN FD, which introduced increased data payloads and programmable data rates. Although this work exists within embedded firmware development, has a natural implied understanding of protocol analysis, integrating peripherals(s) and system validation, in particular when used with complimentary tools, like CAN FD sniffers, and oscilloscopes.

The project provides a relevant academic contribution or significance by connecting theory of the CAN protocol to actual use of the protocol. This hands-on approach not only strengthens comprehension of embedded network stack implementation but also builds foundational expertise in real-time system communication design.

Key Points:

  • Introduces CAN FD implementation in a real-world microcontroller environment.

  • Focuses on practical usage of MPLAB IDE for embedded C development.

  • Establishes educational utility through protocol analysis using physical diagnostic tools.

 Objectives of the project

The goal—to build a Embedded C CAN FD project using MCP2517FD and PIC18F4520—expresses a deliberate mix of a contemporary CAN controller with an old school 8-bit microcontroller. The goal expresses an attempt to join performance-limited platforms with new communications protocols, a situation not uncommon in cost-sensitive embedded applications.

Secondary goals expand the project’s technical breadth. By aiming to understand the CAN protocol’s internal mechanisms, the project aligns with the conceptual depth required for robust embedded protocol implementation. Although peripheral to the main task, learning to fully exploit MPLAB IDE’s capabilities becomes an enabler for productive firmware development and debugging.

The focus on academic value is especially important. The end result – a node that will send and receive both CAN frames and CAN FD frames – is not only intended to be a demonstrative prototype but also a reusable learning environment. When combined with signalling diagnostic devices (CAN FD sniffers, oscilloscopes), the node will serve as a more direct means of exploring complex learning topics such as arbitration, frame structure, or error signaling.

Key Points:

  • Develop a working CAN FD node using MCP2517FD and PIC18F4520.

  • Study core elements of the CAN/CAN FD protocol.

  • Learn MPLAB IDE features to enhance firmware development.

  • Provide an academic tool for real-time protocol inspection.

Scope of the project

This section establishes that the project is explicitly software-focused, meaning no hardware modifications will be performed. This choice allows for deeper exploration of embedded software constructs such as device drivers, register-level SPI communication, and message management using FIFO structures.

The emphasis on writing a custom driver for the MCP2517FD controller illustrates a non-trivial engineering task. Such drivers must handle a wide range of protocol features, including bit timing configurations, frame parsing, CRC generation, and interrupt management.

In addition, the project’s exploration of filtering and masking mechanisms—essential for realizing effective network traffic management in high-load CAN systems—will be a fundamental aspect of the project.

In addition, the node operates on a real CAN network (not a simulated one); therefore, we have an additional challenge of timing accuracy, contention due to synchronization, and bus contention, which provides a meaningful real-world operational context. This will enhance the usability of the work and mean that any practical solution will consider meaningful real-world viability.

Key Points:

  • Focuses entirely on software/firmware—no hardware design/modification.

  • Develops a new driver to enable MCP2517FD-based CAN FD communication.

  • Utilizes FIFO buffers for message transmission and reception.

  • Implements filters and masks to control incoming message flow.

  • Designed for real-world CAN FD network operation.

SYSTEM

In Embedded C CAN FD project this section outlines the architectural and technological components of the CAN FD node implementation. It systematically shows the communication protocol, controller hardware, microcontroller, and development environment, ultimately developing an integrated embedded system that can communicate with other systems, transmit, and receive CAN FD frames. The system’s modular arrangement demonstrates good engineering practice: each subsection considers a single thing or concept, and builds toward logically completing the entire architecture described in 4.5.

CAN PROTOCOL

This overarching section introduces the Controller Area Network (CAN) protocol in its classical and extended Embedded C CAN FD project . The progression from the historical context of CAN to its modern FD variant effectively frames the protocol’s relevance in embedded communication systems.

CONTROLLER AREA NETWORK

This subsection in Embedded C CAN FD project provides a functional overview of Classical CAN, emphasizing its decentralized, bus-based architecture. The mention of its hostless topology and the use of message-based communication (rather than address-based) aligns with its use by distributed embedded systems, especially in automobile and industrial control networks.

The distinction between dominant and recessive states (which are defined by voltage differences over twisted pair differential lines called CAN_HIGH and CAN_LOW) demonstrates how the protocol can resist noise and electromagnetic interference. Further examination of bit stuffing, synchronization, or the latencies in the transceiver would strengthen its technical rigor.

Key Points

  • Classical CAN supports up to 1 Mbps and 8-byte payloads.
  • All nodes have equal access; arbitration is based on identifier priority.
  • It includes physical, data link, and error-handling layers, but lacks higher-level protocols.
 Physical Layer – Architecture

This excerpt provides a concise yet technically significant explanation of the CAN physical layer and its frame-level communication characteristics, touching on key principles of differential signaling, frame formatting, bit timing, and arbitration logic.

The conversation begins with the differential signaling scheme that has the two complementary lines (CAN_HIGH and CAN_LOW) transmitting a voltage differential to encode the binary states. This technique enhances the electromagnetic immunity of the protocol, which is crucial in electrically noisy environments such as automotive or industrial applications. It also defines how logical values map to voltage states—Recessive (logical 1, ΔV ≈ 0) and Dominant (logical 0, ΔV > 0)—reflecting an active-low logic model in which dominant bits override recessive bits. This asymmetry provides the deterministic properties for the arbitration of bits on the bus allowing real-time prioritization of messages.

 

CAN Voltage Levels. Source
CAN Voltage Levels. Source

The summary of the structure of a CAN data frame—the Start of Frame (SOF), an identifier field (11-bits or 29-bits), data payload (08 bytes), CRC, and control bitsis correct and a foundational definition. The identifier field is important for addressing, but this also acts as the arbitration key for the bus. The lower identifier will have a higher priority than others. This arbitration strategy allows for time-sensitive messages to be sent promptly during times of congestion on the bus (e.g., braking or allowing powertrain timestep delivery). This can provide a better experience for the consumer.

CAN Frame. Source Embedded C CAN FD project
CAN Frame. Source Embedded C CAN FD project

The note on baud rates (250 kbps 1 Mbps), as displayed here, is noting deployable values and represents the deterministic timing constraints for synchronous CAN communication. The rule requiring at least one bit every 5-bit times ensures that nodes remain time-aligned—an indirect reference to bit stuffing, a synchronization technique not explicitly mentioned but inherently related.

Key Points
    1. Differential Pair Naming
      The two lines used in CAN communication are explicitly named as CAN_HIGH and CAN_LOW, which define the physical layer wiring convention.

    2. Voltage Difference of Zero Equals Recessive State
      A voltage difference of zero volts across CAN_HIGH and CAN_LOW represents a Recessive bit (logical ‘1’) on the bus.

    3. Dominant State Corresponds to Voltage Difference
      The Dominant state (logical ‘0’) occurs when a voltage difference exists between the CAN_HIGH and CAN_LOW lines.

    4. Start Bit and Extra Control Bits in Frame Structure
      A CAN data frame includes a start bit, identifier, payload, CRC, and additional control bits, all of which define its complete structure.

    5. Standard vs. Extended Identifier Length
      CAN supports two formats for identifiers: a Standard frame with an 11-bit ID and an Extended frame with a 29-bit ID.

    6. Node-Based Message Filtering
      Each CAN node decides to accept or ignore a message based on the message’s identifier, providing software-level filtering.

    7. Fixed Baud Rates in Automotive Use
      Common baud rates in automotive applications are cited: 250 Kbps (e.g., in commercial trucks) and 500 Kbps (e.g., in passenger cars).

    8. Maximum Bitrate of 1 Mbit/s
      The upper limit for classical CAN bus speed is 1 megabit per second under ideal conditions.

    9. Fixed Bit Transmission Interval
      The protocol requires at least one bit to be transmitted every 5-bit time to maintain clock synchronization across nodes.

    10. Priority Based on Lower Identifier Value
      Arbitration is based on message identifier values, where lower numerical values have higher priority on the bus.

Error Detection

In Embedded C CAN FD project this subsection touches on the robust fault-tolerance mechanisms of the CAN protocol. The dual-counter system (Transmit and Receive Error Counters) and bus-off condition illustrate how CAN ensures network integrity by isolating malfunctioning nodes.

The narrative effectively explains how retransmission and fault confinement are enforced. However, the omission of specific error types—bit errors, stuff errors, form errors, CRC errors, and acknowledgment errors—limits the depth of this discussion. A more rigorous treatment could elaborate on error flagging, active vs. passive error states, and error frames.

Control Area Network with Flexible Data-Rate

The excerpt communicates the merits of CAN FD (Controller Area Network with Flexible Data-Rate) as a critical development against classical CAN protocols and developments due to the increasing requirements for higher bandwidth and real-time data transmission in vehicles. The comments convey the dual capability of the protocol original compatibility, which allows for the support of classical CAN frames, therefore permitting backward interoperability when phased in to legacy automotive applications, which is an important aspect of consideration.

The most relevant advancement raised, it relates to data throughput. The classical CAN protocol was limited to a maximum of 8 byte frame size that effectively capped the size and complexity of data payloads. CAN FD allows for a maximum of 64 bytes per frame, meaning data transmission efficiency has increased dramatically. CAN FD also allows for dynamic bit-rate switching, allowing a higher data phase bit rate when only one node transmitted. This is possible due to the deterministic nature of CAN arbitration and the shared-bus topology, where bit timing can be relaxed once contention has resolved.

Three key bits that differentiate CAN FD from classical CAN are briefly listed:

  • The FDF (FD Format) bit in the control field signals whether the frame is CAN FD or classical CAN, enabling receivers to distinguish formats mid-stream.

  • The RTR (Remote Transmission Request) bit in classical CAN is replaced in CAN FD by the RRS (Reserved Substitution Bit) because remote frames are no longer a part of CAN FD.
  • The BRS indicates whether the data phase should be at a higher bitrate, allowing for higher rates of data transfer after arbitration.

Together these different improvements make CAN FD a protocol that maintains the original CAN characteristics of real-time arbitration and error behaviour but greatly increases throughput and scalability.

CAN frame and CAN FD frame. Source
CAN frame and CAN FD frame. Source
 Key Technical Observations
  1. The CAN FD protocol remains backward compatible with classical CAN by allowing both types of frames to exist in the same protocol.
  2. The amount of data can be expanded from 8 bytes to 64 bytes, improving bandwidth use of larger data sets.
  3. CAN FD can support greater baud rates (greater than 1Mbit/s), especially during the data phase where only one node is controlling the bus.
  4. After transmission at high speed, all nodes must resynchronize, ensuring continued timing accuracy.

  5. CAN and CAN FD share identical frame structures until the arbitration field (SOF through 11/29-bit identifier).

  6. The FDF bit distinguishes frame format.

  7. The RTR bit used in classical CAN is replaced with RRS in CAN FD.

  8. The BRS bit enables a switch to a higher bit rate for the data field only.

CAN vs. CAN FD:

The comparison presented outlines many valid reasons to migrate from Classical CAN to the CAN FD (Flexible Data-rate) protocol, and illustrates the performance-based advantages alongside the ease of migration into existing systems. These improvements correspond to the increased demands of automotive and embedded systems of today, especially for low-latency data acquisition, larger payloads, or real-time actions.

One of the key improvements is the frame duration now being shorter, despite the data payload increasing, as CAN FD can increase the bitrate during the data phase. In a dual-rate mode, the arbitration phase remains compatible with classical CAN, but the data field can be sent faster, reducing communication latency and improving the real-time properties.

In addition, with a data field increasing from 8 bytes to 64 bytes, it has a dual advantage for sending more data per frame while simplifying upper-layer protocols and software design. Developers are not limited to fragmenting the large data into several CAN frames, but rather are able to work with fewer ‘denser’ frames minimizing protocol overhead and CPU activity. For this to happen, it would also have to remediate extended bus occupation, and CAN FD is able to accommodate with an increased bitrate, through its Bit Rate Switch (BRS).

Notably, Embedded C CAN FD project maintains backward compatibility with classical CAN by allowing its controllers to handle both frame formats. This compatibility is crucial for incremental system upgrades, allowing developers to gradually introduce CAN FD nodes without redesigning the entire network infrastructure—an approach that preserves legacy investment while future-proofing the system.

CAN FD Performance. Source
CAN FD Performance. Source

 Key:

  1. Reduced Frame Latency: CAN FD shortens overall transmission time by increasing the bitrate during the data phase.

  2. Dual Bitrate Operation: Arbitration remains at classical CAN speed, while the data field uses a higher bitrate—ensuring compatibility and performance.

  3. Extended Data Payload: Up to 64 bytes per frame vs. 8 in classical CAN—reduces the number of frames and simplifies software logic.

  4. Stronger Error Detection: An enhanced CRC algorithm improves transmission reliability and fault tolerance.

  5. Backward Compatibility: CAN FD controllers can seamlessly process both frame formats, enabling non-disruptive integration.

  6. Increased Data Throughput: Faster data delivery and minimized transmission cycles lead to more efficient bus utilization.

Key Points:

  • CAN FD reduces bus occupancy and increases throughput.
  • More efficient for large data sets and firmware updates.
  • Maintains coexistence with classical CAN nodes on the same bus.

MCP2517FD CLICK:

In Embedded C CAN FD project this subsection presents the MCP2517FD Click. The MCP2517FD Click is an off-the-shelf board that combines the CAN FD controller (MCP2517FD) and the CAN transceiver (ATA6563) in a single module. The modularity makes prototyping easier and reduces development overhead.

MCP2517FD Click. Source
MCP2517FD Click. Source

External CAN FD Controller with SPI Interface

The MCP2517FD is an adaptable and scalable external CAN FD controller that is inexpensive, diminutive, and easily connected through an SPI interface, which makes it versatile. This integration approach is particularly interesting for older microcontrollers or for lowercapacity MCUs that do not inherently support CAN FD or are limited to internal CAN FD channels.

The modularity facilitates a flexible, passive upgrade opportunity in cases where existing systems will be transitioning to ISO 11898-1:2015-compliant CAN FD communication. From a functional aspect, the MCP2517FD is designed as a block-based device, meaning it has distinct subsystems allowing specific protocol, memory, and data functionality. The MCP2517FD architecture prioritizes clearly defined boundaries for the CAN FD protocol in the CAN FD Controller block. This block encompasses all the protocol strategies and provides frame filtering and access to a variety of FIFOs. These FIFO buffers facilitate message queuing and limit the number of CPU interactions, and enable priority up/down transmission and reception techniques which is vital for lowlatency applications.

Module block diagram. Source
Module block diagram. Source

The SPI interface is the primary communication vehicle between the host microcontroller and the MCP2517FD. The main communication with initiates communication with on-chip RAM for indirect access to Special Function Registers (SFRs) to reduce the overhead for the host MCU with respect to the complexity of CAN FD transactions. Low overhead integration is also achieved in terms of performance

 Key points

  1. CAN FD Controller – Implements ISO 11898-1 CAN FD protocol; supports frame filtering, FIFO buffering, and operation in both CAN FD and classic CAN 2.0 modes.

  2. SPI Interface – Facilitates high-speed communication with the host MCU; enables access to internal control registers and memory.

  3. RAM Controller – Manages arbitration between the SPI master and CAN logic to ensure safe and efficient access to internal RAM.

  4. Message RAM – Stores CAN messages; supports both transmit and receive buffers for classic and extended frames.

  5. Oscillator – Generates the internal clock signal required for timing-critical protocol functions.

  6. LDO & POR Circuit – Provides on-chip voltage regulation and reliable startup behavior.

  7. I/O Control – Handles external signal interfacing and status monitoring.

ATA6563 CAN Transceiver

The ATA6563 transceiver ensures reliable signal conversion between digital controller outputs and the physical CAN bus. Its high-speed capabilities and enhanced EMC/ESD protections make it suitable for automotive and industrial use cases.

This subsection accurately reflects the role of the transceiver in ensuring line conformity, differential signaling, and bus behavior under fault conditions (e.g., supply off-state).

Used Pins

This concise table provides a functional mapping of the SPI communication lines used between the PIC18F4520 and MCP2517FD Click. It aligns with industry practice, where dedicated I/O lines are mapped to SPI functionality for full-duplex communication.

Used pins of the MCP2517FD Click. Source
Used pins of the MCP2517FD Click. Source

This mapping is critical for ensuring the correct operation of the external CAN FD controller. Additional commentary on SPI speed limitations or chip select timing could deepen this section’s value.

PIC18F4520

This section describes briefly the profile of the PIC18F4520, highlighting its memory layout, ADC channels, and mixed signal capabilities. The extensive list of pin assignments (RC3-RC5, RB0) gives context as to how the MCU interacts with the MCP2517FD over SPI.

Constraining the 8-bit architecture of microcontroller systems as compared to the one today – available 32-bit architectures, one can say that these are sufficient for many educational and lightweight real-time control applications. There are other positive features like ICSP support, low power consumption, and easy availability, which justify its use in the academic arena.

PIN features. Source
PIN features. Source

Key Points:

  • Sufficient RAM/Flash for communication-centric embedded tasks.
  • SPI-compatible I/O lines for external peripheral interfacing.
  • Suitable for low-cost, low-power prototyping environments.

 MPLAB C COMPILER FOR PIC18 MCUs

In Embedded C CAN FD project this section discusses the usefulness of MPLAB C18, an ANSI C compiler that was specifically designed for PIC18 devices, while tightly integrated with MPLAB IDE to offer a user-friendly debugging and project management environment.

Among its strengths are inline assembly, library support, and modular memory models—important in performance-constrained embedded systems. However, it should be noted that MPLAB C18 has mostly been overshadowed by MPLAB XC8, which comes with better optimization and more modern language features.

Key Points:

  • Supports C and assembly code integration.
  • Compatible with legacy and extended instruction sets.
  • Facilitates efficient debugging and code organization within MPLAB IDE.

ARCHITECTURE OF THE SYSTEM

In Embedded C CAN FD project this subsection synthesizes all preceding hardware and software components into a working system architecture. The workflow—starting from driver development on a PC, interfacing through MPLAB ICD 3 and a WaveShare development board, and ultimately connecting the PIC18 to the MCP2517FD Click—demonstrates a methodical, tiered development strategy.

Computer connected to the node through the MPLAB ICD 3. Source
Computer connected to the node through the MPLAB ICD 3. Source

The inclusion of diagrams (Fig. 7, Fig. 8) enhances the clarity of hardware interconnections. Although the system is not yet connected to a live CAN FD network, the infrastructure is evidently simulation- and test-ready, allowing for controlled validation of driver logic before deployment in real-world networks.

PIC18 connected to the MCP2517FD. Source: Own
PIC18 connected to the MCP2517FD. Source: Own

Key Points

  • Demonstrates end-to-end embedded system integration.
  • Allows driver testing without physical CAN bus exposure.
  • Highlights modularity and adaptability for future real-network testing.

PROJECT

Embedded C CAN FD project

DRIVER DEVELOPMENT
Needed files

In Embedded C CAN FD project this section describes the preliminary steps required for the porting and customization of the CAN FD driver for use with a PIC18F4520 microcontroller, based on code originally designed for a more advanced PIC32MX470 platform. It gives a practical demonstration of reusing already available open-source Microchip resources, which directly corresponds to best practice in embedded systems development and especially in academia or prototyping environments, where development time, resource constraints, and code reliability are primary considerations.

The original driver’s source was developed for 32-bit architecture and had to be customized for working perfectly on 8-bit. The mismatch in architecture made it imperative to review the data structures, memory access patterns, and register-level operations since all these require good understanding of the underlying instruction sets, peripheral interfaces, and memory models of both platforms.

Used files. Source
Used files. Source

A key initial task involved importing the appropriate header and source files essential for CAN FD communication over SPI. These include:

  • Header Files such as drv_canfdspi_api.h and drv_canfdspi_register.h, which encapsulate macro definitions, SPI protocol abstractions, and CAN FD controller registers.

  • Source Files such as drv_canfdspi_api.c and drv_spi.c, which implement the functional logic for SPI communication and CAN frame handling.

The documentation encourages reproducibility and transparency in the development process by creating a well-organized list of necessary files in Table 3. This kind of transparency is essential, especially when transferring code between platforms, when compiler compatibility and inherited dependencies can pose significant difficulties.

Furthermore, the author accurately notes how crucial it is to eliminate unnecessary files that were inadvertently included in the initial PIC32-based project. These could make reference to peripheral drivers, hardware modules, or platform-specific headers that the PIC18 architecture does not allow. Runtime instability, duplicated code, and compilation issues may result from improperly commenting out or removing these elements. Therefore, it makes sense to remark import statements rather than just removing them, which keeps the option intact and enables future developers to comprehend the code lineage.

Data types

The reconciliation of undefined or incompatible data types between architectures is a critical component of cross-platform driver adaption that is covered in this section. Since the PIC32MX470 operates in a 32-bit environment and the PIC18F4520 is an 8-bit microcontroller, discrepancies in data type declarations can lead to significant compilation errors and runtime inconsistencies if not properly managed.

Data types definition. Source
Data types definition. Source

To fill this gap, the developer explicitly defines standard fixed-width data types like uint32_t, uint16_t, and uint8_t using native types (unsigned long, unsigned int, unsigned char, etc.) compatible with the MPLAB C18 compiler for PIC18 devices The drv_canfdspi_defines.h file contains all of these type definitions, allowing for modular reuse and maintainability throughout the driver source files.

Additionally, because C18 lacks a native Boolean type, developers define bool as an alias for unsigned char to enhance readability in conditionals. This structured type definition enables the driver code—originally developed for a more advanced processor—to compile and run reliably on the simpler PIC18 platform without requiring major logic modifications.

Making a local declaration

Local variables declaration. Source
Local variables declaration. Source

Failure to follow this rule in the C18 environment results in syntax errors, which can hinder compilation and disrupt program logic. As a corrective measure, the developer must manually refactor the code, relocating all local variable declarations to the top of each function body before any executable statements. This stylistic constraint, although archaic by contemporary C standards, reflects the limitations of older ANSI C compliance used in C18 and must be adhered to for successful compilation.

Splitting the message

In Embedded C CAN FD project this section addresses one of the core architectural challenges in porting software from a 32-bit to an 8-bit microcontroller—the handling of bit fields and data structures that exceed the target architecture’s native word size. Since the PIC18F4520 operates on an 8-bit word length, it cannot natively accommodate bit fields or structure members larger than 8 bits, which are common in codebases optimized for 32-bit systems like the PIC32MX470.

To resolve this incompatibility, it becomes necessary to restructure complex data types by splitting large members into smaller fields that are each ≤ 8 bits. This ensures that memory alignment, data access, and pointer arithmetic behave predictably within the constraints of the 8-bit environment. The required changes are applied within the drv_canfdspi_defines.h header file, where many of these bit fields are originally defined.

Splitting the message
Splitting the message

This section focuses on adapting union structures for the PIC18F4520, which cannot handle bit fields wider than 8 bits. In the original code, 12-bit fields—like UserAddress—must be split into smaller parts (e.g., UserAddress1 and UserAddress2) to fit the 8-bit architecture.

Structure type modification example. Source
Structure type modification example. Source

The modification ensures compatibility with the C18 compiler while preserving access to register data via full-word or byte-level views. Although this resolves syntax issues, functional testing is still required to confirm that the new structure behaves identically to the original.

New SPI

This section outlines the reengineering of the SPI communication layer necessitated by the architectural downgrade from the PIC32, which supports advanced SPI abstraction layers, to the PIC18F4520, a resource-constrained 8-bit microcontroller. The original SPI driver, tailored for multi-peripheral environments and designed to interface with more sophisticated hardware, proved to be overly complex and incompatible with the minimalist peripheral model of the PIC18.

Given that the PIC18 features only a single SPI module, the need for peripheral indexing and dynamic slave selection is entirely obviated. Consequently, the driver is reduced to a minimalist, hardware-near implementation leveraging the built-in C18 library functions: OpenSPI for module initialization, and WriteSPI/ReadSPI for synchronous data transactions. This reduction removes redundant abstractions and aligns with the architectural simplicity of the PIC18.

The SPI_CS macro is employed to manually manage the Chip Select line, with a binary logic—1 indicating SPI bus engagement—serving as the only necessary control mechanism. Furthermore, code related to dynamic slave addressing is eliminated, since only a single slave device (the MCP2517FD) exists in the system.

This tailored SPI configuration reflects a deliberate downscaling of software complexity to meet hardware limitations, ensuring deterministic behavior, lower memory overhead, and improved execution efficiency. Such adaptations are essential when retrofitting sophisticated communication stacks onto microcontrollers with limited computational resources and peripheral depth.

Memory Usage

This section in Embedded C CAN FD project outlines the practical constraints encountered while porting the CAN FD driver to the memory-limited PIC18F4520 and the optimizations required to accommodate the firmware within the available ROM and RAM space. The transition from a PIC32—equipped with significantly greater memory resources—to an 8-bit PIC18 necessitated a careful reallocation of code and selective feature removal.

To mitigate the RAM limitations, static data was strategically relocated to Read-Only Memory (ROM), thereby freeing volatile memory for essential runtime operations. This memory management strategy is particularly important in embedded systems where dynamic memory allocation is either limited or discouraged.

Additionally, the source code was pruned by eliminating all superfluous API functions—those not directly contributing to the project’s objectives. This not only reduced the memory footprint but also simplified the codebase, improving maintainability and build performance. A complete list of retained functions is referenced in Annex 1, demonstrating a clear boundary between core functionality and auxiliary components.

These measures collectively enabled the successful integration of main.c, highlighting a critical aspect of embedded development: efficient memory budgeting in resource-constrained environments.

SPI Instructions

This portion of the text delves into the low-level mechanics of SPI communication between the PIC18F4520 and the MCP2517FD CAN FD controller. The interaction with both Special Function Registers (SFRs) and RAM via SPI requires strict adherence to timing and protocol specifications dictated by the MCP2517FD datasheet.

To enable read/write operations over SPI, standard library functions ReadSPI and WriteSPI are employed, encapsulating the physical layer signaling and clock synchronization. Access to SFRs demands that the controller first enter Configuration Mode, ensuring the stability of control registers during modification. In contrast, RAM access is word-oriented, mandating that data be read or written in 4-byte-aligned chunks, which is typical for memory-mapped device buffers in embedded protocols.

Each SPI transaction is framed by asserting and de-asserting the nCS (Chip Select) line—active low—to bracket the instruction. The command phase involves shifting a 4-bit command and a 12-bit address into the controller, followed by either writing to or reading from the data bus, depending on the instruction type. Data direction is determined by the clock edge: writes occur on the rising edge of SCK, and reads on the falling edge, as per SPI mode configuration.

To maintain protocol integrity, all SPI routines were modified to correctly implement these signal transitions and framing conventions. This low-level handling ensures deterministic, hardware-compliant SPI access, which is critical for successful communication with the MCP2517FD.

The SPI instructions used in this project are the following:
• DRV_CANFDSPI_Reset
• DRV_CANFDSPI_ReadByte
• DRV_CANFDSPI_WriteByte
• DRV_CANFDSPI_ReadWord
• DRV_CANFDSPI_WriteWord
• DRV_CANFDSPI_ReadHalfWord
• DRV_CANFDSPI_WriteHalfWord
• DRV_CANFDSPI_ReadByteArray
• DRV_CANFDSPI_WriteByteArray
• DRV_CANFDSPI_ReadWordArray
• DRV_CANFDSPI_WriteWordArray

Following there is one example of the modified code:

SPI instruction modification example. Source
SPI instruction modification example. Source

Linking structs and unions

This section in Embedded C CAN FD project addresses the architectural adaptation required when working with composite data types—namely structures and unions—in the context of the PIC18’s 8-bit word architecture. The core challenge lies in the inherent mismatch between the original codebase, developed for a 32-bit system, and the memory and data alignment constraints of the PIC18 microcontroller.

To reconcile this mismatch, developers must deconstruct large structures and unions into byte-sized components that conform to the 8-bit data path. This splitting operation ensures that no single field exceeds the word size of the PIC18, thereby preventing overflow, misalignment, or undefined behavior during register or memory access.

After decomposition, developers must logically reconstruct the original data structures to preserve semantic integrity. This typically requires carefully reassembling bit fields or multi-byte registers into meaningful entities before using them in application logic or transmitting them via communication protocols.

Union data type

This section outlines a critical aspect of adapting low-level register mappings to an 8-bit architecture, focusing on the transformation of union-based structures originally designed for 32-bit systems. The modification involves redefining bit fields in the REG_CiFIFOUA union within the drv_canfdspi_register.h file to ensure compatibility with the PIC18’s limited word width.

Union type modification
Union type modification

The original union contains a 12-bit field (UserAddress) and an unimplemented 20-bit padding. However, the C18 compiler for PIC18 does not reliably support non-byte-aligned bit fields, making such a layout prone to data misalignment and compiler misinterpretation. To mitigate this, the revised union disaggregates UserAddress into two fields: UserAddress1 (8 bits) and UserAddress2 (4 bits), followed by appropriately adjusted unimplemented padding fields that align to byte boundaries.

This restructuring ensures that all bit fields are multiples of 8 bits, thereby avoiding data overlapping and maintaining compatibility with the PIC18 memory alignment constraints. However, this structural change introduces a functional limitation: the original UserAddress field no longer exists, causing references to it in the API to fail. To preserve functional parity, the value must be reconstructed manually by combining UserAddress1 and UserAddress2 using logical operations (e.g., bit shifting and masking).

UserAddress call.
UserAddress call.
Structured data types

This section delves into the structural realignment of bit fields within CAN_FILTEROBJ_ID, a data structure essential for configuring CAN filter objects. Originally designed for a 32-bit microcontroller, the structure relies on tightly packed bit fields that exceed the handling capabilities of the PIC18’s 8-bit architecture and the C18 compiler’s limited bit-field support.

Structure type modification.
Structure type modification.

In the original implementation, fields such as SID (11 bits) and EID (18 bits) are contiguous, with minimal padding and implicit byte alignment. However, the C18 compiler cannot reliably manage non-byte-aligned bit fields, particularly those crossing byte boundaries. Consequently, the structure must be refactored into smaller, byte-sized fields (SIDA, EIDA, EIDB, etc.) to ensure alignment and compatibility.

The modified version introduces granular fragmentation of the extended and standard identifier fields (EID and SID, respectively), distributing their bits across multiple explicitly declared fields (EIDA, EIDB, EIDC, SIDB, etc.). This not only preserves the overall bit width but also aligns the structure with the 8-bit word constraints of the PIC18F4520.

A key functional implication of this transformation is that, unlike previous cases involving unimplemented fields, the modified structure interacts directly with hardware registers via the API. As such, bit field reconstruction becomes mandatory during runtime. Specifically, the integrity and semantic correctness of transmitted or filtered CAN IDs must be preserved when interfacing with the following driver functions:

  • DRV_CANFDSPI_TransmitChannelLoad

  • DRV_CANFDSPI_FilterObjectConfigure

  • DRV_CANFDSPI_FilterMaskConfigure

Failure to recompose the identifiers in the correct bitwise order could result in improper frame matching, invalid message filtering, or communication faults on the CAN bus.

Structure bit fields put together in order. Source:
Structure bit fields put together in order. Source:

RESULTS

Once the system is ready it is mandatory to do several tests in order to proof that it works properly.

SPI Instructions Tests

This section emphasizes the foundational importance of validating the SPI communication layer before higher-level CAN functionalities are introduced. Given that the entire communication protocol stack relies on accurate read/write access to the MCP2517FD’s RAM and Special Function Registers (SFRs), any fault at the SPI level would propagate system-wide, rendering CAN configuration and data transmission infeasible.

The decision to decouple SPI validation from the broader CAN subsystem configuration reflects a modular verification approach—a standard practice in embedded systems engineering. By isolating and testing SPI routines independently, developers can detect hardware misconfigurations, signal integrity issues, or protocol mismatches at the lowest level, thereby de-risking subsequent integration phases.

Test WriteByte & ReadByte

Using the code shown in Figure 7, the following SPI instructions are tested:
• DRV_CANFDSPI_Reset
• DRV_CANFDSPI_WriteByte
• DRV_CANFDSPI_ReadByte

WriteByte & ReadByte test code. Source
WriteByte & ReadByte test code. Source

Results:

Results of the WriteByte & ReadByte test. Source
Results of the WriteByte & ReadByte test. Source

CAN TESTS

Configuration

To ensure proper operation, the CAN FD controller module must be configured correctly. This configuration is primarily implemented in the main.c file. Most settings require entering Configuration Mode.

Reset
  • The MCP2517FD should be reset to its initial values to avoid using unintended settings.

  • Resetting automatically puts the device into Configuration Mode.

  • In this mode:

    • The controller does not access the CAN bus, reducing the chance of interference.

    • Some features, like FIFOs and the oscillator, can only be set in this mode.

Initialize RAM
  • RAM must be initialized and filled with a selected value before use.

CAN Configuration
  • CRC Settings

    • Supports both ISO CRC and non-ISO CRC.

    • Use the ISOCREN bit to enable/disable ISO CRC.

  • Memory Allocation:

    • Reserve RAM for TEF (Transmit Event FIFO) and TXQ (Transmit Queue) using the STEF and TXQEN bits.

Set Up TX and RX FIFOs
  • Transmit and Receive FIFOs are stored in RAM.

  • Configure:

    • Number of message objects

    • Payload size

  • These settings determine the RAM layout of the message objects.

 Filter & Mask Configuration
  • Disabling filters is required before configuring them. Configuration mode is not needed for this step.

  • After configuration, link each filter to a FIFO where matching messages will be stored.

Filter vs. Mask:

  • Mask: Defines which bits are relevant for comparison.

  • Filter: Specifies the conditions messages must meet to pass through.

 Bit Time Configuration
  • CAN FD allows two bit rates:

    • Nominal Bit Rate (NBR): Used during arbitration; inverse of Nominal Bit Time (NBT).

    • Data Bit Rate (DBR): Used for data transfer.

  • Transmitter Delay Compensation (TDC):

    • Enables faster data phase bit time than the transceiver loop delay.

    • Uses a Secondary Sample Point (SSP), which can be automatically calculated.

  • Recommended CAN clock frequencies: 20 MHz or 40 MHz.

Mode Selection

Aside from Configuration Mode, two modes are used in this project:

  1. CAN FD Normal Mode:

    • Allows both transmission and reception in CAN FD mode.

    • Supports bit rate switching and payloads up to 64 bytes.

  2. CAN FD LoopBack Mode

    • Used for debugging.

    • Specifically, External LoopBack Mode is used:

      • Transmit signals are internally connected to receive.

      • Messages appear on the TXCAN pin for monitoring.

The next example shows how to configure the MCP2517FD:

CAN configuration code example. Source: Own
CAN configuration code example. Source: Own

Loop-Back mode tests

As previously mentioned, LoopBack mode allows the CAN FD controller to receive messages that it has transmitted itself. This makes it an ideal method for performing initial tests on the CAN system without requiring a complete CAN network.

To validate the functionality of the system, several variables will be systematically changed in each test. These key variables include:

  • DLC (Data Length Code): Determines the number of bytes in the data field.

  • Txd: The variable holding the data to be transmitted.

  • FIFO Size: Specifies the number of FIFO message buffers.

  • IDE (Identifier Extension): Indicates whether the message uses a standard or extended identifier.

  • Mask & Filter: Used to control which messages are received; some messages may be ignored or only partially received depending on the settings.

Test 1

Table 14 shows the variable values that will be used for the Test 1.

Test 1 variable values
Test 1 variable values
Results
Test 1 results
Test 1 results

Normal mode tests with CAN sniffer

Once the system is verified to function correctly in Loop-Back mode, it becomes feasible to switch to CAN FD Normal Mode for real communication over a physical CAN FD network.

To validate system performance in real conditions, the following measures will be taken:

  • A CAN FD sniffer will be used to monitor transmitted and received messages.

    • If the observed behavior matches expectations, it can be concluded that the system is functioning correctly.

  • An oscilloscope will be employed to verify voltage levels on the CAN bus:

    • Both CAN_H (CAN High) and CAN_L (CAN Low) signals will be observable.

    • The CAN FD frame will be visibly represented, allowing visual confirmation of signal integrity.

  • During these tests, both the arbitration bit time and data bit time will be modified to observe system response and ensure correct operation at different speeds.

  • The overall test structure will follow the same methodology as the LoopBack mode tests, ensuring consistency and comparability in the results.

    Assembling of the system. Source: Own.
    Assembling of the system. Source: Own.
Test 1

Table 20 shows the variable values that will be used for the Test 1.

Test 1 variable values. Source
Test 1 variable values. Source

As shown in Figure 30, the CAN FD frame is clearly visible. The figure illustrates the difference in bit rates between  arbitration phase and the payload phase, which is a key feature of CAN FD. In this example, the payload size is 8 bytes.

Test 1 voltage levels. Source
Test 1 voltage levels. Source

Results

In Figure 31 it can be seen that the message sent through the real CAN FD network is the expected. Therefore, the system works properly.

Test 1 results.
Test 1 results.

Commentary on “Conclusions and Future Work”

The conclusion effectively affirms the successful realization of the project’s principal goal—the implementation of a functional Embedded C CAN FD project  capable of both transmitting and receiving data within a real CAN network. This achievement not only demonstrates technical competence but also confirms the feasibility of utilizing the PIC18 microcontroller in CAN FD applications.

However, the authors appropriately acknowledge the project’s preliminary nature. The current implementation is limited to core functionalities, suggesting ample room for refinement and feature expansion. This self-awareness marks a valuable understanding of the iterative nature of embedded system design.

The proposed future enhancements reflect a thoughtful and technically grounded progression:

  • Expansion to TEF and Queue Usage: As noted, only basic FIFO structures were utilized in the initial design. Incorporating Transmit Event FIFOs (TEF) and Transmit/Receive Queues (TxQ/RxQ) would introduce greater flexibility and control in message handling, aligning the system with more complex real-world applications.

  • Interrupt Handling: The absence of interrupt-driven logic represents a significant limitation. Given the CAN protocol’s hallmark for reliability through error detection, integrating interrupts would not only enhance responsiveness but also pave the way for low-power and real-time applications.

  • Error Detection Enhancements: Although CRC mechanisms are inherently part of the CAN FD specification, explicitly implementing and verifying Cyclic Redundancy Check (CRC) handling would reinforce the robustness of the node, especially in noisy or high-load networks.

  • Mode Diversity: Currently, the node operates only in Normal and LoopBack modes. Since the MCP2517FD controller supports additional operational modes (e.g., Listen-Only, Sleep, Restricted Operation), future work could explore these to broaden system applicability and efficiency, particularly in diagnostics or power-constrained environments.

Finally, the authors correctly highlight that beyond the primary deliverable, several secondary outcomes were achieved. These include a deeper comprehension of the CAN protocol, practical experience with MPLAB, and enhanced proficiency in embedded C programming—all of which are critical competencies in the field of embedded systems engineering.

Read more: CAN FD Node based on a PIC18 Microcontroller

Quick Solutions to Questions related to Embedded C CAN FD project:

  • What is the main goal of the project?
    To build an Embedded C CAN FD node using the MCP2517FD Click and PIC18F4520 that can send and receive CAN and CAN FD frames.
  • Can the PIC18F4520 be used for CAN FD despite being an 8-bit MCU?
    Yes; the project demonstrates adapting a PIC32-based driver to the PIC18F4520 and implementing SPI-based communication to the MCP2517FD.
  • How is the MCP2517FD interfaced to the PIC18F4520?
    Via an SPI interface using SCK, MOSI, MISO, and a chip select (nCS) line, with Read/Write SPI routines implemented.
  • Does the project modify hardware of the MCP2517FD Click or PIC18F4520?
    No; the scope is software/firmware only with no hardware modifications.
  • What tests validate SPI communication with the MCP2517FD?
    WriteByte and ReadByte SPI instruction tests (including DRV_CANFDSPI_Reset, DRV_CANFDSPI_WriteByte, DRV_CANFDSPI_ReadByte) are performed to validate SPI.
  • How is CAN FD functionality initially verified?
    Using External LoopBack mode to transmit and receive the node's own messages for early validation before real bus tests.
  • What tools are used to validate the node on a real CAN FD network?
    A CAN FD sniffer to monitor messages and an oscilloscope to observe CAN_H and CAN_L voltage waveforms.
  • How does the project handle data structures incompatible with 8-bit architecture?
    Large bit fields and unions are split into byte-sized fields and reassembled in software (e.g., splitting a 12-bit UserAddress into two fields).
  • What firmware changes were needed for PIC18 compatibility?
    Define fixed-width types for C18, move local variable declarations to function tops, refactor bitfields/unions, simplify SPI driver, and relocate static data to ROM to save RAM.
  • What future improvements does the article suggest?
    Adding TEF and queue usage, interrupt-driven handling, enhanced error detection (CRC verification), and exploring additional MCP2517FD modes like Listen-Only and Sleep.

About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:
LinkedinTwitter