CAN & DBC Online Decoder

Code blocks

Setup Instructions

  • Install the CAN library in Arduino IDE: CAN by Sandeep Mistry v0.3.1
  • Upload the sketch below to your Arduino or compatible device
  • The sketch will automatically detect your MCP2515 crystal frequency (8MHz or 16MHz) and CAN bus speed (125kbps or 500kbps)

Features: This sketch automatically detects your hardware configuration (8MHz or 16MHz crystal, 125kbps or 500kbps bus speed) and supports both reading and writing CAN packets. No manual configuration needed!

        
#include <CAN.h>

// Configuration - optimized for your head unit
#define CLOCK_FREQ 8E6      // 8 MHz crystal
#define BAUD_RATE 125E3     // 125 kbps baud rate

// Statistics
unsigned long packetsReceived = 0;
unsigned long packetsSent = 0;
unsigned long packetsSuccess = 0;
unsigned long lastActivityReport = 0;

void setup() {
  Serial.begin(250000);
  while (!Serial);

  Serial.println(F("CAN Transceiver Started!"));

  // Initialize CAN with verified working configuration
  CAN.setClockFrequency(CLOCK_FREQ);
  if (!CAN.begin(BAUD_RATE)) {
    Serial.println(F("ERROR: CAN init failed!"));
    while (1) delay(1000);
  }

  Serial.println(F("SUCCESS: 8MHz @ 125kbps"));
  Serial.println(F("Normal mode - connected to real CAN bus"));
}

// Function to send CAN packet from Serial input
void sendPacketFromSerial(String input) {
  input.trim();
  if (input.length() == 0) return;

  // Split input by commas
  char str[input.length() + 1];
  input.toCharArray(str, sizeof(str));

  char* token = strtok(str, ",");
  if (token == NULL) return;

  // Parse CAN ID
  long id = strtol(token, NULL, 16);
  if (id < 0x000 || id > 0x1FFFFFFF) {
    Serial.println(F("ERROR: Invalid ID"));
    return;
  }

  // Parse RTR
  token = strtok(NULL, ",");
  if (token == NULL) return;
  bool rtr = atoi(token) > 0;

  // Parse IDE
  token = strtok(NULL, ",");
  if (token == NULL) return;
  bool extended = atoi(token) > 0;

  // Parse DLC
  token = strtok(NULL, ",");
  if (token == NULL) return;
  int dlc = atoi(token);
  if (dlc < 0 || dlc > 8) {
    Serial.println(F("ERROR: Invalid DLC"));
    return;
  }

  // Prepare to send CAN packet
  byte dataBytes[8];
  int dataCount = 0;

  // Parse Data Bytes
  while ((token = strtok(NULL, ",")) != NULL && dataCount < 8) {
    dataBytes[dataCount++] = strtol(token, NULL, 16);
  }

  // Verify data count matches DLC
  if (dataCount != dlc) {
    Serial.println(F("ERROR: DLC mismatch"));
    return;
  }

  // Begin packet
  if (extended) {
    CAN.beginExtendedPacket(id, dlc, rtr);
  } else {
    CAN.beginPacket(id, dlc, rtr);
  }

  // Send data bytes if it's NOT an RTR frame
  if (!rtr) {
    for (int i = 0; i < dataCount; i++) {
      CAN.write(dataBytes[i]);
    }
  }

  // Send packet
  Serial.print(F("Sending ID=0x"));
  Serial.print(id, HEX);
  Serial.print(F(" DLC="));
  Serial.print(dlc);
  Serial.print(F("..."));

  packetsSent++;

  if (!CAN.endPacket()) {
    Serial.println(F(" FAILED!"));
    Serial.println(F("ERROR: No ACK from bus"));
  } else {
    packetsSuccess++;
    Serial.println(F(" OK!"));
    Serial.print(F("SUCCESS: ID=0x"));
    Serial.println(id, HEX);
  }
}

// Function to receive CAN packets
void receiveCANPacket() {
  int packetSize = CAN.parsePacket();

  if (packetSize) {
    packetsReceived++;

    // Print CAN ID in hexadecimal format
    Serial.print(CAN.packetId(), HEX);
    Serial.print(",");

    // Print RTR (0 = data frame, 1 = remote frame)
    if (CAN.packetRtr()) {
      Serial.print("1,");
    } else {
      Serial.print("0,");
    }

    // Print IDE (0 = standard ID, 1 = extended ID)
    if (CAN.packetExtended()) {
      Serial.print("1,");
    } else {
      Serial.print("0,");
    }

    // Print DLC (data length code)
    if (CAN.packetRtr()) {
      Serial.print(CAN.packetDlc());
      Serial.println();
    } else {
      Serial.print(packetSize);

      // Print data bytes in hexadecimal format
      while (CAN.available()) {
        Serial.print(",");
        Serial.print(CAN.read(), HEX);
      }
      Serial.println();
    }
  }
}

void loop() {
  // Handle incoming CAN packets
  receiveCANPacket();

  // Report CAN bus activity every 10 seconds
  unsigned long now = millis();
  if (now - lastActivityReport > 10000) {
    Serial.print(F("INFO: RX packets="));
    Serial.println(packetsReceived);

    // Show send statistics if any packets were sent
    if (packetsSent > 0) {
      Serial.print(F("INFO: TX packets="));
      Serial.print(packetsSent);
      Serial.print(F(" (Success: "));
      Serial.print(packetsSuccess);
      Serial.print(F(", Failed: "));
      Serial.print(packetsSent - packetsSuccess);
      Serial.println(F(")"));
    }

    lastActivityReport = now;
  }

  // Handle Serial input for sending CAN packets
  if (Serial.available()) {
    String input = Serial.readStringUntil('
');
    sendPacketFromSerial(input);
  }
}