A working demonstration on how to read GMLAN packets using an mbed and a compatible CAN transceiver such as (and tested with) the CAN-Bus demo board. The SparkFun CAN Shield should also work perfectly too, as should just about every MCP2551-based solution (but this code should be portable to other transceivers). Please note to get this to work, you must tie CAN_L to ground and connect CAN_H to the single wire CAN.

Dependencies:   mbed

GMLAN Sniffer

Introduction

This project makes use of CAN on an LPC1768 to communicate with General Motors GMLAN network via a compatible transceiver. GMLAN is a single wire CAN Bus that operates at 33.333 kbit with 29-bit header packets and is commonly used for transmission of non-critical information between such nodes on automobiles as the following;

  • Dash cluster
  • Entertainment system (head unit)
  • Satellite Navigation (OnStar for example)
  • HVAC controls
  • Immobiliser / alarm / other security systems
  • Door locks and door status
  • Power Windows
  • Interior / exterior lighting
  • Reversing sensors

The list is extensive, for a better idea of what can be done, view the ARBIDs tab on the GMLAN Bible Google Docs spreadsheet (tabs are at the bottom of the page).

Hardware setup

This is just one example of how you can interface with GMLAN using an SKPang CAN-Bus Breakout Board (based around an MCP2551 CAN Transceiver), using these instructions I assembled the following on my trusty prototyping board;

/media/uploads/foxdie/_scaled_mbed-canbus-layout.jpg

(Click to open high resolution version)

Committer:
foxdie
Date:
Thu Dec 06 22:36:10 2012 +0000
Revision:
4:e40a05b32518
Parent:
3:ce56713e4201
Child:
5:f9107433b66a
Commented code to help assist others in future

Who changed what in which revision?

UserRevisionLine numberNew contents of line
foxdie 0:f08f63171361 1 #include "mbed.h"
foxdie 0:f08f63171361 2
foxdie 0:f08f63171361 3 DigitalOut rx_led(LED1);
foxdie 0:f08f63171361 4 Serial pc(USBTX, USBRX);
foxdie 0:f08f63171361 5 CAN gmlan(p30, p29);
foxdie 0:f08f63171361 6
foxdie 0:f08f63171361 7 void clearAndHome()
foxdie 0:f08f63171361 8 {
foxdie 0:f08f63171361 9 pc.printf("%c", 27); // ESC
foxdie 0:f08f63171361 10 pc.printf("[2J"); // clear screen
foxdie 0:f08f63171361 11 pc.printf("%c", 27); // ESC
foxdie 0:f08f63171361 12 pc.printf("[H"); // cursor to home
foxdie 0:f08f63171361 13 }
foxdie 0:f08f63171361 14
foxdie 1:3daf1c9b3315 15 void processMessage()
foxdie 1:3daf1c9b3315 16 {
foxdie 4:e40a05b32518 17 // Get system time and turn on rx_led to indicate we are receiving data
foxdie 1:3daf1c9b3315 18 time_t seconds = time(NULL);
foxdie 1:3daf1c9b3315 19 rx_led = 1;
foxdie 4:e40a05b32518 20
foxdie 4:e40a05b32518 21 // Create a CANMessage object and read the buffer into it
foxdie 1:3daf1c9b3315 22 CANMessage rxmsg;
foxdie 1:3daf1c9b3315 23 gmlan.read(rxmsg);
foxdie 4:e40a05b32518 24
foxdie 4:e40a05b32518 25 // Output to the USB serial device formatted data, walking through and formatting each packet
foxdie 4:e40a05b32518 26 // http://www.cplusplus.com/reference/cstdio/printf/ is a useful resource to describe printf
foxdie 1:3daf1c9b3315 27 pc.printf("[%10d]\t[%d]\t[0x%08X]\t", seconds, rxmsg.len, rxmsg.id);
foxdie 1:3daf1c9b3315 28 for (unsigned int i = 0; i < rxmsg.len; i++)
foxdie 1:3daf1c9b3315 29 pc.printf("%02X ", rxmsg.data[i]);
foxdie 1:3daf1c9b3315 30 pc.printf("\r\n");
foxdie 4:e40a05b32518 31
foxdie 4:e40a05b32518 32 // Turn off our rx_led as we have finished reading data
foxdie 1:3daf1c9b3315 33 rx_led = 0;
foxdie 1:3daf1c9b3315 34 }
foxdie 1:3daf1c9b3315 35
foxdie 0:f08f63171361 36 int main() {
foxdie 2:a285b70981c6 37 // Reset uptime timer and set serial baud rate to 115kbit
foxdie 1:3daf1c9b3315 38 set_time(0);
foxdie 0:f08f63171361 39 pc.baud(115200);
foxdie 0:f08f63171361 40
foxdie 2:a285b70981c6 41 // Set CANBUS to 33.3kbit and put into monitor mode (does not ACK packets, aka stealth mode)
foxdie 2:a285b70981c6 42 int baudrate = 33333;
foxdie 2:a285b70981c6 43 gmlan.frequency(baudrate);
foxdie 0:f08f63171361 44 gmlan.monitor(true);
foxdie 0:f08f63171361 45
foxdie 2:a285b70981c6 46 // Clear serial terminal and start capturing packets
foxdie 0:f08f63171361 47 clearAndHome();
foxdie 0:f08f63171361 48 pc.printf("Starting packet capture at %i bps\r\n", baudrate);
foxdie 1:3daf1c9b3315 49 gmlan.attach(&processMessage);
foxdie 1:3daf1c9b3315 50
foxdie 0:f08f63171361 51 while(1) {
foxdie 2:a285b70981c6 52 // Sleep for 20ms repeatedly, all messages are handled by an interrupt, this prevents keeping the mbed at full load
foxdie 1:3daf1c9b3315 53 wait(0.02);
foxdie 0:f08f63171361 54 }
foxdie 0:f08f63171361 55 }