The library has a ton of functions. A lot of them are complicated and really aren't necessary for normal use. This document explains how to use the library simply and will suffice for most applications. To start with, you'll need to initialize the canbus hardware. There are two Canbus ports on the Due. There are objects already created for each port: Can0 and Can1. All functions below are called on one of those two objects. Note: The library used to use CAN and CAN2 in place of Can0 and Can1. You can still use those other names as they've been maintained as aliases. Where functions have been added the old functions have been left behind so backward compatibility is maintained. Use whichever functions work best for you. init(baudrate) - Initializes the given canbus port with the given baud rate. Sets up for interrupt driven canbus with 7 receive mailboxes and 1 transmit mailbox. You don't need to worry about mailboxes though if you don't want to. Also sets the default enable pin (62 for Can0, 65 for Can1) Example: Can0.init(250000); begin(baudrate) - Exactly like init above. begin(baudrate, enablepin) - Like above two but with addition of an enable pin. The enable pin will be raised high when the relevant canbus port is enabled and sunk low when the relevant port is disabled. If you do not need an enable pin then pass 255. Example: Can0.begin(250000, 62); begin() - Initializes with default settings for both baud and enable (250k baud, enable as above) set_baudrate(baudrate) - Set the baud rate of the canbus. This can be set to anything you'd like (within reason) but the common baud rates are 33333, 125000, 250000, 500000, 1000000. Do not use this unless you are changing the baud rate of an already initialized canbus port. Example: Can0.set_baudrate(500000); enable() - Enable the canbus port. You don't need to call this unless you've disabled the port at some time in the past. Example: Can0.enable(); disable() - Disable the canbus port. You will no longer be able to properly use it. Example: Can0.disable(); Then, it is on to using the newly set-up canbus port: This is the structure you will use for both sending and receiving. typedef struct { uint32_t id; // Can0 be either 11 or 29 bit ID uint32_t fid; // Family ID is a somewhat advanced thing. You Can0 ignore it. uint8_t rtr; // Remote Transmission Request - Don't use this. uint8_t priority; // Priority for TX frames. Probably not that useful normally uint8_t extended;//Set to true for extended frames, false for standard uint8_t length; // Number of data bytes BytesUnion data; // Data bytes } CAN_FRAME; In turn, BytesUnion is a way to access the 8 data bytes in a variety of ways with a variety of names: typedef union { uint64_t value; struct { uint32_t low; uint32_t high; }; struct { uint16_t s0; uint16_t s1; uint16_t s2; uint16_t s3; }; uint8_t bytes[8]; uint8_t byte[8]; //alternate name so you can omit the s if you feel it makes more sense } BytesUnion; int setRXFilter(id, mask, extended) - Set up a filter for incoming frames. This version of the function allows one to forget about mailboxes and just set a filter. It will handle the details for you and return which mailbox it used in case you need to change it later. It returns -1 if there was a problem. Example: Can0.setRXFilter(0x7E0, 0x7E0, false); int setRXFilter(mailbox,id,mask,extended) - The other version of setting a filter. It takes the mailbox to change. So long as you pass a valid mailbox number (0-7) you will get that number back as the return value. It returns -1 on error. Example: Can0.setRXFilter(0, 0x10000, 0x10000, true); int watchFor() - An easy way to allow all traffic through. Will automatically add 1 mailbox for standard frames and 1 for extended frames. Example: Can0.watchFor(); int watchFor(uint32_t id) - Watch for a specific and single ID. Will automatically determine whether to accept extended or standard frames. Example: Can0.watchFor(0x740); int watchFor(uint32_t id, uint32_t mask) - Watch for a group of IDs based on ID and a mask. Also uses automatic determination of extended/standard. Example: Can0.watchFor(0x620, 0x7F0); //Watch for a range of ids from 0x620 to 0x62F int watchForRange(uint32_t id1, uint32_t id2) - A potentially much easier routine. Pass the lowest and highest IDs you want to accept and it will automatically determine a suitable ID and mask to use. It might accept more IDs than what you passed if necessary. Example: Can0.watchForRange(0x620, 0x64F); //Accept frames with IDs from 0x620 to 0x64F int findFreeRXMailbox() - Allows your program to get a free mailbox if you're going to use the above function directly. You shouldn't need to use this very often. Example: mailbox = Can0.findFreeRXMailbox(); setNumTXBoxes(txboxes) - Above it was mentioned that the default setup is to have 7 RX mailboxes and 1 TX mailbox. This should work for 95% of programs because the underlying library code uses interrupts with large buffers. But, if you will only be sending or only receiving or if you otherwise really need to tweak the arrangement you Can0 with this function. This function totally reinitializes all mailboxes so be sure to call this function before you start setting up your filters. Example: Can0.setNumTXBoxes(2); There are two ways to receive canbus frames with this library. You Can0 choose from callback driven reception or buffered frames. Either one is interrupt driven. The choice really comes down to whether you'd like to process frames at a given point in your code or whether you'd like to immediately get a call when a frame comes in. Buffered / Polling version: bool rx_avail() - The actual frame reception code is interrupt driven so you do not need to rapidly poll for incoming frames at risk of losing some. However, it is still handy to know if one or more frames came in. This function returns true if there are received frames waiting to be processed by your program. Example: if (Can0.rx_avail()) //do something here. int available() - Returns the number of waiting frames in the receive buffer. Can be used in place of rx_avail() Example: if (Can0.available() > 0) //do something get_rx_buff(CAN_FRAME &) - Read a waiting frame into the variable passed to the function. Example: CAN_FRAME myFrame; if (Can0.rx_avail()) get_rx_buff(myFrame); read(CAN_FRAME &) - Exactly like get_rx_buff but with an easier to remember name. Example: Can0.read(myFrame); Callback version: setCallback(mailbox, cb) - Set a callback function for a mailbox (0-7) Example: void someFunction(Can0_FRAME *frame) { //do something with frame in here } setCallback(3, someFunction); //sets callback for third mailbox setGeneralCallback(cb) - Set a callback that will be used for any mailbox that doesn't have a registered callback Example: Can0.setGeneralCallback(someFunction); void attachCANInterrupt(void (*cb)(CAN_FRAME *)) - Merely an alternative name for setGeneralCallback void attachCANInterrupt(uint8_t mailBox, void (*cb)(CAN_FRAME *)) - An alternative name for setCallback void detachCANInterrupt(uint8_t mailBox) - Removes the handler from the given mailbox. Example: Can0.detachCANInterrupt(0); These calls will not require any polling at all. You will immediately be given any frames that come into the system. However, care must be taken as your callback function will be in interrupt context. Do not do very much work in the callback function. Any frame that was returned via callback will not be buffered and thus will not be available to the buffered system described previously. Frame sending: bool sendFrame(Can0_FRAME&) - Send a frame over canbus. It will try to send immediately but will automatically fall back to buffering the frame and sending via interrupt when the bus frees up. Returns whether it could send a frame (true/false). Only false if the TX buffer fills up for some reason. In that cases you'll have to send frames at a slower rate or check to be sure that the CAN bus is actually operational. Example: CAN_FRAME myFrame; myFrame.id = 45; myFrame.length = 1 myFrame.data[0] = 128; Can0.sendFrame(myFrame); There is an alternative output method now. You can set the ID and then use write to write out frames. This will send one frame per call but can be used to output the value of variables up to 8 bytes in size: void setWriteID(uint32_t id) - Set the ID to use for the write function. Example: Can0.setWriteID(0x620); void setBigEndian(bool) - Set how to output the bytes sent by the write function. The Due is little endian so setting True to this function will cause bytes to be output in reverse order (big endian) Example: Can0.setBigEndian(true); template void write(t inputValue) - Write the given input bytewise into a frame and send it. Uses the ID from the setWriteID function. Immediately tries to send the frame. This function is probably most useful for simple tests as it does not support sending multiple values in the same frame. Example: int SomeValue = 23423; Can0.write(SomeValue);